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