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