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