]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
- fix vserver patch
[packages/kernel.git] / kernel-apparmor.patch
1 From d29d73fa5d7b5d016f9c17236fff2a741acea247 Mon Sep 17 00:00:00 2001
2 From: John Johansen <john.johansen@canonical.com>
3 Date: Mon, 4 Oct 2010 15:03:36 -0700
4 Subject: [PATCH 1/3] UBUNTU: SAUCE: AppArmor: basic networking rules
5
6 Base support for network mediation.
7
8 Signed-off-by: John Johansen <john.johansen@canonical.com>
9
10 Conflicts:
11         security/apparmor/Makefile
12         security/apparmor/policy.c
13 ---
14  security/apparmor/.gitignore       |   1 +
15  security/apparmor/Makefile         |  42 +++++++++-
16  security/apparmor/apparmorfs.c     |   1 +
17  security/apparmor/include/audit.h  |   4 +
18  security/apparmor/include/net.h    |  44 ++++++++++
19  security/apparmor/include/policy.h |   3 +
20  security/apparmor/lsm.c            | 112 +++++++++++++++++++++++++
21  security/apparmor/net.c            | 162 +++++++++++++++++++++++++++++++++++++
22  security/apparmor/policy.c         |   1 +
23  security/apparmor/policy_unpack.c  |  46 +++++++++++
24  10 files changed, 414 insertions(+), 2 deletions(-)
25  create mode 100644 security/apparmor/include/net.h
26  create mode 100644 security/apparmor/net.c
27
28 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
29 index 9cdec70..d5b291e 100644
30 --- a/security/apparmor/.gitignore
31 +++ b/security/apparmor/.gitignore
32 @@ -1,5 +1,6 @@
33  #
34  # Generated include files
35  #
36 +net_names.h
37  capability_names.h
38  rlim_names.h
39 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
40 index d693df8..5dbb72f 100644
41 --- a/security/apparmor/Makefile
42 +++ b/security/apparmor/Makefile
43 @@ -4,10 +4,10 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
44  
45  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
46                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
47 -              resource.o sid.o file.o
48 +              resource.o sid.o file.o net.o
49  apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
50  
51 -clean-files := capability_names.h rlim_names.h
52 +clean-files := capability_names.h rlim_names.h net_names.h
53  
54  
55  # Build a lower case string table of capability names
56 @@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
57             -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
58              tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
59  
60 +# Build a lower case string table of address family names
61 +# Transform lines from
62 +#    define AF_LOCAL   1       /* POSIX name for AF_UNIX       */
63 +#    #define AF_INET           2       /* Internet IP Protocol         */
64 +# to
65 +#    [1] = "local",
66 +#    [2] = "inet",
67 +#
68 +# and build the securityfs entries for the mapping.
69 +# Transforms lines from
70 +#    #define AF_INET           2       /* Internet IP Protocol         */
71 +# to
72 +#    #define AA_FS_AF_MASK "local inet"
73 +quiet_cmd_make-af = GEN     $@
74 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
75 +       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
76 +        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
77 +       echo "};" >> $@ ;\
78 +       echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
79 +       sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
80 +        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
81 +
82 +# Build a lower case string table of sock type names
83 +# Transform lines from
84 +#    SOCK_STREAM       = 1,
85 +# to
86 +#    [1] = "stream",
87 +quiet_cmd_make-sock = GEN     $@
88 +cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
89 +       sed $^ >>$@ -r -n \
90 +       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
91 +       echo "};" >> $@
92  
93  # Build a lower case string table of rlimit names.
94  # Transforms lines from
95 @@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
96             tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
97  
98  $(obj)/capability.o : $(obj)/capability_names.h
99 +$(obj)/net.o : $(obj)/net_names.h
100  $(obj)/resource.o : $(obj)/rlim_names.h
101  $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
102                             $(src)/Makefile
103 @@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
104  $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
105                       $(src)/Makefile
106         $(call cmd,make-rlim)
107 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
108 +                    $(srctree)/include/linux/net.h \
109 +                    $(src)/Makefile
110 +       $(call cmd,make-af)
111 +       $(call cmd,make-sock)
112 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
113 index 7db9954..18fc02c 100644
114 --- a/security/apparmor/apparmorfs.c
115 +++ b/security/apparmor/apparmorfs.c
116 @@ -806,6 +806,7 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
117         AA_FS_DIR("policy",                     aa_fs_entry_policy),
118         AA_FS_DIR("domain",                     aa_fs_entry_domain),
119         AA_FS_DIR("file",                       aa_fs_entry_file),
120 +       AA_FS_DIR("network",                    aa_fs_entry_network),
121         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
122         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
123         AA_FS_DIR("caps",                       aa_fs_entry_caps),
124 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
125 index 30e8d76..61abec5 100644
126 --- a/security/apparmor/include/audit.h
127 +++ b/security/apparmor/include/audit.h
128 @@ -126,6 +126,10 @@ struct apparmor_audit_data {
129                         u32 denied;
130                         kuid_t ouid;
131                 } fs;
132 +               struct {
133 +                       int type, protocol;
134 +                       struct sock *sk;
135 +               } net;
136         };
137  };
138  
139 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
140 new file mode 100644
141 index 0000000..cb8a121
142 --- /dev/null
143 +++ b/security/apparmor/include/net.h
144 @@ -0,0 +1,44 @@
145 +/*
146 + * AppArmor security module
147 + *
148 + * This file contains AppArmor network mediation definitions.
149 + *
150 + * Copyright (C) 1998-2008 Novell/SUSE
151 + * Copyright 2009-2012 Canonical Ltd.
152 + *
153 + * This program is free software; you can redistribute it and/or
154 + * modify it under the terms of the GNU General Public License as
155 + * published by the Free Software Foundation, version 2 of the
156 + * License.
157 + */
158 +
159 +#ifndef __AA_NET_H
160 +#define __AA_NET_H
161 +
162 +#include <net/sock.h>
163 +
164 +#include "apparmorfs.h"
165 +
166 +/* struct aa_net - network confinement data
167 + * @allowed: basic network families permissions
168 + * @audit_network: which network permissions to force audit
169 + * @quiet_network: which network permissions to quiet rejects
170 + */
171 +struct aa_net {
172 +       u16 allow[AF_MAX];
173 +       u16 audit[AF_MAX];
174 +       u16 quiet[AF_MAX];
175 +};
176 +
177 +extern struct aa_fs_entry aa_fs_entry_network[];
178 +
179 +extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
180 +                      int type, int protocol, struct sock *sk);
181 +extern int aa_revalidate_sk(int op, struct sock *sk);
182 +
183 +static inline void aa_free_net_rules(struct aa_net *new)
184 +{
185 +       /* NOP */
186 +}
187 +
188 +#endif /* __AA_NET_H */
189 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
190 index c28b0f2..b524d88 100644
191 --- a/security/apparmor/include/policy.h
192 +++ b/security/apparmor/include/policy.h
193 @@ -27,6 +27,7 @@
194  #include "capability.h"
195  #include "domain.h"
196  #include "file.h"
197 +#include "net.h"
198  #include "resource.h"
199  
200  extern const char *const aa_profile_mode_names[];
201 @@ -176,6 +177,7 @@ struct aa_replacedby {
202   * @policy: general match rules governing policy
203   * @file: The set of rules governing basic file access and domain transitions
204   * @caps: capabilities for the profile
205 + * @net: network controls for the profile
206   * @rlimits: rlimits for the profile
207   *
208   * @dents: dentries for the profiles file entries in apparmorfs
209 @@ -217,6 +219,7 @@ struct aa_profile {
210         struct aa_policydb policy;
211         struct aa_file_rules file;
212         struct aa_caps caps;
213 +       struct aa_net net;
214         struct aa_rlimit rlimits;
215  
216         unsigned char *hash;
217 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
218 index fb99e18..de55a7f 100644
219 --- a/security/apparmor/lsm.c
220 +++ b/security/apparmor/lsm.c
221 @@ -32,6 +32,7 @@
222  #include "include/context.h"
223  #include "include/file.h"
224  #include "include/ipc.h"
225 +#include "include/net.h"
226  #include "include/path.h"
227  #include "include/policy.h"
228  #include "include/procattr.h"
229 @@ -615,6 +616,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
230         return error;
231  }
232  
233 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
234 +{
235 +       struct aa_profile *profile;
236 +       int error = 0;
237 +
238 +       if (kern)
239 +               return 0;
240 +
241 +       profile = __aa_current_profile();
242 +       if (!unconfined(profile))
243 +               error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
244 +                                   NULL);
245 +       return error;
246 +}
247 +
248 +static int apparmor_socket_bind(struct socket *sock,
249 +                               struct sockaddr *address, int addrlen)
250 +{
251 +       struct sock *sk = sock->sk;
252 +
253 +       return aa_revalidate_sk(OP_BIND, sk);
254 +}
255 +
256 +static int apparmor_socket_connect(struct socket *sock,
257 +                                  struct sockaddr *address, int addrlen)
258 +{
259 +       struct sock *sk = sock->sk;
260 +
261 +       return aa_revalidate_sk(OP_CONNECT, sk);
262 +}
263 +
264 +static int apparmor_socket_listen(struct socket *sock, int backlog)
265 +{
266 +       struct sock *sk = sock->sk;
267 +
268 +       return aa_revalidate_sk(OP_LISTEN, sk);
269 +}
270 +
271 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
272 +{
273 +       struct sock *sk = sock->sk;
274 +
275 +       return aa_revalidate_sk(OP_ACCEPT, sk);
276 +}
277 +
278 +static int apparmor_socket_sendmsg(struct socket *sock,
279 +                                  struct msghdr *msg, int size)
280 +{
281 +       struct sock *sk = sock->sk;
282 +
283 +       return aa_revalidate_sk(OP_SENDMSG, sk);
284 +}
285 +
286 +static int apparmor_socket_recvmsg(struct socket *sock,
287 +                                  struct msghdr *msg, int size, int flags)
288 +{
289 +       struct sock *sk = sock->sk;
290 +
291 +       return aa_revalidate_sk(OP_RECVMSG, sk);
292 +}
293 +
294 +static int apparmor_socket_getsockname(struct socket *sock)
295 +{
296 +       struct sock *sk = sock->sk;
297 +
298 +       return aa_revalidate_sk(OP_GETSOCKNAME, sk);
299 +}
300 +
301 +static int apparmor_socket_getpeername(struct socket *sock)
302 +{
303 +       struct sock *sk = sock->sk;
304 +
305 +       return aa_revalidate_sk(OP_GETPEERNAME, sk);
306 +}
307 +
308 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
309 +                                     int optname)
310 +{
311 +       struct sock *sk = sock->sk;
312 +
313 +       return aa_revalidate_sk(OP_GETSOCKOPT, sk);
314 +}
315 +
316 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
317 +                                     int optname)
318 +{
319 +       struct sock *sk = sock->sk;
320 +
321 +       return aa_revalidate_sk(OP_SETSOCKOPT, sk);
322 +}
323 +
324 +static int apparmor_socket_shutdown(struct socket *sock, int how)
325 +{
326 +       struct sock *sk = sock->sk;
327 +
328 +       return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
329 +}
330 +
331  static struct security_operations apparmor_ops = {
332         .name =                         "apparmor",
333  
334 @@ -647,6 +746,19 @@ static struct security_operations apparmor_ops = {
335         .getprocattr =                  apparmor_getprocattr,
336         .setprocattr =                  apparmor_setprocattr,
337  
338 +       .socket_create =                apparmor_socket_create,
339 +       .socket_bind =                  apparmor_socket_bind,
340 +       .socket_connect =               apparmor_socket_connect,
341 +       .socket_listen =                apparmor_socket_listen,
342 +       .socket_accept =                apparmor_socket_accept,
343 +       .socket_sendmsg =               apparmor_socket_sendmsg,
344 +       .socket_recvmsg =               apparmor_socket_recvmsg,
345 +       .socket_getsockname =           apparmor_socket_getsockname,
346 +       .socket_getpeername =           apparmor_socket_getpeername,
347 +       .socket_getsockopt =            apparmor_socket_getsockopt,
348 +       .socket_setsockopt =            apparmor_socket_setsockopt,
349 +       .socket_shutdown =              apparmor_socket_shutdown,
350 +
351         .cred_alloc_blank =             apparmor_cred_alloc_blank,
352         .cred_free =                    apparmor_cred_free,
353         .cred_prepare =                 apparmor_cred_prepare,
354 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
355 new file mode 100644
356 index 0000000..003dd18
357 --- /dev/null
358 +++ b/security/apparmor/net.c
359 @@ -0,0 +1,162 @@
360 +/*
361 + * AppArmor security module
362 + *
363 + * This file contains AppArmor network mediation
364 + *
365 + * Copyright (C) 1998-2008 Novell/SUSE
366 + * Copyright 2009-2012 Canonical Ltd.
367 + *
368 + * This program is free software; you can redistribute it and/or
369 + * modify it under the terms of the GNU General Public License as
370 + * published by the Free Software Foundation, version 2 of the
371 + * License.
372 + */
373 +
374 +#include "include/apparmor.h"
375 +#include "include/audit.h"
376 +#include "include/context.h"
377 +#include "include/net.h"
378 +#include "include/policy.h"
379 +
380 +#include "net_names.h"
381 +
382 +struct aa_fs_entry aa_fs_entry_network[] = {
383 +       AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
384 +       { }
385 +};
386 +
387 +/* audit callback for net specific fields */
388 +static void audit_cb(struct audit_buffer *ab, void *va)
389 +{
390 +       struct common_audit_data *sa = va;
391 +
392 +       audit_log_format(ab, " family=");
393 +       if (address_family_names[sa->u.net->family]) {
394 +               audit_log_string(ab, address_family_names[sa->u.net->family]);
395 +       } else {
396 +               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
397 +       }
398 +       audit_log_format(ab, " sock_type=");
399 +       if (sock_type_names[sa->aad->net.type]) {
400 +               audit_log_string(ab, sock_type_names[sa->aad->net.type]);
401 +       } else {
402 +               audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
403 +       }
404 +       audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
405 +}
406 +
407 +/**
408 + * audit_net - audit network access
409 + * @profile: profile being enforced  (NOT NULL)
410 + * @op: operation being checked
411 + * @family: network family
412 + * @type:   network type
413 + * @protocol: network protocol
414 + * @sk: socket auditing is being applied to
415 + * @error: error code for failure else 0
416 + *
417 + * Returns: %0 or sa->error else other errorcode on failure
418 + */
419 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
420 +                    int protocol, struct sock *sk, int error)
421 +{
422 +       int audit_type = AUDIT_APPARMOR_AUTO;
423 +       struct common_audit_data sa;
424 +       struct apparmor_audit_data aad = { };
425 +       struct lsm_network_audit net = { };
426 +       if (sk) {
427 +               sa.type = LSM_AUDIT_DATA_NET;
428 +       } else {
429 +               sa.type = LSM_AUDIT_DATA_NONE;
430 +       }
431 +       /* todo fill in socket addr info */
432 +       sa.aad = &aad;
433 +       sa.u.net = &net;
434 +       sa.aad->op = op,
435 +       sa.u.net->family = family;
436 +       sa.u.net->sk = sk;
437 +       sa.aad->net.type = type;
438 +       sa.aad->net.protocol = protocol;
439 +       sa.aad->error = error;
440 +
441 +       if (likely(!sa.aad->error)) {
442 +               u16 audit_mask = profile->net.audit[sa.u.net->family];
443 +               if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
444 +                          !(1 << sa.aad->net.type & audit_mask)))
445 +                       return 0;
446 +               audit_type = AUDIT_APPARMOR_AUDIT;
447 +       } else {
448 +               u16 quiet_mask = profile->net.quiet[sa.u.net->family];
449 +               u16 kill_mask = 0;
450 +               u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
451 +
452 +               if (denied & kill_mask)
453 +                       audit_type = AUDIT_APPARMOR_KILL;
454 +
455 +               if ((denied & quiet_mask) &&
456 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
457 +                   AUDIT_MODE(profile) != AUDIT_ALL)
458 +                       return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
459 +       }
460 +
461 +       return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
462 +}
463 +
464 +/**
465 + * aa_net_perm - very course network access check
466 + * @op: operation being checked
467 + * @profile: profile being enforced  (NOT NULL)
468 + * @family: network family
469 + * @type:   network type
470 + * @protocol: network protocol
471 + *
472 + * Returns: %0 else error if permission denied
473 + */
474 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
475 +               int protocol, struct sock *sk)
476 +{
477 +       u16 family_mask;
478 +       int error;
479 +
480 +       if ((family < 0) || (family >= AF_MAX))
481 +               return -EINVAL;
482 +
483 +       if ((type < 0) || (type >= SOCK_MAX))
484 +               return -EINVAL;
485 +
486 +       /* unix domain and netlink sockets are handled by ipc */
487 +       if (family == AF_UNIX || family == AF_NETLINK)
488 +               return 0;
489 +
490 +       family_mask = profile->net.allow[family];
491 +
492 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
493 +
494 +       return audit_net(profile, op, family, type, protocol, sk, error);
495 +}
496 +
497 +/**
498 + * aa_revalidate_sk - Revalidate access to a sock
499 + * @op: operation being checked
500 + * @sk: sock being revalidated  (NOT NULL)
501 + *
502 + * Returns: %0 else error if permission denied
503 + */
504 +int aa_revalidate_sk(int op, struct sock *sk)
505 +{
506 +       struct aa_profile *profile;
507 +       int error = 0;
508 +
509 +       /* aa_revalidate_sk should not be called from interrupt context
510 +        * don't mediate these calls as they are not task related
511 +        */
512 +       if (in_interrupt())
513 +               return 0;
514 +
515 +       profile = __aa_current_profile();
516 +       if (!unconfined(profile))
517 +               error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
518 +                                   sk->sk_protocol, sk);
519 +
520 +       return error;
521 +}
522 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
523 index 705c287..e2afe29 100644
524 --- a/security/apparmor/policy.c
525 +++ b/security/apparmor/policy.c
526 @@ -603,6 +603,7 @@ void aa_free_profile(struct aa_profile *profile)
527  
528         aa_free_file_rules(&profile->file);
529         aa_free_cap_rules(&profile->caps);
530 +       aa_free_net_rules(&profile->net);
531         aa_free_rlimit_rules(&profile->rlimits);
532  
533         kzfree(profile->dirname);
534 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
535 index a689f10..1a35e6b 100644
536 --- a/security/apparmor/policy_unpack.c
537 +++ b/security/apparmor/policy_unpack.c
538 @@ -193,6 +193,19 @@ fail:
539         return 0;
540  }
541  
542 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
543 +{
544 +       if (unpack_nameX(e, AA_U16, name)) {
545 +               if (!inbounds(e, sizeof(u16)))
546 +                       return 0;
547 +               if (data)
548 +                       *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
549 +               e->pos += sizeof(u16);
550 +               return 1;
551 +       }
552 +       return 0;
553 +}
554 +
555  static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
556  {
557         if (unpack_nameX(e, AA_U32, name)) {
558 @@ -476,6 +489,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
559  {
560         struct aa_profile *profile = NULL;
561         const char *name = NULL;
562 +       size_t size = 0;
563         int i, error = -EPROTO;
564         kernel_cap_t tmpcap;
565         u32 tmp;
566 @@ -576,6 +590,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
567         if (!unpack_rlimits(e, profile))
568                 goto fail;
569  
570 +       size = unpack_array(e, "net_allowed_af");
571 +       if (size) {
572 +
573 +               for (i = 0; i < size; i++) {
574 +                       /* discard extraneous rules that this kernel will
575 +                        * never request
576 +                        */
577 +                       if (i >= AF_MAX) {
578 +                               u16 tmp;
579 +                               if (!unpack_u16(e, &tmp, NULL) ||
580 +                                   !unpack_u16(e, &tmp, NULL) ||
581 +                                   !unpack_u16(e, &tmp, NULL))
582 +                                       goto fail;
583 +                               continue;
584 +                       }
585 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
586 +                               goto fail;
587 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
588 +                               goto fail;
589 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
590 +                               goto fail;
591 +               }
592 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
593 +                       goto fail;
594 +       }
595 +       /*
596 +        * allow unix domain and netlink sockets they are handled
597 +        * by IPC
598 +        */
599 +       profile->net.allow[AF_UNIX] = 0xffff;
600 +       profile->net.allow[AF_NETLINK] = 0xffff;
601 +
602         if (unpack_nameX(e, AA_STRUCT, "policydb")) {
603                 /* generic policy dfa - optional and may be NULL */
604                 profile->policy.dfa = unpack_dfa(e);
605 -- 
606 1.8.3.2
607
608 From b452a37e97af826ba6c7548230e07c95bd13d9c4 Mon Sep 17 00:00:00 2001
609 From: John Johansen <john.johansen@canonical.com>
610 Date: Fri, 29 Jun 2012 17:34:00 -0700
611 Subject: [PATCH 2/3] apparmor: Fix quieting of audit messages for network
612  mediation
613
614 If a profile specified a quieting of network denials for a given rule by
615 either the quiet or deny rule qualifiers, the resultant quiet mask for
616 denied requests was applied incorrectly, resulting in two potential bugs.
617 1. The misapplied quiet mask would prevent denials from being correctly
618    tested against the kill mask/mode. Thus network access requests that
619    should have resulted in the application being killed did not.
620
621 2. The actual quieting of the denied network request was not being applied.
622    This would result in network rejections always being logged even when
623    they had been specifically marked as quieted.
624
625 Signed-off-by: John Johansen <john.johansen@canonical.com>
626 ---
627  security/apparmor/net.c | 2 +-
628  1 file changed, 1 insertion(+), 1 deletion(-)
629
630 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
631 index 003dd18..6e6e5c9 100644
632 --- a/security/apparmor/net.c
633 +++ b/security/apparmor/net.c
634 @@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
635         } else {
636                 u16 quiet_mask = profile->net.quiet[sa.u.net->family];
637                 u16 kill_mask = 0;
638 -               u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
639 +               u16 denied = (1 << sa.aad->net.type);
640  
641                 if (denied & kill_mask)
642                         audit_type = AUDIT_APPARMOR_KILL;
643 -- 
644 1.8.3.2
645
646 From 0f113c1f052be315f5097d8b7294a620b0adda87 Mon Sep 17 00:00:00 2001
647 From: John Johansen <john.johansen@canonical.com>
648 Date: Wed, 16 May 2012 10:58:05 -0700
649 Subject: [PATCH 3/3] UBUNTU: SAUCE: apparmor: Add the ability to mediate mount
650
651 Add the ability for apparmor to do mediation of mount operations. Mount
652 rules require an updated apparmor_parser (2.8 series) for policy compilation.
653
654 The basic form of the rules are.
655
656   [audit] [deny] mount [conds]* [device] [ -> [conds] path],
657   [audit] [deny] remount [conds]* [path],
658   [audit] [deny] umount [conds]* [path],
659   [audit] [deny] pivotroot [oldroot=<value>] <path>
660
661   remount is just a short cut for mount options=remount
662
663   where [conds] can be
664     fstype=<expr>
665     options=<expr>
666
667 Example mount commands
668   mount,                # allow all mounts, but not umount or pivotroot
669
670   mount fstype=procfs,  # allow mounting procfs anywhere
671
672   mount options=(bind, ro) /foo -> /bar,  # readonly bind mount
673
674   mount /dev/sda -> /mnt,
675
676   mount /dev/sd** -> /mnt/**,
677
678   mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
679
680   umount,
681
682   umount /m*,
683
684 See the apparmor userspace for full documentation
685
686 Signed-off-by: John Johansen <john.johansen@canonical.com>
687 Acked-by: Kees Cook <kees@ubuntu.com>
688
689 Conflicts:
690         security/apparmor/Makefile
691         security/apparmor/apparmorfs.c
692 ---
693  security/apparmor/Makefile           |   2 +-
694  security/apparmor/apparmorfs.c       |  15 +-
695  security/apparmor/audit.c            |   4 +
696  security/apparmor/domain.c           |   2 +-
697  security/apparmor/include/apparmor.h |   3 +-
698  security/apparmor/include/audit.h    |  11 +
699  security/apparmor/include/domain.h   |   2 +
700  security/apparmor/include/mount.h    |  54 +++
701  security/apparmor/lsm.c              |  59 ++++
702  security/apparmor/mount.c            | 620 +++++++++++++++++++++++++++++++++++
703  10 files changed, 768 insertions(+), 4 deletions(-)
704  create mode 100644 security/apparmor/include/mount.h
705  create mode 100644 security/apparmor/mount.c
706
707 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
708 index 5dbb72f..89b3445 100644
709 --- a/security/apparmor/Makefile
710 +++ b/security/apparmor/Makefile
711 @@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
712  
713  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
714                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
715 -              resource.o sid.o file.o net.o
716 +              resource.o sid.o file.o net.o mount.o
717  apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
718  
719  clean-files := capability_names.h rlim_names.h net_names.h
720 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
721 index 18fc02c..e709030 100644
722 --- a/security/apparmor/apparmorfs.c
723 +++ b/security/apparmor/apparmorfs.c
724 @@ -799,7 +799,18 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
725  
726  static struct aa_fs_entry aa_fs_entry_policy[] = {
727         AA_FS_FILE_BOOLEAN("set_load",          1),
728 -       {}
729 +       { }
730 +};
731 +
732 +static struct aa_fs_entry aa_fs_entry_mount[] = {
733 +       AA_FS_FILE_STRING("mask", "mount umount"),
734 +       { }
735 +};
736 +
737 +static struct aa_fs_entry aa_fs_entry_namespaces[] = {
738 +       AA_FS_FILE_BOOLEAN("profile",           1),
739 +       AA_FS_FILE_BOOLEAN("pivot_root",        1),
740 +       { }
741  };
742  
743  static struct aa_fs_entry aa_fs_entry_features[] = {
744 @@ -807,6 +818,8 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
745         AA_FS_DIR("domain",                     aa_fs_entry_domain),
746         AA_FS_DIR("file",                       aa_fs_entry_file),
747         AA_FS_DIR("network",                    aa_fs_entry_network),
748 +       AA_FS_DIR("mount",                      aa_fs_entry_mount),
749 +       AA_FS_DIR("namespaces",                 aa_fs_entry_namespaces),
750         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
751         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
752         AA_FS_DIR("caps",                       aa_fs_entry_caps),
753 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
754 index 031d2d9..02d804c 100644
755 --- a/security/apparmor/audit.c
756 +++ b/security/apparmor/audit.c
757 @@ -44,6 +44,10 @@ const char *const op_table[] = {
758         "file_mmap",
759         "file_mprotect",
760  
761 +       "pivotroot",
762 +       "mount",
763 +       "umount",
764 +
765         "create",
766         "post_create",
767         "bind",
768 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
769 index 26c607c..23936c5 100644
770 --- a/security/apparmor/domain.c
771 +++ b/security/apparmor/domain.c
772 @@ -238,7 +238,7 @@ static const char *next_name(int xtype, const char *name)
773   *
774   * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
775   */
776 -static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
777 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
778  {
779         struct aa_profile *new_profile = NULL;
780         struct aa_namespace *ns = profile->ns;
781 diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
782 index 8fb1488..22b172c 100644
783 --- a/security/apparmor/include/apparmor.h
784 +++ b/security/apparmor/include/apparmor.h
785 @@ -30,8 +30,9 @@
786  #define AA_CLASS_NET           4
787  #define AA_CLASS_RLIMITS       5
788  #define AA_CLASS_DOMAIN                6
789 +#define AA_CLASS_MOUNT         7
790  
791 -#define AA_CLASS_LAST          AA_CLASS_DOMAIN
792 +#define AA_CLASS_LAST          AA_CLASS_MOUNT
793  
794  /* Control parameters settable through module/boot flags */
795  extern enum audit_mode aa_g_audit;
796 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
797 index 61abec5..a9835c3 100644
798 --- a/security/apparmor/include/audit.h
799 +++ b/security/apparmor/include/audit.h
800 @@ -72,6 +72,10 @@ enum aa_ops {
801         OP_FMMAP,
802         OP_FMPROT,
803  
804 +       OP_PIVOTROOT,
805 +       OP_MOUNT,
806 +       OP_UMOUNT,
807 +
808         OP_CREATE,
809         OP_POST_CREATE,
810         OP_BIND,
811 @@ -121,6 +125,13 @@ struct apparmor_audit_data {
812                         unsigned long max;
813                 } rlim;
814                 struct {
815 +                       const char *src_name;
816 +                       const char *type;
817 +                       const char *trans;
818 +                       const char *data;
819 +                       unsigned long flags;
820 +               } mnt;
821 +               struct {
822                         const char *target;
823                         u32 request;
824                         u32 denied;
825 diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
826 index de04464..a3f70c5 100644
827 --- a/security/apparmor/include/domain.h
828 +++ b/security/apparmor/include/domain.h
829 @@ -23,6 +23,8 @@ struct aa_domain {
830         char **table;
831  };
832  
833 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
834 +
835  int apparmor_bprm_set_creds(struct linux_binprm *bprm);
836  int apparmor_bprm_secureexec(struct linux_binprm *bprm);
837  void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
838 diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
839 new file mode 100644
840 index 0000000..bc17a53
841 --- /dev/null
842 +++ b/security/apparmor/include/mount.h
843 @@ -0,0 +1,54 @@
844 +/*
845 + * AppArmor security module
846 + *
847 + * This file contains AppArmor file mediation function definitions.
848 + *
849 + * Copyright 2012 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 +#ifndef __AA_MOUNT_H
858 +#define __AA_MOUNT_H
859 +
860 +#include <linux/fs.h>
861 +#include <linux/path.h>
862 +
863 +#include "domain.h"
864 +#include "policy.h"
865 +
866 +/* mount perms */
867 +#define AA_MAY_PIVOTROOT       0x01
868 +#define AA_MAY_MOUNT           0x02
869 +#define AA_MAY_UMOUNT          0x04
870 +#define AA_AUDIT_DATA          0x40
871 +#define AA_CONT_MATCH          0x40
872 +
873 +#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
874 +
875 +int aa_remount(struct aa_profile *profile, struct path *path,
876 +              unsigned long flags, void *data);
877 +
878 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
879 +                 const char *old_name, unsigned long flags);
880 +
881 +
882 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
883 +                        unsigned long flags);
884 +
885 +int aa_move_mount(struct aa_profile *profile, struct path *path,
886 +                 const char *old_name);
887 +
888 +int aa_new_mount(struct aa_profile *profile, const char *dev_name,
889 +                struct path *path, const char *type, unsigned long flags,
890 +                void *data);
891 +
892 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
893 +
894 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
895 +                 struct path *new_path);
896 +
897 +#endif /* __AA_MOUNT_H */
898 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
899 index de55a7f..e0dd95f 100644
900 --- a/security/apparmor/lsm.c
901 +++ b/security/apparmor/lsm.c
902 @@ -36,6 +36,7 @@
903  #include "include/path.h"
904  #include "include/policy.h"
905  #include "include/procattr.h"
906 +#include "include/mount.h"
907  
908  /* Flag indicating whether initialization completed */
909  int apparmor_initialized __initdata;
910 @@ -502,6 +503,60 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
911                            !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
912  }
913  
914 +static int apparmor_sb_mount(const char *dev_name, struct path *path, const char *type,
915 +                            unsigned long flags, void *data)
916 +{
917 +       struct aa_profile *profile;
918 +       int error = 0;
919 +
920 +       /* Discard magic */
921 +       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
922 +               flags &= ~MS_MGC_MSK;
923 +
924 +       flags &= ~AA_MS_IGNORE_MASK;
925 +
926 +       profile = __aa_current_profile();
927 +       if (!unconfined(profile)) {
928 +               if (flags & MS_REMOUNT)
929 +                       error = aa_remount(profile, path, flags, data);
930 +               else if (flags & MS_BIND)
931 +                       error = aa_bind_mount(profile, path, dev_name, flags);
932 +               else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
933 +                                 MS_UNBINDABLE))
934 +                       error = aa_mount_change_type(profile, path, flags);
935 +               else if (flags & MS_MOVE)
936 +                       error = aa_move_mount(profile, path, dev_name);
937 +               else
938 +                       error = aa_new_mount(profile, dev_name, path, type,
939 +                                            flags, data);
940 +       }
941 +       return error;
942 +}
943 +
944 +static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
945 +{
946 +       struct aa_profile *profile;
947 +       int error = 0;
948 +
949 +       profile = __aa_current_profile();
950 +       if (!unconfined(profile))
951 +               error = aa_umount(profile, mnt, flags);
952 +
953 +       return error;
954 +}
955 +
956 +static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
957 +{
958 +       struct aa_profile *profile;
959 +       int error = 0;
960 +
961 +       profile = __aa_current_profile();
962 +       if (!unconfined(profile))
963 +               error = aa_pivotroot(profile, old_path, new_path);
964 +
965 +       return error;
966 +}
967 +
968  static int apparmor_getprocattr(struct task_struct *task, char *name,
969                                 char **value)
970  {
971 @@ -722,6 +777,10 @@ static struct security_operations apparmor_ops = {
972         .capget =                       apparmor_capget,
973         .capable =                      apparmor_capable,
974  
975 +       .sb_mount =                     apparmor_sb_mount,
976 +       .sb_umount =                    apparmor_sb_umount,
977 +       .sb_pivotroot =                 apparmor_sb_pivotroot,
978 +
979         .path_link =                    apparmor_path_link,
980         .path_unlink =                  apparmor_path_unlink,
981         .path_symlink =                 apparmor_path_symlink,
982 diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
983 new file mode 100644
984 index 0000000..478aa4d
985 --- /dev/null
986 +++ b/security/apparmor/mount.c
987 @@ -0,0 +1,620 @@
988 +/*
989 + * AppArmor security module
990 + *
991 + * This file contains AppArmor mediation of files
992 + *
993 + * Copyright (C) 1998-2008 Novell/SUSE
994 + * Copyright 2009-2012 Canonical Ltd.
995 + *
996 + * This program is free software; you can redistribute it and/or
997 + * modify it under the terms of the GNU General Public License as
998 + * published by the Free Software Foundation, version 2 of the
999 + * License.
1000 + */
1001 +
1002 +#include <linux/fs.h>
1003 +#include <linux/mount.h>
1004 +#include <linux/namei.h>
1005 +
1006 +#include "include/apparmor.h"
1007 +#include "include/audit.h"
1008 +#include "include/context.h"
1009 +#include "include/domain.h"
1010 +#include "include/file.h"
1011 +#include "include/match.h"
1012 +#include "include/mount.h"
1013 +#include "include/path.h"
1014 +#include "include/policy.h"
1015 +
1016 +
1017 +static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
1018 +{
1019 +       if (flags & MS_RDONLY)
1020 +               audit_log_format(ab, "ro");
1021 +       else
1022 +               audit_log_format(ab, "rw");
1023 +       if (flags & MS_NOSUID)
1024 +               audit_log_format(ab, ", nosuid");
1025 +       if (flags & MS_NODEV)
1026 +               audit_log_format(ab, ", nodev");
1027 +       if (flags & MS_NOEXEC)
1028 +               audit_log_format(ab, ", noexec");
1029 +       if (flags & MS_SYNCHRONOUS)
1030 +               audit_log_format(ab, ", sync");
1031 +       if (flags & MS_REMOUNT)
1032 +               audit_log_format(ab, ", remount");
1033 +       if (flags & MS_MANDLOCK)
1034 +               audit_log_format(ab, ", mand");
1035 +       if (flags & MS_DIRSYNC)
1036 +               audit_log_format(ab, ", dirsync");
1037 +       if (flags & MS_NOATIME)
1038 +               audit_log_format(ab, ", noatime");
1039 +       if (flags & MS_NODIRATIME)
1040 +               audit_log_format(ab, ", nodiratime");
1041 +       if (flags & MS_BIND)
1042 +               audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
1043 +       if (flags & MS_MOVE)
1044 +               audit_log_format(ab, ", move");
1045 +       if (flags & MS_SILENT)
1046 +               audit_log_format(ab, ", silent");
1047 +       if (flags & MS_POSIXACL)
1048 +               audit_log_format(ab, ", acl");
1049 +       if (flags & MS_UNBINDABLE)
1050 +               audit_log_format(ab, flags & MS_REC ? ", runbindable" :
1051 +                                ", unbindable");
1052 +       if (flags & MS_PRIVATE)
1053 +               audit_log_format(ab, flags & MS_REC ? ", rprivate" :
1054 +                                ", private");
1055 +       if (flags & MS_SLAVE)
1056 +               audit_log_format(ab, flags & MS_REC ? ", rslave" :
1057 +                                ", slave");
1058 +       if (flags & MS_SHARED)
1059 +               audit_log_format(ab, flags & MS_REC ? ", rshared" :
1060 +                                ", shared");
1061 +       if (flags & MS_RELATIME)
1062 +               audit_log_format(ab, ", relatime");
1063 +       if (flags & MS_I_VERSION)
1064 +               audit_log_format(ab, ", iversion");
1065 +       if (flags & MS_STRICTATIME)
1066 +               audit_log_format(ab, ", strictatime");
1067 +       if (flags & MS_NOUSER)
1068 +               audit_log_format(ab, ", nouser");
1069 +}
1070 +
1071 +/**
1072 + * audit_cb - call back for mount specific audit fields
1073 + * @ab: audit_buffer  (NOT NULL)
1074 + * @va: audit struct to audit values of  (NOT NULL)
1075 + */
1076 +static void audit_cb(struct audit_buffer *ab, void *va)
1077 +{
1078 +       struct common_audit_data *sa = va;
1079 +
1080 +       if (sa->aad->mnt.type) {
1081 +               audit_log_format(ab, " fstype=");
1082 +               audit_log_untrustedstring(ab, sa->aad->mnt.type);
1083 +       }
1084 +       if (sa->aad->mnt.src_name) {
1085 +               audit_log_format(ab, " srcname=");
1086 +               audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
1087 +       }
1088 +       if (sa->aad->mnt.trans) {
1089 +               audit_log_format(ab, " trans=");
1090 +               audit_log_untrustedstring(ab, sa->aad->mnt.trans);
1091 +       }
1092 +       if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
1093 +               audit_log_format(ab, " flags=\"");
1094 +               audit_mnt_flags(ab, sa->aad->mnt.flags);
1095 +               audit_log_format(ab, "\"");
1096 +       }
1097 +       if (sa->aad->mnt.data) {
1098 +               audit_log_format(ab, " options=");
1099 +               audit_log_untrustedstring(ab, sa->aad->mnt.data);
1100 +       }
1101 +}
1102 +
1103 +/**
1104 + * audit_mount - handle the auditing of mount operations
1105 + * @profile: the profile being enforced  (NOT NULL)
1106 + * @gfp: allocation flags
1107 + * @op: operation being mediated (NOT NULL)
1108 + * @name: name of object being mediated (MAYBE NULL)
1109 + * @src_name: src_name of object being mediated (MAYBE_NULL)
1110 + * @type: type of filesystem (MAYBE_NULL)
1111 + * @trans: name of trans (MAYBE NULL)
1112 + * @flags: filesystem idependent mount flags
1113 + * @data: filesystem mount flags
1114 + * @request: permissions requested
1115 + * @perms: the permissions computed for the request (NOT NULL)
1116 + * @info: extra information message (MAYBE NULL)
1117 + * @error: 0 if operation allowed else failure error code
1118 + *
1119 + * Returns: %0 or error on failure
1120 + */
1121 +static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
1122 +                      const char *name, const char *src_name,
1123 +                      const char *type, const char *trans,
1124 +                      unsigned long flags, const void *data, u32 request,
1125 +                      struct file_perms *perms, const char *info, int error)
1126 +{
1127 +       int audit_type = AUDIT_APPARMOR_AUTO;
1128 +       struct common_audit_data sa = { };
1129 +       struct apparmor_audit_data aad = { };
1130 +
1131 +       if (likely(!error)) {
1132 +               u32 mask = perms->audit;
1133 +
1134 +               if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
1135 +                       mask = 0xffff;
1136 +
1137 +               /* mask off perms that are not being force audited */
1138 +               request &= mask;
1139 +
1140 +               if (likely(!request))
1141 +                       return 0;
1142 +               audit_type = AUDIT_APPARMOR_AUDIT;
1143 +       } else {
1144 +               /* only report permissions that were denied */
1145 +               request = request & ~perms->allow;
1146 +
1147 +               if (request & perms->kill)
1148 +                       audit_type = AUDIT_APPARMOR_KILL;
1149 +
1150 +               /* quiet known rejects, assumes quiet and kill do not overlap */
1151 +               if ((request & perms->quiet) &&
1152 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1153 +                   AUDIT_MODE(profile) != AUDIT_ALL)
1154 +                       request &= ~perms->quiet;
1155 +
1156 +               if (!request)
1157 +                       return COMPLAIN_MODE(profile) ?
1158 +                               complain_error(error) : error;
1159 +       }
1160 +
1161 +       sa.type = LSM_AUDIT_DATA_NONE;
1162 +       sa.aad = &aad;
1163 +       sa.aad->op = op;
1164 +       sa.aad->name = name;
1165 +       sa.aad->mnt.src_name = src_name;
1166 +       sa.aad->mnt.type = type;
1167 +       sa.aad->mnt.trans = trans;
1168 +       sa.aad->mnt.flags = flags;
1169 +       if (data && (perms->audit & AA_AUDIT_DATA))
1170 +               sa.aad->mnt.data = data;
1171 +       sa.aad->info = info;
1172 +       sa.aad->error = error;
1173 +
1174 +       return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
1175 +}
1176 +
1177 +/**
1178 + * match_mnt_flags - Do an ordered match on mount flags
1179 + * @dfa: dfa to match against
1180 + * @state: state to start in
1181 + * @flags: mount flags to match against
1182 + *
1183 + * Mount flags are encoded as an ordered match. This is done instead of
1184 + * checking against a simple bitmask, to allow for logical operations
1185 + * on the flags.
1186 + *
1187 + * Returns: next state after flags match
1188 + */
1189 +static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
1190 +                                   unsigned long flags)
1191 +{
1192 +       unsigned int i;
1193 +
1194 +       for (i = 0; i <= 31 ; ++i) {
1195 +               if ((1 << i) & flags)
1196 +                       state = aa_dfa_next(dfa, state, i + 1);
1197 +       }
1198 +
1199 +       return state;
1200 +}
1201 +
1202 +/**
1203 + * compute_mnt_perms - compute mount permission associated with @state
1204 + * @dfa: dfa to match against (NOT NULL)
1205 + * @state: state match finished in
1206 + *
1207 + * Returns: mount permissions
1208 + */
1209 +static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
1210 +                                          unsigned int state)
1211 +{
1212 +       struct file_perms perms;
1213 +
1214 +       perms.kill = 0;
1215 +       perms.allow = dfa_user_allow(dfa, state);
1216 +       perms.audit = dfa_user_audit(dfa, state);
1217 +       perms.quiet = dfa_user_quiet(dfa, state);
1218 +       perms.xindex = dfa_user_xindex(dfa, state);
1219 +
1220 +       return perms;
1221 +}
1222 +
1223 +static const char const *mnt_info_table[] = {
1224 +       "match succeeded",
1225 +       "failed mntpnt match",
1226 +       "failed srcname match",
1227 +       "failed type match",
1228 +       "failed flags match",
1229 +       "failed data match"
1230 +};
1231 +
1232 +/*
1233 + * Returns 0 on success else element that match failed in, this is the
1234 + * index into the mnt_info_table above
1235 + */
1236 +static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
1237 +                       const char *mntpnt, const char *devname,
1238 +                       const char *type, unsigned long flags,
1239 +                       void *data, bool binary, struct file_perms *perms)
1240 +{
1241 +       unsigned int state;
1242 +
1243 +       state = aa_dfa_match(dfa, start, mntpnt);
1244 +       state = aa_dfa_null_transition(dfa, state);
1245 +       if (!state)
1246 +               return 1;
1247 +
1248 +       if (devname)
1249 +               state = aa_dfa_match(dfa, state, devname);
1250 +       state = aa_dfa_null_transition(dfa, state);
1251 +       if (!state)
1252 +               return 2;
1253 +
1254 +       if (type)
1255 +               state = aa_dfa_match(dfa, state, type);
1256 +       state = aa_dfa_null_transition(dfa, state);
1257 +       if (!state)
1258 +               return 3;
1259 +
1260 +       state = match_mnt_flags(dfa, state, flags);
1261 +       if (!state)
1262 +               return 4;
1263 +       *perms = compute_mnt_perms(dfa, state);
1264 +       if (perms->allow & AA_MAY_MOUNT)
1265 +               return 0;
1266 +
1267 +       /* only match data if not binary and the DFA flags data is expected */
1268 +       if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
1269 +               state = aa_dfa_null_transition(dfa, state);
1270 +               if (!state)
1271 +                       return 4;
1272 +
1273 +               state = aa_dfa_match(dfa, state, data);
1274 +               if (!state)
1275 +                       return 5;
1276 +               *perms = compute_mnt_perms(dfa, state);
1277 +               if (perms->allow & AA_MAY_MOUNT)
1278 +                       return 0;
1279 +       }
1280 +
1281 +       /* failed at end of flags match */
1282 +       return 4;
1283 +}
1284 +
1285 +/**
1286 + * match_mnt - handle path matching for mount
1287 + * @profile: the confining profile
1288 + * @mntpnt: string for the mntpnt (NOT NULL)
1289 + * @devname: string for the devname/src_name (MAYBE NULL)
1290 + * @type: string for the dev type (MAYBE NULL)
1291 + * @flags: mount flags to match
1292 + * @data: fs mount data (MAYBE NULL)
1293 + * @binary: whether @data is binary
1294 + * @perms: Returns: permission found by the match
1295 + * @info: Returns: infomation string about the match for logging
1296 + *
1297 + * Returns: 0 on success else error
1298 + */
1299 +static int match_mnt(struct aa_profile *profile, const char *mntpnt,
1300 +                    const char *devname, const char *type,
1301 +                    unsigned long flags, void *data, bool binary,
1302 +                    struct file_perms *perms, const char **info)
1303 +{
1304 +       int pos;
1305 +
1306 +       if (!profile->policy.dfa)
1307 +               return -EACCES;
1308 +
1309 +       pos = do_match_mnt(profile->policy.dfa,
1310 +                          profile->policy.start[AA_CLASS_MOUNT],
1311 +                          mntpnt, devname, type, flags, data, binary, perms);
1312 +       if (pos) {
1313 +               *info = mnt_info_table[pos];
1314 +               return -EACCES;
1315 +       }
1316 +
1317 +       return 0;
1318 +}
1319 +
1320 +static int path_flags(struct aa_profile *profile, struct path *path)
1321 +{
1322 +       return profile->path_flags |
1323 +               S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
1324 +}
1325 +
1326 +int aa_remount(struct aa_profile *profile, struct path *path,
1327 +              unsigned long flags, void *data)
1328 +{
1329 +       struct file_perms perms = { };
1330 +       const char *name, *info = NULL;
1331 +       char *buffer = NULL;
1332 +       int binary, error;
1333 +
1334 +       binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
1335 +
1336 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1337 +                            &info);
1338 +       if (error)
1339 +               goto audit;
1340 +
1341 +       error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
1342 +                         &perms, &info);
1343 +
1344 +audit:
1345 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1346 +                           NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1347 +                           error);
1348 +       kfree(buffer);
1349 +
1350 +       return error;
1351 +}
1352 +
1353 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
1354 +                 const char *dev_name, unsigned long flags)
1355 +{
1356 +       struct file_perms perms = { };
1357 +       char *buffer = NULL, *old_buffer = NULL;
1358 +       const char *name, *old_name = NULL, *info = NULL;
1359 +       struct path old_path;
1360 +       int error;
1361 +
1362 +       if (!dev_name || !*dev_name)
1363 +               return -EINVAL;
1364 +
1365 +       flags &= MS_REC | MS_BIND;
1366 +
1367 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1368 +                            &info);
1369 +       if (error)
1370 +               goto audit;
1371 +
1372 +       error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1373 +       if (error)
1374 +               goto audit;
1375 +
1376 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
1377 +                            &old_buffer, &old_name, &info);
1378 +       path_put(&old_path);
1379 +       if (error)
1380 +               goto audit;
1381 +
1382 +       error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
1383 +                         &perms, &info);
1384 +
1385 +audit:
1386 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1387 +                           NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
1388 +                           info, error);
1389 +       kfree(buffer);
1390 +       kfree(old_buffer);
1391 +
1392 +       return error;
1393 +}
1394 +
1395 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
1396 +                        unsigned long flags)
1397 +{
1398 +       struct file_perms perms = { };
1399 +       char *buffer = NULL;
1400 +       const char *name, *info = NULL;
1401 +       int error;
1402 +
1403 +       /* These are the flags allowed by do_change_type() */
1404 +       flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
1405 +                 MS_UNBINDABLE);
1406 +
1407 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1408 +                            &info);
1409 +       if (error)
1410 +               goto audit;
1411 +
1412 +       error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
1413 +                         &info);
1414 +
1415 +audit:
1416 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1417 +                           NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
1418 +                           error);
1419 +       kfree(buffer);
1420 +
1421 +       return error;
1422 +}
1423 +
1424 +int aa_move_mount(struct aa_profile *profile, struct path *path,
1425 +                 const char *orig_name)
1426 +{
1427 +       struct file_perms perms = { };
1428 +       char *buffer = NULL, *old_buffer = NULL;
1429 +       const char *name, *old_name = NULL, *info = NULL;
1430 +       struct path old_path;
1431 +       int error;
1432 +
1433 +       if (!orig_name || !*orig_name)
1434 +               return -EINVAL;
1435 +
1436 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1437 +                            &info);
1438 +       if (error)
1439 +               goto audit;
1440 +
1441 +       error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
1442 +       if (error)
1443 +               goto audit;
1444 +
1445 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
1446 +                            &old_buffer, &old_name, &info);
1447 +       path_put(&old_path);
1448 +       if (error)
1449 +               goto audit;
1450 +
1451 +       error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
1452 +                         &perms, &info);
1453 +
1454 +audit:
1455 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1456 +                           NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
1457 +                           info, error);
1458 +       kfree(buffer);
1459 +       kfree(old_buffer);
1460 +
1461 +       return error;
1462 +}
1463 +
1464 +int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
1465 +                struct path *path, const char *type, unsigned long flags,
1466 +                void *data)
1467 +{
1468 +       struct file_perms perms = { };
1469 +       char *buffer = NULL, *dev_buffer = NULL;
1470 +       const char *name = NULL, *dev_name = NULL, *info = NULL;
1471 +       int binary = 1;
1472 +       int error;
1473 +
1474 +       dev_name = orig_dev_name;
1475 +       if (type) {
1476 +               int requires_dev;
1477 +               struct file_system_type *fstype = get_fs_type(type);
1478 +               if (!fstype)
1479 +                       return -ENODEV;
1480 +
1481 +               binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
1482 +               requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
1483 +               put_filesystem(fstype);
1484 +
1485 +               if (requires_dev) {
1486 +                       struct path dev_path;
1487 +
1488 +                       if (!dev_name || !*dev_name) {
1489 +                               error = -ENOENT;
1490 +                               goto out;
1491 +                       }
1492 +
1493 +                       error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
1494 +                       if (error)
1495 +                               goto audit;
1496 +
1497 +                       error = aa_path_name(&dev_path,
1498 +                                            path_flags(profile, &dev_path),
1499 +                                            &dev_buffer, &dev_name, &info);
1500 +                       path_put(&dev_path);
1501 +                       if (error)
1502 +                               goto audit;
1503 +               }
1504 +       }
1505 +
1506 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1507 +                            &info);
1508 +       if (error)
1509 +               goto audit;
1510 +
1511 +       error = match_mnt(profile, name, dev_name, type, flags, data, binary,
1512 +                         &perms, &info);
1513 +
1514 +audit:
1515 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,  dev_name,
1516 +                           type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1517 +                           error);
1518 +       kfree(buffer);
1519 +       kfree(dev_buffer);
1520 +
1521 +out:
1522 +       return error;
1523 +
1524 +}
1525 +
1526 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
1527 +{
1528 +       struct file_perms perms = { };
1529 +       char *buffer = NULL;
1530 +       const char *name, *info = NULL;
1531 +       int error;
1532 +
1533 +       struct path path = { mnt, mnt->mnt_root };
1534 +       error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
1535 +                            &info);
1536 +       if (error)
1537 +               goto audit;
1538 +
1539 +       if (!error && profile->policy.dfa) {
1540 +               unsigned int state;
1541 +               state = aa_dfa_match(profile->policy.dfa,
1542 +                                    profile->policy.start[AA_CLASS_MOUNT],
1543 +                                    name);
1544 +               perms = compute_mnt_perms(profile->policy.dfa, state);
1545 +       }
1546 +
1547 +       if (AA_MAY_UMOUNT & ~perms.allow)
1548 +               error = -EACCES;
1549 +
1550 +audit:
1551 +       error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
1552 +                           NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
1553 +       kfree(buffer);
1554 +
1555 +       return error;
1556 +}
1557 +
1558 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
1559 +                 struct path *new_path)
1560 +{
1561 +       struct file_perms perms = { };
1562 +       struct aa_profile *target = NULL;
1563 +       char *old_buffer = NULL, *new_buffer = NULL;
1564 +       const char *old_name, *new_name = NULL, *info = NULL;
1565 +       int error;
1566 +
1567 +       error = aa_path_name(old_path, path_flags(profile, old_path),
1568 +                            &old_buffer, &old_name, &info);
1569 +       if (error)
1570 +               goto audit;
1571 +
1572 +       error = aa_path_name(new_path, path_flags(profile, new_path),
1573 +                            &new_buffer, &new_name, &info);
1574 +       if (error)
1575 +               goto audit;
1576 +
1577 +       if (profile->policy.dfa) {
1578 +               unsigned int state;
1579 +               state = aa_dfa_match(profile->policy.dfa,
1580 +                                    profile->policy.start[AA_CLASS_MOUNT],
1581 +                                    new_name);
1582 +               state = aa_dfa_null_transition(profile->policy.dfa, state);
1583 +               state = aa_dfa_match(profile->policy.dfa, state, old_name);
1584 +               perms = compute_mnt_perms(profile->policy.dfa, state);
1585 +       }
1586 +
1587 +       if (AA_MAY_PIVOTROOT & perms.allow) {
1588 +               if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
1589 +                       target = x_table_lookup(profile, perms.xindex);
1590 +                       if (!target)
1591 +                               error = -ENOENT;
1592 +                       else
1593 +                               error = aa_replace_current_profile(target);
1594 +               }
1595 +       } else
1596 +               error = -EACCES;
1597 +
1598 +audit:
1599 +       error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
1600 +                           old_name, NULL, target ? target->base.name : NULL,
1601 +                           0, NULL,  AA_MAY_PIVOTROOT, &perms, info, error);
1602 +       aa_put_profile(target);
1603 +       kfree(old_buffer);
1604 +       kfree(new_buffer);
1605 +
1606 +       return error;
1607 +}
1608 -- 
1609 1.8.3.2
1610
1611 patches.apparmor/apparmor-temporary-work-around-for-bug-while-unloadi
1612 From: John Johansen <john.johansen@canonical.com>
1613 Date: Thu, 1 Oct 2015 11:57:52 -0700
1614 Subject: [PATCH] apparmor: temporary work around for bug while unloading policy
1615 Patch-mainline: TBD
1616 References: boo#941867
1617
1618 Buglink: https://bugzilla.opensuse.org/show_bug.cgi?id=941867
1619
1620 This patch will stop the bug() call from triggering while unloading/
1621 replacing policy. It does not address the root cause of the issue
1622 but will only cause some memory leakage of the sub policies that
1623 should have been freed before the current profile being destroyed.
1624
1625 Signed-off-by: John Johansen <john.johansen@canonical.com>
1626 Acked-by: Takashi Iwai <tiwai@suse.de>
1627
1628 ---
1629  security/apparmor/policy.c |    2 --
1630  1 file changed, 2 deletions(-)
1631
1632 --- a/security/apparmor/policy.c
1633 +++ b/security/apparmor/policy.c
1634 @@ -157,12 +157,10 @@ static void policy_destroy(struct aa_pol
1635                 AA_ERROR("%s: internal error, "
1636                          "policy '%s' still contains profiles\n",
1637                          __func__, policy->name);
1638 -               BUG();
1639         }
1640         if (on_list_rcu(&policy->list)) {
1641                 AA_ERROR("%s: internal error, policy '%s' still on list\n",
1642                          __func__, policy->name);
1643 -               BUG();
1644         }
1645  
1646         /* don't free name as its a subset of hname */
1647 patches.apparmor/apparmor-fix-refcount-bug-in-profile-replacement
1648 From dcda617a0c5160c73e0aa02813c871339ea08004 Mon Sep 17 00:00:00 2001
1649 From: John Johansen <john.johansen@canonical.com>
1650 Date: Mon, 11 Apr 2016 16:55:10 -0700
1651 Subject: [PATCH] apparmor: fix refcount bug in profile replacement
1652 Git-commit: dcda617a0c5160c73e0aa02813c871339ea08004
1653 Patch-mainline: 4.8-rc1
1654 References: bsc#1000304
1655
1656 Signed-off-by: John Johansen <john.johansen@canonical.com>
1657 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1658 Acked-by: Takashi Iwai <tiwai@suse.de>
1659
1660 ---
1661  security/apparmor/policy.c |    4 ++--
1662  1 file changed, 2 insertions(+), 2 deletions(-)
1663
1664 --- a/security/apparmor/policy.c
1665 +++ b/security/apparmor/policy.c
1666 @@ -1188,12 +1188,12 @@ ssize_t aa_replace_profiles(void *udata,
1667                                 aa_get_profile(newest);
1668                                 aa_put_profile(parent);
1669                                 rcu_assign_pointer(ent->new->parent, newest);
1670 -                       } else
1671 -                               aa_put_profile(newest);
1672 +                       }
1673                         /* aafs interface uses replacedby */
1674                         rcu_assign_pointer(ent->new->replacedby->profile,
1675                                            aa_get_profile(ent->new));
1676                         __list_add_profile(&parent->base.profiles, ent->new);
1677 +                       aa_put_profile(newest);
1678                 } else {
1679                         /* aafs interface uses replacedby */
1680                         rcu_assign_pointer(ent->new->replacedby->profile,
1681 patches.apparmor/apparmor-fix-replacement-bug-that-adds-new-child-to-
1682 From ec34fa24a934f4c8fd68f39b84abf34c42e5b06a Mon Sep 17 00:00:00 2001
1683 From: John Johansen <john.johansen@canonical.com>
1684 Date: Mon, 11 Apr 2016 16:57:19 -0700
1685 Subject: [PATCH] apparmor: fix replacement bug that adds new child to old parent
1686 Git-commit: ec34fa24a934f4c8fd68f39b84abf34c42e5b06a
1687 Patch-mainline: 4.8-rc1
1688 References: bsc#1000304
1689
1690 When set atomic replacement is used and the parent is updated before the
1691 child, and the child did not exist in the old parent so there is no
1692 direct replacement then the new child is incorrectly added to the old
1693 parent. This results in the new parent not having the child(ren) that
1694 it should and the old parent when being destroyed asserting the
1695 following error.
1696
1697 Apparmor: policy_destroy: internal error, policy '<profile/name>' still
1698 contains profiles
1699
1700 Signed-off-by: John Johansen <john.johansen@canonical.com>
1701 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1702 Acked-by: Takashi Iwai <tiwai@suse.de>
1703
1704 ---
1705  security/apparmor/policy.c |    2 +-
1706  1 file changed, 1 insertion(+), 1 deletion(-)
1707
1708 --- a/security/apparmor/policy.c
1709 +++ b/security/apparmor/policy.c
1710 @@ -1192,7 +1192,7 @@ ssize_t aa_replace_profiles(void *udata,
1711                         /* aafs interface uses replacedby */
1712                         rcu_assign_pointer(ent->new->replacedby->profile,
1713                                            aa_get_profile(ent->new));
1714 -                       __list_add_profile(&parent->base.profiles, ent->new);
1715 +                       __list_add_profile(&newest->base.profiles, ent->new);
1716                         aa_put_profile(newest);
1717                 } else {
1718                         /* aafs interface uses replacedby */
1719 patches.apparmor/apparmor-fix-uninitialized-lsm_audit-member
1720 From b6b1b81b3afba922505b57f4c812bba022f7c4a9 Mon Sep 17 00:00:00 2001
1721 From: John Johansen <john.johansen@canonical.com>
1722 Date: Sun, 8 Jun 2014 11:20:54 -0700
1723 Subject: [PATCH] apparmor: fix uninitialized lsm_audit member
1724 Git-commit: b6b1b81b3afba922505b57f4c812bba022f7c4a9
1725 Patch-mainline: 4.8-rc1
1726 References: bsc#1000304
1727
1728 Buglink: http://bugs.launchpad.net/bugs/1268727
1729
1730 The task field in the lsm_audit struct needs to be initialized if
1731 a change_hat fails, otherwise the following oops will occur
1732
1733 Bug: unable to handle kernel paging request at 0000002fbead7d08
1734 Ip: [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
1735 PGD 1e3f35067 PUD 0
1736 Oops: 0002 [#1] SMP
1737 Modules linked in: pppox crc_ccitt p8023 p8022 psnap llc ax25 btrfs raid6_pq xor xfs libcrc32c dm_multipath scsi_dh kvm_amd dcdbas kvm microcode amd64_edac_mod joydev edac_core psmouse edac_mce_amd serio_raw k10temp sp5100_tco i2c_piix4 ipmi_si ipmi_msghandler acpi_power_meter mac_hid lp parport hid_generic usbhid hid pata_acpi mpt2sas ahci raid_class pata_atiixp bnx2 libahci scsi_transport_sas [last unloaded: tipc]
1738 Cpu: 2 PID: 699 Comm: changehat_twice Tainted: GF          O 3.13.0-7-generic #25-Ubuntu
1739 Hardware name: Dell Inc. PowerEdge R415/08WNM9, BIOS 1.8.6 12/06/2011
1740 Task: ffff8802135c6000 ti: ffff880212986000 task.ti: ffff880212986000
1741 Rip: 0010:[<ffffffff8171153e>]  [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
1742 Rsp: 0018:ffff880212987b68  EFLAGS: 00010006
1743 Rax: 0000000000020000 RBX: 0000002fbead7500 RCX: 0000000000000000
1744 Rdx: 0000000000000292 RSI: ffff880212987ba8 RDI: 0000002fbead7d08
1745 Rbp: ffff880212987b68 R08: 0000000000000246 R09: ffff880216e572a0
1746 R10: ffffffff815fd677 R11: ffffea0008469580 R12: ffffffff8130966f
1747 R13: ffff880212987ba8 R14: 0000002fbead7d08 R15: ffff8800d8c6b830
1748 Fs: 00002b5e6c84e7c0(0000) GS:ffff880216e40000(0000) knlGS:0000000055731700
1749 Cs: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
1750 Cr2: 0000002fbead7d08 CR3: 000000021270f000 CR4: 00000000000006e0
1751 Stack: ffff880212987b98 ffffffff81075f17 ffffffff8130966f 0000000000000009 0000000000000000 0000000000000000 ffff880212987bd0 ffffffff81075f7c 0000000000000292 ffff880212987c08 ffff8800d8c6b800 0000000000000026
1752 Call Trace:
1753  [<ffffffff81075f17>] __lock_task_sighand+0x47/0x80
1754  [<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
1755  [<ffffffff81075f7c>] do_send_sig_info+0x2c/0x80
1756  [<ffffffff81075fee>] send_sig_info+0x1e/0x30
1757  [<ffffffff8130242d>] aa_audit+0x13d/0x190
1758  [<ffffffff8130c1dc>] aa_audit_file+0xbc/0x130
1759  [<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
1760  [<ffffffff81304cc2>] aa_change_hat+0x202/0x530
1761  [<ffffffff81308fc6>] aa_setprocattr_changehat+0x116/0x1d0
1762  [<ffffffff8130a11d>] apparmor_setprocattr+0x25d/0x300
1763  [<ffffffff812cee56>] security_setprocattr+0x16/0x20
1764  [<ffffffff8121fc87>] proc_pid_attr_write+0x107/0x130
1765  [<ffffffff811b7604>] vfs_write+0xb4/0x1f0
1766  [<ffffffff811b8039>] SyS_write+0x49/0xa0
1767  [<ffffffff8171a1bf>] tracesys+0xe1/0xe6
1768
1769 Signed-off-by: John Johansen <john.johansen@canonical.com>
1770 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1771 Acked-by: Takashi Iwai <tiwai@suse.de>
1772
1773 ---
1774  security/apparmor/audit.c |    3 ++-
1775  security/apparmor/file.c  |    3 ++-
1776  2 files changed, 4 insertions(+), 2 deletions(-)
1777
1778 --- a/security/apparmor/audit.c
1779 +++ b/security/apparmor/audit.c
1780 @@ -200,7 +200,8 @@ int aa_audit(int type, struct aa_profile
1781  
1782         if (sa->aad->type == AUDIT_APPARMOR_KILL)
1783                 (void)send_sig_info(SIGKILL, NULL,
1784 -                                   sa->u.tsk ?  sa->u.tsk : current);
1785 +                       sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
1786 +                                   sa->u.tsk : current);
1787  
1788         if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
1789                 return complain_error(sa->aad->error);
1790 --- a/security/apparmor/file.c
1791 +++ b/security/apparmor/file.c
1792 @@ -110,7 +110,8 @@ int aa_audit_file(struct aa_profile *pro
1793         int type = AUDIT_APPARMOR_AUTO;
1794         struct common_audit_data sa;
1795         struct apparmor_audit_data aad = {0,};
1796 -       sa.type = LSM_AUDIT_DATA_NONE;
1797 +       sa.type = LSM_AUDIT_DATA_TASK;
1798 +       sa.u.tsk = NULL;
1799         sa.aad = &aad;
1800         aad.op = op,
1801         aad.fs.request = request;
1802 patches.apparmor/apparmor-exec-should-not-be-returning-ENOENT-when-it
1803 From 9049a7922124d843a2cd26a02b1d00a17596ec0c Mon Sep 17 00:00:00 2001
1804 From: John Johansen <john.johansen@canonical.com>
1805 Date: Fri, 25 Jul 2014 04:02:03 -0700
1806 Subject: [PATCH] apparmor: exec should not be returning ENOENT when it denies
1807 Git-commit: 9049a7922124d843a2cd26a02b1d00a17596ec0c
1808 Patch-mainline: 4.8-rc1
1809 References: bsc#1000304
1810
1811 The current behavior is confusing as it causes exec failures to report
1812 the executable is missing instead of identifying that apparmor
1813 caused the failure.
1814
1815 Signed-off-by: John Johansen <john.johansen@canonical.com>
1816 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1817 Acked-by: Takashi Iwai <tiwai@suse.de>
1818
1819 ---
1820  security/apparmor/domain.c |    2 +-
1821  1 file changed, 1 insertion(+), 1 deletion(-)
1822
1823 --- a/security/apparmor/domain.c
1824 +++ b/security/apparmor/domain.c
1825 @@ -433,7 +433,7 @@ int apparmor_bprm_set_creds(struct linux
1826                                 new_profile = aa_get_newest_profile(ns->unconfined);
1827                                 info = "ux fallback";
1828                         } else {
1829 -                               error = -ENOENT;
1830 +                               error = -EACCES;
1831                                 info = "profile not found";
1832                                 /* remove MAY_EXEC to audit as failure */
1833                                 perms.allow &= ~MAY_EXEC;
1834 patches.apparmor/apparmor-fix-update-the-mtime-of-the-profile-file-on
1835 From d671e890205a663429da74e1972e652bea4d73ab Mon Sep 17 00:00:00 2001
1836 From: John Johansen <john.johansen@canonical.com>
1837 Date: Fri, 25 Jul 2014 04:01:56 -0700
1838 Subject: [PATCH] apparmor: fix update the mtime of the profile file on replacement
1839 Git-commit: d671e890205a663429da74e1972e652bea4d73ab
1840 Patch-mainline: 4.8-rc1
1841 References: bsc#1000304
1842
1843 Signed-off-by: John Johansen <john.johansen@canonical.com>
1844 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1845 Acked-by: Takashi Iwai <tiwai@suse.de>
1846
1847 ---
1848  security/apparmor/apparmorfs.c |    2 ++
1849  1 file changed, 2 insertions(+)
1850
1851 --- a/security/apparmor/apparmorfs.c
1852 +++ b/security/apparmor/apparmorfs.c
1853 @@ -380,6 +380,8 @@ void __aa_fs_profile_migrate_dents(struc
1854  
1855         for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
1856                 new->dents[i] = old->dents[i];
1857 +               if (new->dents[i])
1858 +                       new->dents[i]->d_inode->i_mtime = CURRENT_TIME;
1859                 old->dents[i] = NULL;
1860         }
1861  }
1862 patches.apparmor/apparmor-fix-disconnected-bind-mnts-reconnection
1863 From f2e561d190da7ff5ee265fa460e2d7f753dddfda Mon Sep 17 00:00:00 2001
1864 From: John Johansen <john.johansen@canonical.com>
1865 Date: Fri, 25 Jul 2014 04:02:08 -0700
1866 Subject: [PATCH] apparmor: fix disconnected bind mnts reconnection
1867 Git-commit: f2e561d190da7ff5ee265fa460e2d7f753dddfda
1868 Patch-mainline: 4.8-rc1
1869 References: bsc#1000304
1870
1871 Bind mounts can fail to be properly reconnected when PATH_CONNECT is
1872 specified. Ensure that when PATH_CONNECT is specified the path has
1873 a root.
1874
1875 Buglink: http://bugs.launchpad.net/bugs/1319984
1876
1877 Signed-off-by: John Johansen <john.johansen@canonical.com>
1878 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1879 Acked-by: Takashi Iwai <tiwai@suse.de>
1880
1881 ---
1882  security/apparmor/path.c |    5 ++++-
1883  1 file changed, 4 insertions(+), 1 deletion(-)
1884
1885 --- a/security/apparmor/path.c
1886 +++ b/security/apparmor/path.c
1887 @@ -141,7 +141,10 @@ static int d_namespace_path(struct path
1888                         error = -EACCES;
1889                         if (*res == '/')
1890                                 *name = res + 1;
1891 -               }
1892 +               } else if (*res != '/')
1893 +                       /* CONNECT_PATH with missing root */
1894 +                       error = prepend(name, *name - buf, "/", 1);
1895 +
1896         }
1897  
1898  out:
1899 patches.apparmor/apparmor-internal-paths-should-be-treated-as-disconn
1900 From bd35db8b8ca6e27fc17a9057ef78e1ddfc0de351 Mon Sep 17 00:00:00 2001
1901 From: John Johansen <john.johansen@canonical.com>
1902 Date: Fri, 25 Jul 2014 04:02:10 -0700
1903 Subject: [PATCH] apparmor: internal paths should be treated as disconnected
1904 Git-commit: bd35db8b8ca6e27fc17a9057ef78e1ddfc0de351
1905 Patch-mainline: 4.8-rc1
1906 References: bsc#1000304
1907
1908 Internal mounts are not mounted anywhere and as such should be treated
1909 as disconnected paths.
1910
1911 Signed-off-by: John Johansen <john.johansen@canonical.com>
1912 Acked-by: Seth Arnold <seth.arnold@canonical.com>
1913 Acked-by: Takashi Iwai <tiwai@suse.de>
1914
1915 ---
1916  security/apparmor/path.c |   64 ++++++++++++++++++++++++++---------------------
1917  1 file changed, 36 insertions(+), 28 deletions(-)
1918
1919 --- a/security/apparmor/path.c
1920 +++ b/security/apparmor/path.c
1921 @@ -25,7 +25,6 @@
1922  #include "include/path.h"
1923  #include "include/policy.h"
1924  
1925 -
1926  /* modified from dcache.c */
1927  static int prepend(char **buffer, int buflen, const char *str, int namelen)
1928  {
1929 @@ -39,6 +38,38 @@ static int prepend(char **buffer, int bu
1930  
1931  #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
1932  
1933 +/* If the path is not connected to the expected root,
1934 + * check if it is a sysctl and handle specially else remove any
1935 + * leading / that __d_path may have returned.
1936 + * Unless
1937 + *     specifically directed to connect the path,
1938 + * OR
1939 + *     if in a chroot and doing chroot relative paths and the path
1940 + *     resolves to the namespace root (would be connected outside
1941 + *     of chroot) and specifically directed to connect paths to
1942 + *     namespace root.
1943 + */
1944 +static int disconnect(const struct path *path, char *buf, char **name,
1945 +                     int flags)
1946 +{
1947 +       int error = 0;
1948 +
1949 +       if (!(flags & PATH_CONNECT_PATH) &&
1950 +           !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
1951 +             our_mnt(path->mnt))) {
1952 +               /* disconnected path, don't return pathname starting
1953 +                * with '/'
1954 +                */
1955 +               error = -EACCES;
1956 +               if (**name == '/')
1957 +                       *name = *name + 1;
1958 +       } else if (**name != '/')
1959 +               /* CONNECT_PATH with missing root */
1960 +               error = prepend(name, *name - buf, "/", 1);
1961 +
1962 +       return error;
1963 +}
1964 +
1965  /**
1966   * d_namespace_path - lookup a name associated with a given path
1967   * @path: path to lookup  (NOT NULL)
1968 @@ -74,7 +105,8 @@ static int d_namespace_path(struct path
1969                          * control instead of hard coded /proc
1970                          */
1971                         return prepend(name, *name - buf, "/proc", 5);
1972 -               }
1973 +               } else
1974 +                       return disconnect(path, buf, name, flags);
1975                 return 0;
1976         }
1977  
1978 @@ -120,32 +152,8 @@ static int d_namespace_path(struct path
1979                         goto out;
1980         }
1981  
1982 -       /* If the path is not connected to the expected root,
1983 -        * check if it is a sysctl and handle specially else remove any
1984 -        * leading / that __d_path may have returned.
1985 -        * Unless
1986 -        *     specifically directed to connect the path,
1987 -        * OR
1988 -        *     if in a chroot and doing chroot relative paths and the path
1989 -        *     resolves to the namespace root (would be connected outside
1990 -        *     of chroot) and specifically directed to connect paths to
1991 -        *     namespace root.
1992 -        */
1993 -       if (!connected) {
1994 -               if (!(flags & PATH_CONNECT_PATH) &&
1995 -                          !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
1996 -                            our_mnt(path->mnt))) {
1997 -                       /* disconnected path, don't return pathname starting
1998 -                        * with '/'
1999 -                        */
2000 -                       error = -EACCES;
2001 -                       if (*res == '/')
2002 -                               *name = res + 1;
2003 -               } else if (*res != '/')
2004 -                       /* CONNECT_PATH with missing root */
2005 -                       error = prepend(name, *name - buf, "/", 1);
2006 -
2007 -       }
2008 +       if (!connected)
2009 +               error = disconnect(path, buf, name, flags);
2010  
2011  out:
2012         return error;
2013 patches.apparmor/apparmor-fix-put-parent-ref-after-updating-the-activ
2014 From f351841f8d41072e741e45299070d421a5833a4a Mon Sep 17 00:00:00 2001
2015 From: John Johansen <john.johansen@canonical.com>
2016 Date: Sat, 16 Apr 2016 13:59:02 -0700
2017 Subject: [PATCH] apparmor: fix put() parent ref after updating the active ref
2018 Git-commit: f351841f8d41072e741e45299070d421a5833a4a
2019 Patch-mainline: 4.8-rc1
2020 References: bsc#1000304
2021
2022 Signed-off-by: John Johansen <john.johansen@canonical.com>
2023 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2024 Acked-by: Takashi Iwai <tiwai@suse.de>
2025
2026 ---
2027  security/apparmor/policy.c |    2 +-
2028  1 file changed, 1 insertion(+), 1 deletion(-)
2029
2030 --- a/security/apparmor/policy.c
2031 +++ b/security/apparmor/policy.c
2032 @@ -1186,8 +1186,8 @@ ssize_t aa_replace_profiles(void *udata,
2033                         /* parent replaced in this atomic set? */
2034                         if (newest != parent) {
2035                                 aa_get_profile(newest);
2036 -                               aa_put_profile(parent);
2037                                 rcu_assign_pointer(ent->new->parent, newest);
2038 +                               aa_put_profile(parent);
2039                         }
2040                         /* aafs interface uses replacedby */
2041                         rcu_assign_pointer(ent->new->replacedby->profile,
2042 patches.apparmor/apparmor-fix-log-failures-for-all-profiles-in-a-set
2043 From bf15cf0c641be8e57d45f110a9d91464f5bb461a Mon Sep 17 00:00:00 2001
2044 From: John Johansen <john.johansen@canonical.com>
2045 Date: Sat, 16 Apr 2016 14:16:50 -0700
2046 Subject: [PATCH] apparmor: fix log failures for all profiles in a set
2047 Git-commit: bf15cf0c641be8e57d45f110a9d91464f5bb461a
2048 Patch-mainline: 4.8-rc1
2049 References: bsc#1000304
2050
2051 currently only the profile that is causing the failure is logged. This
2052 makes it more confusing than necessary about which profiles loaded
2053 and which didn't. So make sure to log success and failure messages for
2054 all profiles in the set being loaded.
2055
2056 Signed-off-by: John Johansen <john.johansen@canonical.com>
2057 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2058 Acked-by: Takashi Iwai <tiwai@suse.de>
2059
2060 ---
2061  security/apparmor/policy.c |   29 +++++++++++++++++++----------
2062  1 file changed, 19 insertions(+), 10 deletions(-)
2063
2064 --- a/security/apparmor/policy.c
2065 +++ b/security/apparmor/policy.c
2066 @@ -1066,7 +1066,7 @@ static int __lookup_replace(struct aa_na
2067   */
2068  ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
2069  {
2070 -       const char *ns_name, *name = NULL, *info = NULL;
2071 +       const char *ns_name, *info = NULL;
2072         struct aa_namespace *ns = NULL;
2073         struct aa_load_ent *ent, *tmp;
2074         int op = OP_PROF_REPL;
2075 @@ -1081,18 +1081,15 @@ ssize_t aa_replace_profiles(void *udata,
2076         /* released below */
2077         ns = aa_prepare_namespace(ns_name);
2078         if (!ns) {
2079 -               info = "failed to prepare namespace";
2080 -               error = -ENOMEM;
2081 -               name = ns_name;
2082 -               goto fail;
2083 +               error = audit_policy(op, GFP_KERNEL, ns_name,
2084 +                                    "failed to prepare namespace", -ENOMEM);
2085 +               goto free;
2086         }
2087  
2088         mutex_lock(&ns->lock);
2089         /* setup parent and ns info */
2090         list_for_each_entry(ent, &lh, list) {
2091                 struct aa_policy *policy;
2092 -
2093 -               name = ent->new->base.hname;
2094                 error = __lookup_replace(ns, ent->new->base.hname, noreplace,
2095                                          &ent->old, &info);
2096                 if (error)
2097 @@ -1120,7 +1117,6 @@ ssize_t aa_replace_profiles(void *udata,
2098                         if (!p) {
2099                                 error = -ENOENT;
2100                                 info = "parent does not exist";
2101 -                               name = ent->new->base.hname;
2102                                 goto fail_lock;
2103                         }
2104                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
2105 @@ -1213,9 +1209,22 @@ out:
2106  
2107  fail_lock:
2108         mutex_unlock(&ns->lock);
2109 -fail:
2110 -       error = audit_policy(op, GFP_KERNEL, name, info, error);
2111  
2112 +       /* audit cause of failure */
2113 +       op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
2114 +       audit_policy(op, GFP_KERNEL, ent->new->base.hname, info, error);
2115 +       /* audit status that rest of profiles in the atomic set failed too */
2116 +       info = "valid profile in failed atomic policy load";
2117 +       list_for_each_entry(tmp, &lh, list) {
2118 +               if (tmp == ent) {
2119 +                       info = "unchecked profile in failed atomic policy load";
2120 +                       /* skip entry that caused failure */
2121 +                       continue;
2122 +               }
2123 +               op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
2124 +               audit_policy(op, GFP_KERNEL, tmp->new->base.hname, info, error);
2125 +       }
2126 +free:
2127         list_for_each_entry_safe(ent, tmp, &lh, list) {
2128                 list_del_init(&ent->list);
2129                 aa_load_ent_free(ent);
2130 patches.apparmor/apparmor-fix-audit-full-profile-hname-on-successful-
2131 From 7ee6da25dcce27b6023a8673fdf8be98dcf7cacf Mon Sep 17 00:00:00 2001
2132 From: John Johansen <john.johansen@canonical.com>
2133 Date: Sat, 16 Apr 2016 14:19:38 -0700
2134 Subject: [PATCH] apparmor: fix audit full profile hname on successful load
2135 Git-commit: 7ee6da25dcce27b6023a8673fdf8be98dcf7cacf
2136 Patch-mainline: 4.8-rc1
2137 References: bsc#1000304
2138
2139 Currently logging of a successful profile load only logs the basename
2140 of the profile. This can result in confusion when a child profile has
2141 the same name as the another profile in the set. Logging the hname
2142 will ensure there is no confusion.
2143
2144 Signed-off-by: John Johansen <john.johansen@canonical.com>
2145 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2146 Acked-by: Takashi Iwai <tiwai@suse.de>
2147
2148 ---
2149  security/apparmor/policy.c |    2 +-
2150  1 file changed, 1 insertion(+), 1 deletion(-)
2151
2152 --- a/security/apparmor/policy.c
2153 +++ b/security/apparmor/policy.c
2154 @@ -1158,7 +1158,7 @@ ssize_t aa_replace_profiles(void *udata,
2155                 list_del_init(&ent->list);
2156                 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
2157  
2158 -               audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
2159 +               audit_policy(op, GFP_ATOMIC, ent->new->base.hname, NULL, error);
2160  
2161                 if (ent->old) {
2162                         __replace_profile(ent->old, ent->new, 1);
2163 patches.apparmor/apparmor-ensure-the-target-profile-name-is-always-au
2164 From f7da2de01127b58d93cebeab165136d0998e7b1a Mon Sep 17 00:00:00 2001
2165 From: John Johansen <john.johansen@canonical.com>
2166 Date: Wed, 20 Apr 2016 14:18:18 -0700
2167 Subject: [PATCH] apparmor: ensure the target profile name is always audited
2168 Git-commit: f7da2de01127b58d93cebeab165136d0998e7b1a
2169 Patch-mainline: 4.8-rc1
2170 References: bsc#1000304
2171
2172 The target profile name was not being correctly audited in a few
2173 cases because the target variable was not being set and gotos
2174 passed the code to set it at apply:
2175
2176 Since it is always based on new_profile just drop the target var
2177 and conditionally report based on new_profile.
2178
2179 Signed-off-by: John Johansen <john.johansen@canonical.com>
2180 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2181 Acked-by: Takashi Iwai <tiwai@suse.de>
2182
2183 ---
2184  security/apparmor/domain.c |   20 +++++++++-----------
2185  1 file changed, 9 insertions(+), 11 deletions(-)
2186
2187 --- a/security/apparmor/domain.c
2188 +++ b/security/apparmor/domain.c
2189 @@ -346,7 +346,7 @@ int apparmor_bprm_set_creds(struct linux
2190                 file_inode(bprm->file)->i_uid,
2191                 file_inode(bprm->file)->i_mode
2192         };
2193 -       const char *name = NULL, *target = NULL, *info = NULL;
2194 +       const char *name = NULL, *info = NULL;
2195         int error = cap_bprm_set_creds(bprm);
2196         if (error)
2197                 return error;
2198 @@ -401,6 +401,7 @@ int apparmor_bprm_set_creds(struct linux
2199         if (cxt->onexec) {
2200                 struct file_perms cp;
2201                 info = "change_profile onexec";
2202 +               new_profile = aa_get_newest_profile(cxt->onexec);
2203                 if (!(perms.allow & AA_MAY_ONEXEC))
2204                         goto audit;
2205  
2206 @@ -415,7 +416,6 @@ int apparmor_bprm_set_creds(struct linux
2207  
2208                 if (!(cp.allow & AA_MAY_ONEXEC))
2209                         goto audit;
2210 -               new_profile = aa_get_newest_profile(cxt->onexec);
2211                 goto apply;
2212         }
2213  
2214 @@ -447,10 +447,8 @@ int apparmor_bprm_set_creds(struct linux
2215                 if (!new_profile) {
2216                         error = -ENOMEM;
2217                         info = "could not create null profile";
2218 -               } else {
2219 +               } else
2220                         error = -EACCES;
2221 -                       target = new_profile->base.hname;
2222 -               }
2223                 perms.xindex |= AA_X_UNSAFE;
2224         } else
2225                 /* fail exec */
2226 @@ -461,7 +459,6 @@ int apparmor_bprm_set_creds(struct linux
2227          * fail the exec.
2228          */
2229         if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
2230 -               aa_put_profile(new_profile);
2231                 error = -EPERM;
2232                 goto cleanup;
2233         }
2234 @@ -476,10 +473,8 @@ int apparmor_bprm_set_creds(struct linux
2235  
2236         if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2237                 error = may_change_ptraced_domain(new_profile);
2238 -               if (error) {
2239 -                       aa_put_profile(new_profile);
2240 +               if (error)
2241                         goto audit;
2242 -               }
2243         }
2244  
2245         /* Determine if secure exec is needed.
2246 @@ -500,7 +495,6 @@ int apparmor_bprm_set_creds(struct linux
2247                 bprm->unsafe |= AA_SECURE_X_NEEDED;
2248         }
2249  apply:
2250 -       target = new_profile->base.hname;
2251         /* when transitioning profiles clear unsafe personality bits */
2252         bprm->per_clear |= PER_CLEAR_ON_SETID;
2253  
2254 @@ -508,15 +502,19 @@ x_clear:
2255         aa_put_profile(cxt->profile);
2256         /* transfer new profile reference will be released when cxt is freed */
2257         cxt->profile = new_profile;
2258 +       new_profile = NULL;
2259  
2260         /* clear out all temporary/transitional state from the context */
2261         aa_clear_task_cxt_trans(cxt);
2262  
2263  audit:
2264         error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
2265 -                             name, target, cond.uid, info, error);
2266 +                             name,
2267 +                             new_profile ? new_profile->base.hname : NULL,
2268 +                             cond.uid, info, error);
2269  
2270  cleanup:
2271 +       aa_put_profile(new_profile);
2272         aa_put_profile(profile);
2273         kfree(buffer);
2274  
2275 patches.apparmor/apparmor-check-that-xindex-is-in-trans_table-bounds
2276 From 23ca7b640b4a55f8747301b6bd984dd05545f6a7 Mon Sep 17 00:00:00 2001
2277 From: John Johansen <john.johansen@canonical.com>
2278 Date: Thu, 17 Mar 2016 12:02:54 -0700
2279 Subject: [PATCH] apparmor: check that xindex is in trans_table bounds
2280 Git-commit: 23ca7b640b4a55f8747301b6bd984dd05545f6a7
2281 Patch-mainline: 4.8-rc1
2282 References: bsc#1000304
2283
2284 Signed-off-by: John Johansen <john.johansen@canonical.com>
2285 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2286 Acked-by: Takashi Iwai <tiwai@suse.de>
2287
2288 ---
2289  security/apparmor/policy_unpack.c |    2 +-
2290  1 file changed, 1 insertion(+), 1 deletion(-)
2291
2292 --- a/security/apparmor/policy_unpack.c
2293 +++ b/security/apparmor/policy_unpack.c
2294 @@ -722,7 +722,7 @@ static bool verify_xindex(int xindex, in
2295         int index, xtype;
2296         xtype = xindex & AA_X_TYPE_MASK;
2297         index = xindex & AA_X_INDEX_MASK;
2298 -       if (xtype == AA_X_TABLE && index > table_size)
2299 +       if (xtype == AA_X_TABLE && index >= table_size)
2300                 return 0;
2301         return 1;
2302  }
2303 patches.apparmor/apparmor-fix-refcount-race-when-finding-a-child-prof
2304 From de7c4cc947f9f56f61520ee7edaf380434a98c8d Mon Sep 17 00:00:00 2001
2305 From: John Johansen <john.johansen@canonical.com>
2306 Date: Wed, 16 Dec 2015 18:09:10 -0800
2307 Subject: [PATCH] apparmor: fix refcount race when finding a child profile
2308 Git-commit: de7c4cc947f9f56f61520ee7edaf380434a98c8d
2309 Patch-mainline: 4.8-rc1
2310 References: bsc#1000304
2311
2312 When finding a child profile via an rcu critical section, the profile
2313 may be put and scheduled for deletion after the child is found but
2314 before its refcount is incremented.
2315
2316 Protect against this by repeating the lookup if the profiles refcount
2317 is 0 and is one its way to deletion.
2318
2319 Signed-off-by: John Johansen <john.johansen@canonical.com>
2320 Acked-by: Seth Arnold <seth.arnold@canonical.com>
2321 Acked-by: Takashi Iwai <tiwai@suse.de>
2322
2323 ---
2324  security/apparmor/policy.c |    4 +++-
2325  1 file changed, 3 insertions(+), 1 deletion(-)
2326
2327 --- a/security/apparmor/policy.c
2328 +++ b/security/apparmor/policy.c
2329 @@ -765,7 +765,9 @@ struct aa_profile *aa_find_child(struct
2330         struct aa_profile *profile;
2331  
2332         rcu_read_lock();
2333 -       profile = aa_get_profile(__find_child(&parent->base.profiles, name));
2334 +       do {
2335 +               profile = __find_child(&parent->base.profiles, name);
2336 +       } while (profile && !aa_get_profile_not0(profile));
2337         rcu_read_unlock();
2338  
2339         /* refcount released by caller */
2340 patches.apparmor/apparmor-use-list_next_entry-instead-of-list_entry_n
2341 From 38dbd7d8be36b5e68c96a24b406f3653180c1c03 Mon Sep 17 00:00:00 2001
2342 From: Geliang Tang <geliangtang@163.com>
2343 Date: Mon, 16 Nov 2015 21:46:33 +0800
2344 Subject: [PATCH] apparmor: use list_next_entry instead of list_entry_next
2345 Git-commit: 38dbd7d8be36b5e68c96a24b406f3653180c1c03
2346 Patch-mainline: 4.8-rc1
2347 References: bsc#1000304
2348
2349 list_next_entry has been defined in list.h, so I replace list_entry_next
2350 with it.
2351
2352 Signed-off-by: Geliang Tang <geliangtang@163.com>
2353 Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
2354 Signed-off-by: John Johansen <john.johansen@canonical.com>
2355 Acked-by: Takashi Iwai <tiwai@suse.de>
2356
2357 ---
2358  security/apparmor/apparmorfs.c |    8 +++-----
2359  1 file changed, 3 insertions(+), 5 deletions(-)
2360
2361 --- a/security/apparmor/apparmorfs.c
2362 +++ b/security/apparmor/apparmorfs.c
2363 @@ -552,8 +552,6 @@ fail2:
2364  }
2365  
2366  
2367 -#define list_entry_next(pos, member) \
2368 -       list_entry(pos->member.next, typeof(*pos), member)
2369  #define list_entry_is_head(pos, head, member) (&pos->member == (head))
2370  
2371  /**
2372 @@ -584,7 +582,7 @@ static struct aa_namespace *__next_names
2373         parent = ns->parent;
2374         while (ns != root) {
2375                 mutex_unlock(&ns->lock);
2376 -               next = list_entry_next(ns, base.list);
2377 +               next = list_next_entry(ns, base.list);
2378                 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
2379                         mutex_lock(&next->lock);
2380                         return next;
2381 @@ -638,7 +636,7 @@ static struct aa_profile *__next_profile
2382         parent = rcu_dereference_protected(p->parent,
2383                                            mutex_is_locked(&p->ns->lock));
2384         while (parent) {
2385 -               p = list_entry_next(p, base.list);
2386 +               p = list_next_entry(p, base.list);
2387                 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
2388                         return p;
2389                 p = parent;
2390 @@ -647,7 +645,7 @@ static struct aa_profile *__next_profile
2391         }
2392  
2393         /* is next another profile in the namespace */
2394 -       p = list_entry_next(p, base.list);
2395 +       p = list_next_entry(p, base.list);
2396         if (!list_entry_is_head(p, &ns->base.profiles, base.list))
2397                 return p;
2398  
2399 patches.apparmor/apparmor-add-missing-id-bounds-check-on-dfa-verifica
2400 From 15756178c6a65b261a080e21af4766f59cafc112 Mon Sep 17 00:00:00 2001
2401 From: John Johansen <john.johansen@canonical.com>
2402 Date: Thu, 2 Jun 2016 02:37:02 -0700
2403 Subject: [PATCH] apparmor: add missing id bounds check on dfa verification
2404 Git-commit: 15756178c6a65b261a080e21af4766f59cafc112
2405 Patch-mainline: 4.8-rc1
2406 References: bsc#1000304
2407
2408 Signed-off-by: John Johansen <john.johansen@canonical.com>
2409 Acked-by: Takashi Iwai <tiwai@suse.de>
2410
2411 ---
2412  security/apparmor/include/match.h |    1 +
2413  security/apparmor/match.c         |    2 ++
2414  2 files changed, 3 insertions(+)
2415
2416 --- a/security/apparmor/include/match.h
2417 +++ b/security/apparmor/include/match.h
2418 @@ -62,6 +62,7 @@ struct table_set_header {
2419  #define YYTD_ID_ACCEPT2 6
2420  #define YYTD_ID_NXT    7
2421  #define YYTD_ID_TSIZE  8
2422 +#define YYTD_ID_MAX    8
2423  
2424  #define YYTD_DATA8     1
2425  #define YYTD_DATA16    2
2426 --- a/security/apparmor/match.c
2427 +++ b/security/apparmor/match.c
2428 @@ -47,6 +47,8 @@ static struct table_header *unpack_table
2429          * it every time we use td_id as an index
2430          */
2431         th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
2432 +       if (th.td_id > YYTD_ID_MAX)
2433 +               goto out;
2434         th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
2435         th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
2436         blob += sizeof(struct table_header);
2437 patches.apparmor/apparmor-don-t-check-for-vmalloc_addr-if-kvzalloc-fa
2438 From 3197f5adf539a3ee6331f433a51483f8c842f890 Mon Sep 17 00:00:00 2001
2439 From: John Johansen <john.johansen@canonical.com>
2440 Date: Wed, 15 Jun 2016 09:57:55 +0300
2441 Subject: [PATCH] apparmor: don't check for vmalloc_addr if kvzalloc() failed
2442 Git-commit: 3197f5adf539a3ee6331f433a51483f8c842f890
2443 Patch-mainline: 4.8-rc1
2444 References: bsc#1000304
2445
2446 Signed-off-by: John Johansen <john.johansen@canonical.com>
2447 Acked-by: Takashi Iwai <tiwai@suse.de>
2448
2449 ---
2450  security/apparmor/match.c |   10 +++++-----
2451  1 file changed, 5 insertions(+), 5 deletions(-)
2452
2453 --- a/security/apparmor/match.c
2454 +++ b/security/apparmor/match.c
2455 @@ -75,14 +75,14 @@ static struct table_header *unpack_table
2456                                      u32, be32_to_cpu);
2457                 else
2458                         goto fail;
2459 +               /* if table was vmalloced make sure the page tables are synced
2460 +                * before it is used, as it goes live to all cpus.
2461 +                */
2462 +               if (is_vmalloc_addr(table))
2463 +                       vm_unmap_aliases();
2464         }
2465  
2466  out:
2467 -       /* if table was vmalloced make sure the page tables are synced
2468 -        * before it is used, as it goes live to all cpus.
2469 -        */
2470 -       if (is_vmalloc_addr(table))
2471 -               vm_unmap_aliases();
2472         return table;
2473  fail:
2474         kvfree(table);
2475 patches.apparmor/apparmor-fix-oops-in-profile_unpack-when-policy_db-i
2476 From 5f20fdfed16bc599a325a145bf0123a8e1c9beea Mon Sep 17 00:00:00 2001
2477 From: John Johansen <john.johansen@canonical.com>
2478 Date: Wed, 15 Jun 2016 10:00:55 +0300
2479 Subject: [PATCH] apparmor: fix oops in profile_unpack() when policy_db is not present
2480 Git-commit: 5f20fdfed16bc599a325a145bf0123a8e1c9beea
2481 Patch-mainline: 4.8-rc1
2482 References: bsc#1000304
2483
2484 Buglink: http://bugs.launchpad.net/bugs/1592547
2485
2486 If unpack_dfa() returns NULL due to the dfa not being present,
2487 profile_unpack() is not checking if the dfa is not present (NULL).
2488
2489 Signed-off-by: John Johansen <john.johansen@canonical.com>
2490 Acked-by: Takashi Iwai <tiwai@suse.de>
2491
2492 ---
2493  security/apparmor/policy_unpack.c |    3 +++
2494  1 file changed, 3 insertions(+)
2495
2496 --- a/security/apparmor/policy_unpack.c
2497 +++ b/security/apparmor/policy_unpack.c
2498 @@ -629,6 +629,9 @@ static struct aa_profile *unpack_profile
2499                         error = PTR_ERR(profile->policy.dfa);
2500                         profile->policy.dfa = NULL;
2501                         goto fail;
2502 +               } else if (!profile->policy.dfa) {
2503 +                       error = -EPROTO;
2504 +                       goto fail;
2505                 }
2506                 if (!unpack_u32(e, &profile->policy.start[0], "start"))
2507                         /* default start state */
2508 patches.apparmor/apparmor-fix-module-parameters-can-be-changed-after-
2509 From 58acf9d911c8831156634a44d0b022d683e1e50c Mon Sep 17 00:00:00 2001
2510 From: John Johansen <john.johansen@canonical.com>
2511 Date: Wed, 22 Jun 2016 18:01:08 -0700
2512 Subject: [PATCH] apparmor: fix module parameters can be changed after policy is locked
2513 Git-commit: 58acf9d911c8831156634a44d0b022d683e1e50c
2514 Patch-mainline: 4.8-rc1
2515 References: bsc#1000304
2516
2517 the policy_lock parameter is a one way switch that prevents policy
2518 from being further modified. Unfortunately some of the module parameters
2519 can effectively modify policy by turning off enforcement.
2520
2521 split policy_admin_capable into a view check and a full admin check,
2522 and update the admin check to test the policy_lock parameter.
2523
2524 Signed-off-by: John Johansen <john.johansen@canonical.com>
2525 Acked-by: Takashi Iwai <tiwai@suse.de>
2526
2527 ---
2528  security/apparmor/include/policy.h |    2 ++
2529  security/apparmor/lsm.c            |   22 ++++++++++------------
2530  security/apparmor/policy.c         |   18 +++++++++++++++++-
2531  3 files changed, 29 insertions(+), 13 deletions(-)
2532
2533 --- a/security/apparmor/include/policy.h
2534 +++ b/security/apparmor/include/policy.h
2535 @@ -406,6 +406,8 @@ static inline int AUDIT_MODE(struct aa_p
2536         return profile->audit;
2537  }
2538  
2539 +bool policy_view_capable(void);
2540 +bool policy_admin_capable(void);
2541  bool aa_may_manage_policy(int op);
2542  
2543  #endif /* __AA_POLICY_H */
2544 --- a/security/apparmor/lsm.c
2545 +++ b/security/apparmor/lsm.c
2546 @@ -874,51 +874,49 @@ __setup("apparmor=", apparmor_enabled_se
2547  /* set global flag turning off the ability to load policy */
2548  static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp)
2549  {
2550 -       if (!capable(CAP_MAC_ADMIN))
2551 +       if (!policy_admin_capable())
2552                 return -EPERM;
2553 -       if (aa_g_lock_policy)
2554 -               return -EACCES;
2555         return param_set_bool(val, kp);
2556  }
2557  
2558  static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp)
2559  {
2560 -       if (!capable(CAP_MAC_ADMIN))
2561 +       if (!policy_view_capable())
2562                 return -EPERM;
2563         return param_get_bool(buffer, kp);
2564  }
2565  
2566  static int param_set_aabool(const char *val, const struct kernel_param *kp)
2567  {
2568 -       if (!capable(CAP_MAC_ADMIN))
2569 +       if (!policy_admin_capable())
2570                 return -EPERM;
2571         return param_set_bool(val, kp);
2572  }
2573  
2574  static int param_get_aabool(char *buffer, const struct kernel_param *kp)
2575  {
2576 -       if (!capable(CAP_MAC_ADMIN))
2577 +       if (!policy_view_capable())
2578                 return -EPERM;
2579         return param_get_bool(buffer, kp);
2580  }
2581  
2582  static int param_set_aauint(const char *val, const struct kernel_param *kp)
2583  {
2584 -       if (!capable(CAP_MAC_ADMIN))
2585 +       if (!policy_admin_capable())
2586                 return -EPERM;
2587         return param_set_uint(val, kp);
2588  }
2589  
2590  static int param_get_aauint(char *buffer, const struct kernel_param *kp)
2591  {
2592 -       if (!capable(CAP_MAC_ADMIN))
2593 +       if (!policy_view_capable())
2594                 return -EPERM;
2595         return param_get_uint(buffer, kp);
2596  }
2597  
2598  static int param_get_audit(char *buffer, struct kernel_param *kp)
2599  {
2600 -       if (!capable(CAP_MAC_ADMIN))
2601 +       if (!policy_view_capable())
2602                 return -EPERM;
2603  
2604         if (!apparmor_enabled)
2605 @@ -930,7 +928,7 @@ static int param_get_audit(char *buffer,
2606  static int param_set_audit(const char *val, struct kernel_param *kp)
2607  {
2608         int i;
2609 -       if (!capable(CAP_MAC_ADMIN))
2610 +       if (!policy_admin_capable())
2611                 return -EPERM;
2612  
2613         if (!apparmor_enabled)
2614 @@ -951,7 +949,7 @@ static int param_set_audit(const char *v
2615  
2616  static int param_get_mode(char *buffer, struct kernel_param *kp)
2617  {
2618 -       if (!capable(CAP_MAC_ADMIN))
2619 +       if (!policy_admin_capable())
2620                 return -EPERM;
2621  
2622         if (!apparmor_enabled)
2623 @@ -963,7 +961,7 @@ static int param_get_mode(char *buffer,
2624  static int param_set_mode(const char *val, struct kernel_param *kp)
2625  {
2626         int i;
2627 -       if (!capable(CAP_MAC_ADMIN))
2628 +       if (!policy_admin_capable())
2629                 return -EPERM;
2630  
2631         if (!apparmor_enabled)
2632 --- a/security/apparmor/policy.c
2633 +++ b/security/apparmor/policy.c
2634 @@ -917,6 +917,22 @@ static int audit_policy(int op, gfp_t gf
2635                         &sa, NULL);
2636  }
2637  
2638 +bool policy_view_capable(void)
2639 +{
2640 +       struct user_namespace *user_ns = current_user_ns();
2641 +       bool response = false;
2642 +
2643 +       if (ns_capable(user_ns, CAP_MAC_ADMIN))
2644 +               response = true;
2645 +
2646 +       return response;
2647 +}
2648 +
2649 +bool policy_admin_capable(void)
2650 +{
2651 +       return policy_view_capable() && !aa_g_lock_policy;
2652 +}
2653 +
2654  /**
2655   * aa_may_manage_policy - can the current task manage policy
2656   * @op: the policy manipulation operation being done
2657 @@ -931,7 +947,7 @@ bool aa_may_manage_policy(int op)
2658                 return 0;
2659         }
2660  
2661 -       if (!capable(CAP_MAC_ADMIN)) {
2662 +       if (!policy_admin_capable()) {
2663                 audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
2664                 return 0;
2665         }
2666 patches.apparmor/apparmor-do-not-expose-kernel-stack
2667 From f4ee2def2d70692ccff0d55353df4ee594fd0017 Mon Sep 17 00:00:00 2001
2668 From: Heinrich Schuchardt <xypron.glpk@gmx.de>
2669 Date: Fri, 10 Jun 2016 23:34:26 +0200
2670 Subject: [PATCH] apparmor: do not expose kernel stack
2671 Git-commit: f4ee2def2d70692ccff0d55353df4ee594fd0017
2672 Patch-mainline: 4.8-rc1
2673 References: bsc#1000304
2674
2675 Do not copy uninitalized fields th.td_hilen, th.td_data.
2676
2677 Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
2678 Signed-off-by: John Johansen <john.johansen@canonical.com>
2679 Acked-by: Takashi Iwai <tiwai@suse.de>
2680
2681 ---
2682  security/apparmor/match.c |    4 +++-
2683  1 file changed, 3 insertions(+), 1 deletion(-)
2684
2685 --- a/security/apparmor/match.c
2686 +++ b/security/apparmor/match.c
2687 @@ -63,7 +63,9 @@ static struct table_header *unpack_table
2688  
2689         table = kvzalloc(tsize);
2690         if (table) {
2691 -               *table = th;
2692 +               table->td_id = th.td_id;
2693 +               table->td_flags = th.td_flags;
2694 +               table->td_lolen = th.td_lolen;
2695                 if (th.td_flags == YYTD_DATA8)
2696                         UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
2697                                      u8, byte_to_byte);
2698 patches.apparmor/apparmor-fix-change_hat-not-finding-hat-after-policy-replacement.patch
2699 From: John Johansen <john.johansen@canonical.com>
2700 Date: Wed, 31 Aug 2016 21:10:06 -0700
2701 Subject: apparmor: fix change_hat not finding hat after policy replacement
2702 Git-commit: 3d40658c977769ce2138f286cf131537bf68bdfe
2703 Patch-mainline: 4.9-rc7
2704 References: bsc#1000287
2705
2706 After a policy replacement, the task cred may be out of date and need
2707 to be updated. However change_hat is using the stale profiles from
2708 the out of date cred resulting in either: a stale profile being applied
2709 or, incorrect failure when searching for a hat profile as it has been
2710 migrated to the new parent profile.
2711
2712 Fixes: 01e2b670aa898a39259bc85c78e3d74820f4d3b6 (failure to find hat)
2713 Fixes: 898127c34ec03291c86f4ff3856d79e9e18952bc (stale policy being applied)
2714 Signed-off-by: John Johansen <john.johansen@canonical.com>
2715 Acked-by: Jeff Mahoney <jeffm@suse.com>
2716 ---
2717  security/apparmor/domain.c | 6 ++++--
2718  1 file changed, 4 insertions(+), 2 deletions(-)
2719
2720 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
2721 index f2a83b4..dbd68f2 100644
2722 --- a/security/apparmor/domain.c
2723 +++ b/security/apparmor/domain.c
2724 @@ -621,8 +621,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
2725         /* released below */
2726         cred = get_current_cred();
2727         cxt = cred_cxt(cred);
2728 -       profile = aa_cred_profile(cred);
2729 -       previous_profile = cxt->previous;
2730 +       profile = aa_get_newest_profile(aa_cred_profile(cred));
2731 +       previous_profile = aa_get_newest_profile(cxt->previous);
2732  
2733         if (unconfined(profile)) {
2734                 info = "unconfined";
2735 @@ -718,6 +718,8 @@ audit:
2736  out:
2737         aa_put_profile(hat);
2738         kfree(name);
2739 +       aa_put_profile(profile);
2740 +       aa_put_profile(previous_profile);
2741         put_cred(cred);
2742  
2743         return error;
2744
This page took 0.274981 seconds and 3 git commands to generate.