]> git.pld-linux.org Git - packages/kernel.git/blob - 0012-apparmor-add-base-infastructure-for-socket-mediation.patch
- 4.14.1
[packages/kernel.git] / 0012-apparmor-add-base-infastructure-for-socket-mediation.patch
1 From 853cbdfb6924857a2ee2a1cd5b9fa494f8e7efa2 Mon Sep 17 00:00:00 2001
2 From: John Johansen <john.johansen@canonical.com>
3 Date: Tue, 18 Jul 2017 23:18:33 -0700
4 Subject: [PATCH 12/17] apparmor: add base infastructure for socket mediation
5
6 Provide a basic mediation of sockets. This is not a full net mediation
7 but just whether a spcific family of socket can be used by an
8 application, along with setting up some basic infrastructure for
9 network mediation to follow.
10
11 the user space rule hav the basic form of
12   NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ]
13                  [ TYPE | PROTOCOL ]
14
15   DOMAIN = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' |
16              'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' |
17              'netbeui' | 'security' | 'key' | 'packet' | 'ash' |
18              'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' |
19              'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' |
20              'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' |
21              'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' |
22              'vsock' | 'mpls' | 'ib' | 'kcm' ) ','
23
24   TYPE = ( 'stream' | 'dgram' | 'seqpacket' |  'rdm' | 'raw' |
25            'packet' )
26
27   PROTOCOL = ( 'tcp' | 'udp' | 'icmp' )
28
29 eg.
30   network,
31   network inet,
32
33 Signed-off-by: John Johansen <john.johansen@canonical.com>
34 Acked-by: Seth Arnold <seth.arnold@canonical.com>
35 (cherry picked from commit 56387cbe3f287034ee6959cb9e8f419889e38bd9)
36 ---
37  security/apparmor/.gitignore       |   1 +
38  security/apparmor/Makefile         |  43 ++++-
39  security/apparmor/apparmorfs.c     |   1 +
40  security/apparmor/file.c           |  30 +++
41  security/apparmor/include/audit.h  |  26 ++-
42  security/apparmor/include/net.h    | 114 +++++++++++
43  security/apparmor/include/perms.h  |   5 +-
44  security/apparmor/include/policy.h |  13 ++
45  security/apparmor/lib.c            |   5 +-
46  security/apparmor/lsm.c            | 387 +++++++++++++++++++++++++++++++++++++
47  security/apparmor/net.c            | 184 ++++++++++++++++++
48  security/apparmor/policy_unpack.c  |  47 ++++-
49  12 files changed, 840 insertions(+), 16 deletions(-)
50  create mode 100644 security/apparmor/include/net.h
51  create mode 100644 security/apparmor/net.c
52
53 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
54 index 9cdec70d72b8..d5b291e94264 100644
55 --- a/security/apparmor/.gitignore
56 +++ b/security/apparmor/.gitignore
57 @@ -1,5 +1,6 @@
58  #
59  # Generated include files
60  #
61 +net_names.h
62  capability_names.h
63  rlim_names.h
64 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
65 index 81a34426d024..dafdd387d42b 100644
66 --- a/security/apparmor/Makefile
67 +++ b/security/apparmor/Makefile
68 @@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
69  
70  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
71                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
72 -              resource.o secid.o file.o policy_ns.o label.o mount.o
73 +              resource.o secid.o file.o policy_ns.o label.o mount.o net.o
74  apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
75  
76 -clean-files := capability_names.h rlim_names.h
77 +clean-files := capability_names.h rlim_names.h net_names.h
78  
79 +# Build a lower case string table of address family names
80 +# Transform lines from
81 +#    #define AF_LOCAL          1       /* POSIX name for AF_UNIX       */
82 +#    #define AF_INET           2       /* Internet IP Protocol         */
83 +# to
84 +#    [1] = "local",
85 +#    [2] = "inet",
86 +#
87 +# and build the securityfs entries for the mapping.
88 +# Transforms lines from
89 +#    #define AF_INET           2       /* Internet IP Protocol         */
90 +# to
91 +#    #define AA_SFS_AF_MASK "local inet"
92 +quiet_cmd_make-af = GEN     $@
93 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
94 +       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
95 +        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
96 +       echo "};" >> $@ ;\
97 +       printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
98 +       sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
99 +        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
100 +        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
101 +
102 +# Build a lower case string table of sock type names
103 +# Transform lines from
104 +#    SOCK_STREAM       = 1,
105 +# to
106 +#    [1] = "stream",
107 +quiet_cmd_make-sock = GEN     $@
108 +cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
109 +       sed $^ >>$@ -r -n \
110 +       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
111 +       echo "};" >> $@
112  
113  # Build a lower case string table of capability names
114  # Transforms lines from
115 @@ -61,6 +94,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
116             tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
117  
118  $(obj)/capability.o : $(obj)/capability_names.h
119 +$(obj)/net.o : $(obj)/net_names.h
120  $(obj)/resource.o : $(obj)/rlim_names.h
121  $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
122                             $(src)/Makefile
123 @@ -68,3 +102,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
124  $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
125                       $(src)/Makefile
126         $(call cmd,make-rlim)
127 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
128 +                    $(srctree)/include/linux/net.h \
129 +                    $(src)/Makefile
130 +       $(call cmd,make-af)
131 +       $(call cmd,make-sock)
132 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
133 index 7acea14c850b..125dad5c3fde 100644
134 --- a/security/apparmor/apparmorfs.c
135 +++ b/security/apparmor/apparmorfs.c
136 @@ -2202,6 +2202,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
137         AA_SFS_DIR("policy",                    aa_sfs_entry_policy),
138         AA_SFS_DIR("domain",                    aa_sfs_entry_domain),
139         AA_SFS_DIR("file",                      aa_sfs_entry_file),
140 +       AA_SFS_DIR("network",                   aa_sfs_entry_network),
141         AA_SFS_DIR("mount",                     aa_sfs_entry_mount),
142         AA_SFS_DIR("namespaces",                aa_sfs_entry_ns),
143         AA_SFS_FILE_U64("capability",           VFS_CAP_FLAGS_MASK),
144 diff --git a/security/apparmor/file.c b/security/apparmor/file.c
145 index 3382518b87fa..db80221891c6 100644
146 --- a/security/apparmor/file.c
147 +++ b/security/apparmor/file.c
148 @@ -21,6 +21,7 @@
149  #include "include/context.h"
150  #include "include/file.h"
151  #include "include/match.h"
152 +#include "include/net.h"
153  #include "include/path.h"
154  #include "include/policy.h"
155  #include "include/label.h"
156 @@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
157         return error;
158  }
159  
160 +static int __file_sock_perm(const char *op, struct aa_label *label,
161 +                           struct aa_label *flabel, struct file *file,
162 +                           u32 request, u32 denied)
163 +{
164 +       struct socket *sock = (struct socket *) file->private_data;
165 +       int error;
166 +
167 +       AA_BUG(!sock);
168 +
169 +       /* revalidation due to label out of date. No revocation at this time */
170 +       if (!denied && aa_label_is_subset(flabel, label))
171 +               return 0;
172 +
173 +       /* TODO: improve to skip profiles cached in flabel */
174 +       error = aa_sock_file_perm(label, op, request, sock);
175 +       if (denied) {
176 +               /* TODO: improve to skip profiles checked above */
177 +               /* check every profile in file label to is cached */
178 +               last_error(error, aa_sock_file_perm(flabel, op, request, sock));
179 +       }
180 +       if (!error)
181 +               update_file_ctx(file_ctx(file), label, request);
182 +
183 +       return error;
184 +}
185 +
186  /**
187   * aa_file_perm - do permission revalidation check & audit for @file
188   * @op: operation being checked
189 @@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
190                 error = __file_path_perm(op, label, flabel, file, request,
191                                          denied);
192  
193 +       else if (S_ISSOCK(file_inode(file)->i_mode))
194 +               error = __file_sock_perm(op, label, flabel, file, request,
195 +                                        denied);
196  done:
197         rcu_read_unlock();
198  
199 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
200 index 620e81169659..ff4316e1068d 100644
201 --- a/security/apparmor/include/audit.h
202 +++ b/security/apparmor/include/audit.h
203 @@ -121,21 +121,29 @@ struct apparmor_audit_data {
204                 /* these entries require a custom callback fn */
205                 struct {
206                         struct aa_label *peer;
207 -                       struct {
208 -                               const char *target;
209 -                               kuid_t ouid;
210 -                       } fs;
211 +                       union {
212 +                               struct {
213 +                                       kuid_t ouid;
214 +                                       const char *target;
215 +                               } fs;
216 +                               struct {
217 +                                       int type, protocol;
218 +                                       struct sock *peer_sk;
219 +                                       void *addr;
220 +                                       int addrlen;
221 +                               } net;
222 +                               int signal;
223 +                               struct {
224 +                                       int rlim;
225 +                                       unsigned long max;
226 +                               } rlim;
227 +                       };
228                 };
229                 struct {
230                         struct aa_profile *profile;
231                         const char *ns;
232                         long pos;
233                 } iface;
234 -               int signal;
235 -               struct {
236 -                       int rlim;
237 -                       unsigned long max;
238 -               } rlim;
239                 struct {
240                         const char *src_name;
241                         const char *type;
242 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
243 new file mode 100644
244 index 000000000000..140c8efcf364
245 --- /dev/null
246 +++ b/security/apparmor/include/net.h
247 @@ -0,0 +1,114 @@
248 +/*
249 + * AppArmor security module
250 + *
251 + * This file contains AppArmor network mediation definitions.
252 + *
253 + * Copyright (C) 1998-2008 Novell/SUSE
254 + * Copyright 2009-2017 Canonical Ltd.
255 + *
256 + * This program is free software; you can redistribute it and/or
257 + * modify it under the terms of the GNU General Public License as
258 + * published by the Free Software Foundation, version 2 of the
259 + * License.
260 + */
261 +
262 +#ifndef __AA_NET_H
263 +#define __AA_NET_H
264 +
265 +#include <net/sock.h>
266 +#include <linux/path.h>
267 +
268 +#include "apparmorfs.h"
269 +#include "label.h"
270 +#include "perms.h"
271 +#include "policy.h"
272 +
273 +#define AA_MAY_SEND            AA_MAY_WRITE
274 +#define AA_MAY_RECEIVE         AA_MAY_READ
275 +
276 +#define AA_MAY_SHUTDOWN                AA_MAY_DELETE
277 +
278 +#define AA_MAY_CONNECT         AA_MAY_OPEN
279 +#define AA_MAY_ACCEPT          0x00100000
280 +
281 +#define AA_MAY_BIND            0x00200000
282 +#define AA_MAY_LISTEN          0x00400000
283 +
284 +#define AA_MAY_SETOPT          0x01000000
285 +#define AA_MAY_GETOPT          0x02000000
286 +
287 +#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |    \
288 +                       AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN |   \
289 +                       AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
290 +                       AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
291 +
292 +#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |   \
293 +                     AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
294 +                     AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD |  \
295 +                     AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK |       \
296 +                     AA_MAY_MPROT)
297 +
298 +#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
299 +                      AA_MAY_ACCEPT)
300 +struct aa_sk_ctx {
301 +       struct aa_label *label;
302 +       struct aa_label *peer;
303 +       struct path path;
304 +};
305 +
306 +#define SK_CTX(X) ((X)->sk_security)
307 +#define SOCK_ctx(X) SOCK_INODE(X)->i_security
308 +#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)                                  \
309 +       struct lsm_network_audit NAME ## _net = { .sk = (SK),             \
310 +                                                 .family = (F)};         \
311 +       DEFINE_AUDIT_DATA(NAME,                                           \
312 +                         ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
313 +                                                    LSM_AUDIT_DATA_NONE, \
314 +                         OP);                                            \
315 +       NAME.u.net = &(NAME ## _net);                                     \
316 +       aad(&NAME)->net.type = (T);                                       \
317 +       aad(&NAME)->net.protocol = (P)
318 +
319 +#define DEFINE_AUDIT_SK(NAME, OP, SK)                                  \
320 +       DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type,  \
321 +                        (SK)->sk_protocol)
322 +
323 +/* struct aa_net - network confinement data
324 + * @allow: basic network families permissions
325 + * @audit: which network permissions to force audit
326 + * @quiet: which network permissions to quiet rejects
327 + */
328 +struct aa_net {
329 +       u16 allow[AF_MAX];
330 +       u16 audit[AF_MAX];
331 +       u16 quiet[AF_MAX];
332 +};
333 +
334 +
335 +extern struct aa_sfs_entry aa_sfs_entry_network[];
336 +
337 +void audit_net_cb(struct audit_buffer *ab, void *va);
338 +int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
339 +                      u32 request, u16 family, int type);
340 +int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
341 +              int type, int protocol);
342 +static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
343 +                                       struct common_audit_data *sa,
344 +                                       u32 request,
345 +                                       struct sock *sk)
346 +{
347 +       return aa_profile_af_perm(profile, sa, request, sk->sk_family,
348 +                                 sk->sk_type);
349 +}
350 +int aa_sk_perm(const char *op, u32 request, struct sock *sk);
351 +
352 +int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
353 +                     struct socket *sock);
354 +
355 +
356 +static inline void aa_free_net_rules(struct aa_net *new)
357 +{
358 +       /* NOP */
359 +}
360 +
361 +#endif /* __AA_NET_H */
362 diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
363 index 2b27bb79aec4..af04d5a7d73d 100644
364 --- a/security/apparmor/include/perms.h
365 +++ b/security/apparmor/include/perms.h
366 @@ -135,9 +135,10 @@ extern struct aa_perms allperms;
367  
368  
369  void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
370 -void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
371 +void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
372 +                        u32 mask);
373  void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
374 -                       u32 chrsmask, const char **names, u32 namesmask);
375 +                       u32 chrsmask, const char * const *names, u32 namesmask);
376  void aa_apply_modes_to_perms(struct aa_profile *profile,
377                              struct aa_perms *perms);
378  void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
379 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
380 index 17fe41a9cac3..4364088a0b9e 100644
381 --- a/security/apparmor/include/policy.h
382 +++ b/security/apparmor/include/policy.h
383 @@ -30,6 +30,7 @@
384  #include "file.h"
385  #include "lib.h"
386  #include "label.h"
387 +#include "net.h"
388  #include "perms.h"
389  #include "resource.h"
390  
391 @@ -111,6 +112,7 @@ struct aa_data {
392   * @policy: general match rules governing policy
393   * @file: The set of rules governing basic file access and domain transitions
394   * @caps: capabilities for the profile
395 + * @net: network controls for the profile
396   * @rlimits: rlimits for the profile
397   *
398   * @dents: dentries for the profiles file entries in apparmorfs
399 @@ -148,6 +150,7 @@ struct aa_profile {
400         struct aa_policydb policy;
401         struct aa_file_rules file;
402         struct aa_caps caps;
403 +       struct aa_net net;
404         struct aa_rlimit rlimits;
405  
406         struct aa_loaddata *rawdata;
407 @@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
408         return 0;
409  }
410  
411 +static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
412 +                                              u16 AF) {
413 +       unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
414 +       u16 be_af = cpu_to_be16(AF);
415 +
416 +       if (!state)
417 +               return 0;
418 +       return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
419 +}
420 +
421  /**
422   * aa_get_profile - increment refcount on profile @p
423   * @p: profile  (MAYBE NULL)
424 diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
425 index 08ca26bcca77..8818621b5d95 100644
426 --- a/security/apparmor/lib.c
427 +++ b/security/apparmor/lib.c
428 @@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
429         *str = '\0';
430  }
431  
432 -void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
433 +void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
434 +                        u32 mask)
435  {
436         const char *fmt = "%s";
437         unsigned int i, perm = 1;
438 @@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
439  }
440  
441  void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
442 -                       u32 chrsmask, const char **names, u32 namesmask)
443 +                       u32 chrsmask, const char * const *names, u32 namesmask)
444  {
445         char str[33];
446  
447 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
448 index 4ad0b3a45142..cc5ab23a2d84 100644
449 --- a/security/apparmor/lsm.c
450 +++ b/security/apparmor/lsm.c
451 @@ -33,6 +33,7 @@
452  #include "include/context.h"
453  #include "include/file.h"
454  #include "include/ipc.h"
455 +#include "include/net.h"
456  #include "include/path.h"
457  #include "include/label.h"
458  #include "include/policy.h"
459 @@ -736,6 +737,368 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
460         return error;
461  }
462  
463 +/**
464 + * apparmor_sk_alloc_security - allocate and attach the sk_security field
465 + */
466 +static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
467 +{
468 +       struct aa_sk_ctx *ctx;
469 +
470 +       ctx = kzalloc(sizeof(*ctx), flags);
471 +       if (!ctx)
472 +               return -ENOMEM;
473 +
474 +       SK_CTX(sk) = ctx;
475 +
476 +       return 0;
477 +}
478 +
479 +/**
480 + * apparmor_sk_free_security - free the sk_security field
481 + */
482 +static void apparmor_sk_free_security(struct sock *sk)
483 +{
484 +       struct aa_sk_ctx *ctx = SK_CTX(sk);
485 +
486 +       SK_CTX(sk) = NULL;
487 +       aa_put_label(ctx->label);
488 +       aa_put_label(ctx->peer);
489 +       path_put(&ctx->path);
490 +       kfree(ctx);
491 +}
492 +
493 +/**
494 + * apparmor_clone_security - clone the sk_security field
495 + */
496 +static void apparmor_sk_clone_security(const struct sock *sk,
497 +                                      struct sock *newsk)
498 +{
499 +       struct aa_sk_ctx *ctx = SK_CTX(sk);
500 +       struct aa_sk_ctx *new = SK_CTX(newsk);
501 +
502 +       new->label = aa_get_label(ctx->label);
503 +       new->peer = aa_get_label(ctx->peer);
504 +       new->path = ctx->path;
505 +       path_get(&new->path);
506 +}
507 +
508 +static int aa_sock_create_perm(struct aa_label *label, int family, int type,
509 +                              int protocol)
510 +{
511 +       AA_BUG(!label);
512 +       AA_BUG(in_interrupt());
513 +
514 +       return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
515 +                         protocol);
516 +}
517 +
518 +
519 +/**
520 + * apparmor_socket_create - check perms before creating a new socket
521 + */
522 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
523 +{
524 +       struct aa_label *label;
525 +       int error = 0;
526 +
527 +       label = begin_current_label_crit_section();
528 +       if (!(kern || unconfined(label)))
529 +               error = aa_sock_create_perm(label, family, type, protocol);
530 +       end_current_label_crit_section(label);
531 +
532 +       return error;
533 +}
534 +
535 +/**
536 + * apparmor_socket_post_create - setup the per-socket security struct
537 + *
538 + * Note:
539 + * -   kernel sockets currently labeled unconfined but we may want to
540 + *     move to a special kernel label
541 + * -   socket may not have sk here if created with sock_create_lite or
542 + *     sock_alloc. These should be accept cases which will be handled in
543 + *     sock_graft.
544 + */
545 +static int apparmor_socket_post_create(struct socket *sock, int family,
546 +                                      int type, int protocol, int kern)
547 +{
548 +       struct aa_label *label;
549 +
550 +       if (kern) {
551 +               struct aa_ns *ns = aa_get_current_ns();
552 +
553 +               label = aa_get_label(ns_unconfined(ns));
554 +               aa_put_ns(ns);
555 +       } else
556 +               label = aa_get_current_label();
557 +
558 +       if (sock->sk) {
559 +               struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
560 +
561 +               aa_put_label(ctx->label);
562 +               ctx->label = aa_get_label(label);
563 +       }
564 +       aa_put_label(label);
565 +
566 +       return 0;
567 +}
568 +
569 +/**
570 + * apparmor_socket_bind - check perms before bind addr to socket
571 + */
572 +static int apparmor_socket_bind(struct socket *sock,
573 +                               struct sockaddr *address, int addrlen)
574 +{
575 +       AA_BUG(!sock);
576 +       AA_BUG(!sock->sk);
577 +       AA_BUG(!address);
578 +       AA_BUG(in_interrupt());
579 +
580 +       return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
581 +}
582 +
583 +/**
584 + * apparmor_socket_connect - check perms before connecting @sock to @address
585 + */
586 +static int apparmor_socket_connect(struct socket *sock,
587 +                                  struct sockaddr *address, int addrlen)
588 +{
589 +       AA_BUG(!sock);
590 +       AA_BUG(!sock->sk);
591 +       AA_BUG(!address);
592 +       AA_BUG(in_interrupt());
593 +
594 +       return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
595 +}
596 +
597 +/**
598 + * apparmor_socket_list - check perms before allowing listen
599 + */
600 +static int apparmor_socket_listen(struct socket *sock, int backlog)
601 +{
602 +       AA_BUG(!sock);
603 +       AA_BUG(!sock->sk);
604 +       AA_BUG(in_interrupt());
605 +
606 +       return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
607 +}
608 +
609 +/**
610 + * apparmor_socket_accept - check perms before accepting a new connection.
611 + *
612 + * Note: while @newsock is created and has some information, the accept
613 + *       has not been done.
614 + */
615 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
616 +{
617 +       AA_BUG(!sock);
618 +       AA_BUG(!sock->sk);
619 +       AA_BUG(!newsock);
620 +       AA_BUG(in_interrupt());
621 +
622 +       return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
623 +}
624 +
625 +static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
626 +                           struct msghdr *msg, int size)
627 +{
628 +       AA_BUG(!sock);
629 +       AA_BUG(!sock->sk);
630 +       AA_BUG(!msg);
631 +       AA_BUG(in_interrupt());
632 +
633 +       return aa_sk_perm(op, request, sock->sk);
634 +}
635 +
636 +/**
637 + * apparmor_socket_sendmsg - check perms before sending msg to another socket
638 + */
639 +static int apparmor_socket_sendmsg(struct socket *sock,
640 +                                  struct msghdr *msg, int size)
641 +{
642 +       return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
643 +}
644 +
645 +/**
646 + * apparmor_socket_recvmsg - check perms before receiving a message
647 + */
648 +static int apparmor_socket_recvmsg(struct socket *sock,
649 +                                  struct msghdr *msg, int size, int flags)
650 +{
651 +       return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
652 +}
653 +
654 +/* revaliation, get/set attr, shutdown */
655 +static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
656 +{
657 +       AA_BUG(!sock);
658 +       AA_BUG(!sock->sk);
659 +       AA_BUG(in_interrupt());
660 +
661 +       return aa_sk_perm(op, request, sock->sk);
662 +}
663 +
664 +/**
665 + * apparmor_socket_getsockname - check perms before getting the local address
666 + */
667 +static int apparmor_socket_getsockname(struct socket *sock)
668 +{
669 +       return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
670 +}
671 +
672 +/**
673 + * apparmor_socket_getpeername - check perms before getting remote address
674 + */
675 +static int apparmor_socket_getpeername(struct socket *sock)
676 +{
677 +       return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
678 +}
679 +
680 +/* revaliation, get/set attr, opt */
681 +static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
682 +                           int level, int optname)
683 +{
684 +       AA_BUG(!sock);
685 +       AA_BUG(!sock->sk);
686 +       AA_BUG(in_interrupt());
687 +
688 +       return aa_sk_perm(op, request, sock->sk);
689 +}
690 +
691 +/**
692 + * apparmor_getsockopt - check perms before getting socket options
693 + */
694 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
695 +                                     int optname)
696 +{
697 +       return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
698 +                               level, optname);
699 +}
700 +
701 +/**
702 + * apparmor_setsockopt - check perms before setting socket options
703 + */
704 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
705 +                                     int optname)
706 +{
707 +       return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
708 +                               level, optname);
709 +}
710 +
711 +/**
712 + * apparmor_socket_shutdown - check perms before shutting down @sock conn
713 + */
714 +static int apparmor_socket_shutdown(struct socket *sock, int how)
715 +{
716 +       return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
717 +}
718 +
719 +/**
720 + * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
721 + *
722 + * Note: can not sleep may be called with locks held
723 + *
724 + * dont want protocol specific in __skb_recv_datagram()
725 + * to deny an incoming connection  socket_sock_rcv_skb()
726 + */
727 +static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
728 +{
729 +       return 0;
730 +}
731 +
732 +
733 +static struct aa_label *sk_peer_label(struct sock *sk)
734 +{
735 +       struct aa_sk_ctx *ctx = SK_CTX(sk);
736 +
737 +       if (ctx->peer)
738 +               return ctx->peer;
739 +
740 +       return ERR_PTR(-ENOPROTOOPT);
741 +}
742 +
743 +/**
744 + * apparmor_socket_getpeersec_stream - get security context of peer
745 + *
746 + * Note: for tcp only valid if using ipsec or cipso on lan
747 + */
748 +static int apparmor_socket_getpeersec_stream(struct socket *sock,
749 +                                            char __user *optval,
750 +                                            int __user *optlen,
751 +                                            unsigned int len)
752 +{
753 +       char *name;
754 +       int slen, error = 0;
755 +       struct aa_label *label;
756 +       struct aa_label *peer;
757 +
758 +       label = begin_current_label_crit_section();
759 +       peer = sk_peer_label(sock->sk);
760 +       if (IS_ERR(peer)) {
761 +               error = PTR_ERR(peer);
762 +               goto done;
763 +       }
764 +       slen = aa_label_asxprint(&name, labels_ns(label), peer,
765 +                                FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
766 +                                FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
767 +       /* don't include terminating \0 in slen, it breaks some apps */
768 +       if (slen < 0) {
769 +               error = -ENOMEM;
770 +       } else {
771 +               if (slen > len) {
772 +                       error = -ERANGE;
773 +               } else if (copy_to_user(optval, name, slen)) {
774 +                       error = -EFAULT;
775 +                       goto out;
776 +               }
777 +               if (put_user(slen, optlen))
778 +                       error = -EFAULT;
779 +out:
780 +               kfree(name);
781 +
782 +       }
783 +
784 +done:
785 +       end_current_label_crit_section(label);
786 +
787 +       return error;
788 +}
789 +
790 +/**
791 + * apparmor_socket_getpeersec_dgram - get security label of packet
792 + * @sock: the peer socket
793 + * @skb: packet data
794 + * @secid: pointer to where to put the secid of the packet
795 + *
796 + * Sets the netlabel socket state on sk from parent
797 + */
798 +static int apparmor_socket_getpeersec_dgram(struct socket *sock,
799 +                                           struct sk_buff *skb, u32 *secid)
800 +
801 +{
802 +       /* TODO: requires secid support */
803 +       return -ENOPROTOOPT;
804 +}
805 +
806 +/**
807 + * apparmor_sock_graft - Initialize newly created socket
808 + * @sk: child sock
809 + * @parent: parent socket
810 + *
811 + * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
812 + *       just set sk security information off of current creating process label
813 + *       Labeling of sk for accept case - probably should be sock based
814 + *       instead of task, because of the case where an implicitly labeled
815 + *       socket is shared by different tasks.
816 + */
817 +static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
818 +{
819 +       struct aa_sk_ctx *ctx = SK_CTX(sk);
820 +
821 +       if (!ctx->label)
822 +               ctx->label = aa_get_current_label();
823 +}
824 +
825  static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
826         LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
827         LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
828 @@ -770,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
829         LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
830         LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
831  
832 +       LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
833 +       LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
834 +       LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
835 +
836 +       LSM_HOOK_INIT(socket_create, apparmor_socket_create),
837 +       LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
838 +       LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
839 +       LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
840 +       LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
841 +       LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
842 +       LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
843 +       LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
844 +       LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
845 +       LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
846 +       LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
847 +       LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
848 +       LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
849 +       LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
850 +       LSM_HOOK_INIT(socket_getpeersec_stream,
851 +                     apparmor_socket_getpeersec_stream),
852 +       LSM_HOOK_INIT(socket_getpeersec_dgram,
853 +                     apparmor_socket_getpeersec_dgram),
854 +       LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
855 +
856         LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
857         LSM_HOOK_INIT(cred_free, apparmor_cred_free),
858         LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
859 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
860 new file mode 100644
861 index 000000000000..33d54435f8d6
862 --- /dev/null
863 +++ b/security/apparmor/net.c
864 @@ -0,0 +1,184 @@
865 +/*
866 + * AppArmor security module
867 + *
868 + * This file contains AppArmor network mediation
869 + *
870 + * Copyright (C) 1998-2008 Novell/SUSE
871 + * Copyright 2009-2017 Canonical Ltd.
872 + *
873 + * This program is free software; you can redistribute it and/or
874 + * modify it under the terms of the GNU General Public License as
875 + * published by the Free Software Foundation, version 2 of the
876 + * License.
877 + */
878 +
879 +#include "include/apparmor.h"
880 +#include "include/audit.h"
881 +#include "include/context.h"
882 +#include "include/label.h"
883 +#include "include/net.h"
884 +#include "include/policy.h"
885 +
886 +#include "net_names.h"
887 +
888 +
889 +struct aa_sfs_entry aa_sfs_entry_network[] = {
890 +       AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
891 +       { }
892 +};
893 +
894 +static const char * const net_mask_names[] = {
895 +       "unknown",
896 +       "send",
897 +       "receive",
898 +       "unknown",
899 +
900 +       "create",
901 +       "shutdown",
902 +       "connect",
903 +       "unknown",
904 +
905 +       "setattr",
906 +       "getattr",
907 +       "setcred",
908 +       "getcred",
909 +
910 +       "chmod",
911 +       "chown",
912 +       "chgrp",
913 +       "lock",
914 +
915 +       "mmap",
916 +       "mprot",
917 +       "unknown",
918 +       "unknown",
919 +
920 +       "accept",
921 +       "bind",
922 +       "listen",
923 +       "unknown",
924 +
925 +       "setopt",
926 +       "getopt",
927 +       "unknown",
928 +       "unknown",
929 +
930 +       "unknown",
931 +       "unknown",
932 +       "unknown",
933 +       "unknown",
934 +};
935 +
936 +
937 +/* audit callback for net specific fields */
938 +void audit_net_cb(struct audit_buffer *ab, void *va)
939 +{
940 +       struct common_audit_data *sa = va;
941 +
942 +       audit_log_format(ab, " family=");
943 +       if (address_family_names[sa->u.net->family])
944 +               audit_log_string(ab, address_family_names[sa->u.net->family]);
945 +       else
946 +               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
947 +       audit_log_format(ab, " sock_type=");
948 +       if (sock_type_names[aad(sa)->net.type])
949 +               audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
950 +       else
951 +               audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
952 +       audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
953 +
954 +       if (aad(sa)->request & NET_PERMS_MASK) {
955 +               audit_log_format(ab, " requested_mask=");
956 +               aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
957 +                                  net_mask_names, NET_PERMS_MASK);
958 +
959 +               if (aad(sa)->denied & NET_PERMS_MASK) {
960 +                       audit_log_format(ab, " denied_mask=");
961 +                       aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
962 +                                          net_mask_names, NET_PERMS_MASK);
963 +               }
964 +       }
965 +       if (aad(sa)->peer) {
966 +               audit_log_format(ab, " peer=");
967 +               aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
968 +                               FLAGS_NONE, GFP_ATOMIC);
969 +       }
970 +}
971 +
972 +
973 +/* Generic af perm */
974 +int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
975 +                      u32 request, u16 family, int type)
976 +{
977 +       struct aa_perms perms = { };
978 +
979 +       AA_BUG(family >= AF_MAX);
980 +       AA_BUG(type < 0 || type >= SOCK_MAX);
981 +
982 +       if (profile_unconfined(profile))
983 +               return 0;
984 +
985 +       perms.allow = (profile->net.allow[family] & (1 << type)) ?
986 +               ALL_PERMS_MASK : 0;
987 +       perms.audit = (profile->net.audit[family] & (1 << type)) ?
988 +               ALL_PERMS_MASK : 0;
989 +       perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
990 +               ALL_PERMS_MASK : 0;
991 +       aa_apply_modes_to_perms(profile, &perms);
992 +
993 +       return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
994 +}
995 +
996 +int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
997 +              int type, int protocol)
998 +{
999 +       struct aa_profile *profile;
1000 +       DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
1001 +
1002 +       return fn_for_each_confined(label, profile,
1003 +                       aa_profile_af_perm(profile, &sa, request, family,
1004 +                                          type));
1005 +}
1006 +
1007 +static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
1008 +                           struct sock *sk)
1009 +{
1010 +       struct aa_profile *profile;
1011 +       DEFINE_AUDIT_SK(sa, op, sk);
1012 +
1013 +       AA_BUG(!label);
1014 +       AA_BUG(!sk);
1015 +
1016 +       if (unconfined(label))
1017 +               return 0;
1018 +
1019 +       return fn_for_each_confined(label, profile,
1020 +                       aa_profile_af_sk_perm(profile, &sa, request, sk));
1021 +}
1022 +
1023 +int aa_sk_perm(const char *op, u32 request, struct sock *sk)
1024 +{
1025 +       struct aa_label *label;
1026 +       int error;
1027 +
1028 +       AA_BUG(!sk);
1029 +       AA_BUG(in_interrupt());
1030 +
1031 +       /* TODO: switch to begin_current_label ???? */
1032 +       label = begin_current_label_crit_section();
1033 +       error = aa_label_sk_perm(label, op, request, sk);
1034 +       end_current_label_crit_section(label);
1035 +
1036 +       return error;
1037 +}
1038 +
1039 +
1040 +int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
1041 +                     struct socket *sock)
1042 +{
1043 +       AA_BUG(!label);
1044 +       AA_BUG(!sock);
1045 +       AA_BUG(!sock->sk);
1046 +
1047 +       return aa_label_sk_perm(label, op, request, sock->sk);
1048 +}
1049 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
1050 index 4ede87c30f8b..5a2aec358322 100644
1051 --- a/security/apparmor/policy_unpack.c
1052 +++ b/security/apparmor/policy_unpack.c
1053 @@ -275,6 +275,19 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
1054         return 0;
1055  }
1056  
1057 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
1058 +{
1059 +       if (unpack_nameX(e, AA_U16, name)) {
1060 +               if (!inbounds(e, sizeof(u16)))
1061 +                       return 0;
1062 +               if (data)
1063 +                       *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
1064 +               e->pos += sizeof(u16);
1065 +               return 1;
1066 +       }
1067 +       return 0;
1068 +}
1069 +
1070  static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
1071  {
1072         if (unpack_nameX(e, AA_U32, name)) {
1073 @@ -584,7 +597,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1074         struct aa_profile *profile = NULL;
1075         const char *tmpname, *tmpns = NULL, *name = NULL;
1076         const char *info = "failed to unpack profile";
1077 -       size_t ns_len;
1078 +       size_t size = 0, ns_len;
1079         struct rhashtable_params params = { 0 };
1080         char *key = NULL;
1081         struct aa_data *data;
1082 @@ -717,6 +730,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
1083                 goto fail;
1084         }
1085  
1086 +       size = unpack_array(e, "net_allowed_af");
1087 +       if (size) {
1088 +
1089 +               for (i = 0; i < size; i++) {
1090 +                       /* discard extraneous rules that this kernel will
1091 +                        * never request
1092 +                        */
1093 +                       if (i >= AF_MAX) {
1094 +                               u16 tmp;
1095 +
1096 +                               if (!unpack_u16(e, &tmp, NULL) ||
1097 +                                   !unpack_u16(e, &tmp, NULL) ||
1098 +                                   !unpack_u16(e, &tmp, NULL))
1099 +                                       goto fail;
1100 +                               continue;
1101 +                       }
1102 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
1103 +                               goto fail;
1104 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
1105 +                               goto fail;
1106 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
1107 +                               goto fail;
1108 +               }
1109 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
1110 +                       goto fail;
1111 +       }
1112 +       if (VERSION_LT(e->version, v7)) {
1113 +               /* pre v7 policy always allowed these */
1114 +               profile->net.allow[AF_UNIX] = 0xffff;
1115 +               profile->net.allow[AF_NETLINK] = 0xffff;
1116 +       }
1117 +
1118         if (unpack_nameX(e, AA_STRUCT, "policydb")) {
1119                 /* generic policy dfa - optional and may be NULL */
1120                 info = "failed to unpack policydb";
1121 -- 
1122 2.11.0
1123
This page took 0.148962 seconds and 3 git commands to generate.