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