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
6 Base support for network mediation.
8 Signed-off-by: John Johansen <john.johansen@canonical.com>
11 security/apparmor/Makefile
12 security/apparmor/policy.c
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
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
34 # Generated include files
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
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
51 -clean-files := capability_names.h rlim_names.h
52 +clean-files := capability_names.h rlim_names.h net_names.h
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/' >> $@
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 */
68 +# and build the securityfs entries for the mapping.
69 +# Transforms lines from
70 +# #define AF_INET 2 /* Internet IP Protocol */
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';\
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/' >> $@
82 +# Build a lower case string table of sock type names
83 +# Transform lines from
87 +quiet_cmd_make-sock = GEN $@
88 +cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
90 + -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
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/' >> $@
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 \
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 \
106 $(call cmd,make-rlim)
107 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
108 + $(srctree)/include/linux/net.h \
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 {
133 + int type, protocol;
139 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
141 index 0000000..cb8a121
143 +++ b/security/apparmor/include/net.h
146 + * AppArmor security module
148 + * This file contains AppArmor network mediation definitions.
150 + * Copyright (C) 1998-2008 Novell/SUSE
151 + * Copyright 2009-2012 Canonical Ltd.
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
162 +#include <net/sock.h>
164 +#include "apparmorfs.h"
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
177 +extern struct aa_fs_entry aa_fs_entry_network[];
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);
183 +static inline void aa_free_net_rules(struct aa_net *new)
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
194 #include "capability.h"
198 #include "resource.h"
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
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;
214 struct aa_rlimit rlimits;
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
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,
233 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
235 + struct aa_profile *profile;
241 + profile = __aa_current_profile();
242 + if (!unconfined(profile))
243 + error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
248 +static int apparmor_socket_bind(struct socket *sock,
249 + struct sockaddr *address, int addrlen)
251 + struct sock *sk = sock->sk;
253 + return aa_revalidate_sk(OP_BIND, sk);
256 +static int apparmor_socket_connect(struct socket *sock,
257 + struct sockaddr *address, int addrlen)
259 + struct sock *sk = sock->sk;
261 + return aa_revalidate_sk(OP_CONNECT, sk);
264 +static int apparmor_socket_listen(struct socket *sock, int backlog)
266 + struct sock *sk = sock->sk;
268 + return aa_revalidate_sk(OP_LISTEN, sk);
271 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
273 + struct sock *sk = sock->sk;
275 + return aa_revalidate_sk(OP_ACCEPT, sk);
278 +static int apparmor_socket_sendmsg(struct socket *sock,
279 + struct msghdr *msg, int size)
281 + struct sock *sk = sock->sk;
283 + return aa_revalidate_sk(OP_SENDMSG, sk);
286 +static int apparmor_socket_recvmsg(struct socket *sock,
287 + struct msghdr *msg, int size, int flags)
289 + struct sock *sk = sock->sk;
291 + return aa_revalidate_sk(OP_RECVMSG, sk);
294 +static int apparmor_socket_getsockname(struct socket *sock)
296 + struct sock *sk = sock->sk;
298 + return aa_revalidate_sk(OP_GETSOCKNAME, sk);
301 +static int apparmor_socket_getpeername(struct socket *sock)
303 + struct sock *sk = sock->sk;
305 + return aa_revalidate_sk(OP_GETPEERNAME, sk);
308 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
311 + struct sock *sk = sock->sk;
313 + return aa_revalidate_sk(OP_GETSOCKOPT, sk);
316 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
319 + struct sock *sk = sock->sk;
321 + return aa_revalidate_sk(OP_SETSOCKOPT, sk);
324 +static int apparmor_socket_shutdown(struct socket *sock, int how)
326 + struct sock *sk = sock->sk;
328 + return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
331 static struct security_operations apparmor_ops = {
334 @@ -647,6 +746,19 @@ static struct security_operations apparmor_ops = {
335 .getprocattr = apparmor_getprocattr,
336 .setprocattr = apparmor_setprocattr,
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,
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
356 index 0000000..003dd18
358 +++ b/security/apparmor/net.c
361 + * AppArmor security module
363 + * This file contains AppArmor network mediation
365 + * Copyright (C) 1998-2008 Novell/SUSE
366 + * Copyright 2009-2012 Canonical Ltd.
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
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"
380 +#include "net_names.h"
382 +struct aa_fs_entry aa_fs_entry_network[] = {
383 + AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
387 +/* audit callback for net specific fields */
388 +static void audit_cb(struct audit_buffer *ab, void *va)
390 + struct common_audit_data *sa = va;
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]);
396 + audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
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]);
402 + audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
404 + audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
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
417 + * Returns: %0 or sa->error else other errorcode on failure
419 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
420 + int protocol, struct sock *sk, int error)
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 = { };
427 + sa.type = LSM_AUDIT_DATA_NET;
429 + sa.type = LSM_AUDIT_DATA_NONE;
431 + /* todo fill in socket addr info */
435 + sa.u.net->family = family;
437 + sa.aad->net.type = type;
438 + sa.aad->net.protocol = protocol;
439 + sa.aad->error = error;
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)))
446 + audit_type = AUDIT_APPARMOR_AUDIT;
448 + u16 quiet_mask = profile->net.quiet[sa.u.net->family];
450 + u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
452 + if (denied & kill_mask)
453 + audit_type = AUDIT_APPARMOR_KILL;
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;
461 + return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
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
472 + * Returns: %0 else error if permission denied
474 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
475 + int protocol, struct sock *sk)
480 + if ((family < 0) || (family >= AF_MAX))
483 + if ((type < 0) || (type >= SOCK_MAX))
486 + /* unix domain and netlink sockets are handled by ipc */
487 + if (family == AF_UNIX || family == AF_NETLINK)
490 + family_mask = profile->net.allow[family];
492 + error = (family_mask & (1 << type)) ? 0 : -EACCES;
494 + return audit_net(profile, op, family, type, protocol, sk, error);
498 + * aa_revalidate_sk - Revalidate access to a sock
499 + * @op: operation being checked
500 + * @sk: sock being revalidated (NOT NULL)
502 + * Returns: %0 else error if permission denied
504 +int aa_revalidate_sk(int op, struct sock *sk)
506 + struct aa_profile *profile;
509 + /* aa_revalidate_sk should not be called from interrupt context
510 + * don't mediate these calls as they are not task related
512 + if (in_interrupt())
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);
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)
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);
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:
542 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
544 + if (unpack_nameX(e, AA_U16, name)) {
545 + if (!inbounds(e, sizeof(u16)))
548 + *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
549 + e->pos += sizeof(u16);
555 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
557 if (unpack_nameX(e, AA_U32, name)) {
558 @@ -476,6 +489,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
560 struct aa_profile *profile = NULL;
561 const char *name = NULL;
563 int i, error = -EPROTO;
566 @@ -576,6 +590,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
567 if (!unpack_rlimits(e, profile))
570 + size = unpack_array(e, "net_allowed_af");
573 + for (i = 0; i < size; i++) {
574 + /* discard extraneous rules that this kernel will
579 + if (!unpack_u16(e, &tmp, NULL) ||
580 + !unpack_u16(e, &tmp, NULL) ||
581 + !unpack_u16(e, &tmp, NULL))
585 + if (!unpack_u16(e, &profile->net.allow[i], NULL))
587 + if (!unpack_u16(e, &profile->net.audit[i], NULL))
589 + if (!unpack_u16(e, &profile->net.quiet[i], NULL))
592 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
596 + * allow unix domain and netlink sockets they are handled
599 + profile->net.allow[AF_UNIX] = 0xffff;
600 + profile->net.allow[AF_NETLINK] = 0xffff;
602 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
603 /* generic policy dfa - optional and may be NULL */
604 profile->policy.dfa = unpack_dfa(e);
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
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.
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.
625 Signed-off-by: John Johansen <john.johansen@canonical.com>
627 security/apparmor/net.c | 2 +-
628 1 file changed, 1 insertion(+), 1 deletion(-)
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,
636 u16 quiet_mask = profile->net.quiet[sa.u.net->family];
638 - u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
639 + u16 denied = (1 << sa.aad->net.type);
641 if (denied & kill_mask)
642 audit_type = AUDIT_APPARMOR_KILL;
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
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.
654 The basic form of the rules are.
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>
661 remount is just a short cut for mount options=remount
667 Example mount commands
668 mount, # allow all mounts, but not umount or pivotroot
670 mount fstype=procfs, # allow mounting procfs anywhere
672 mount options=(bind, ro) /foo -> /bar, # readonly bind mount
674 mount /dev/sda -> /mnt,
676 mount /dev/sd** -> /mnt/**,
678 mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
684 See the apparmor userspace for full documentation
686 Signed-off-by: John Johansen <john.johansen@canonical.com>
687 Acked-by: Kees Cook <kees@ubuntu.com>
690 security/apparmor/Makefile
691 security/apparmor/apparmorfs.c
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
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
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
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[] = {
726 static struct aa_fs_entry aa_fs_entry_policy[] = {
727 AA_FS_FILE_BOOLEAN("set_load", 1),
732 +static struct aa_fs_entry aa_fs_entry_mount[] = {
733 + AA_FS_FILE_STRING("mask", "mount umount"),
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),
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[] = {
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)
774 * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
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)
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
786 #define AA_CLASS_NET 4
787 #define AA_CLASS_RLIMITS 5
788 #define AA_CLASS_DOMAIN 6
789 +#define AA_CLASS_MOUNT 7
791 -#define AA_CLASS_LAST AA_CLASS_DOMAIN
792 +#define AA_CLASS_LAST AA_CLASS_MOUNT
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 {
811 @@ -121,6 +125,13 @@ struct apparmor_audit_data {
815 + const char *src_name;
819 + unsigned long flags;
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 {
833 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
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
840 index 0000000..bc17a53
842 +++ b/security/apparmor/include/mount.h
845 + * AppArmor security module
847 + * This file contains AppArmor file mediation function definitions.
849 + * Copyright 2012 Canonical Ltd.
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
857 +#ifndef __AA_MOUNT_H
858 +#define __AA_MOUNT_H
860 +#include <linux/fs.h>
861 +#include <linux/path.h>
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
873 +#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
875 +int aa_remount(struct aa_profile *profile, struct path *path,
876 + unsigned long flags, void *data);
878 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
879 + const char *old_name, unsigned long flags);
882 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
883 + unsigned long flags);
885 +int aa_move_mount(struct aa_profile *profile, struct path *path,
886 + const char *old_name);
888 +int aa_new_mount(struct aa_profile *profile, const char *dev_name,
889 + struct path *path, const char *type, unsigned long flags,
892 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
894 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
895 + struct path *new_path);
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
903 #include "include/path.h"
904 #include "include/policy.h"
905 #include "include/procattr.h"
906 +#include "include/mount.h"
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);
914 +static int apparmor_sb_mount(const char *dev_name, struct path *path, const char *type,
915 + unsigned long flags, void *data)
917 + struct aa_profile *profile;
920 + /* Discard magic */
921 + if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
922 + flags &= ~MS_MGC_MSK;
924 + flags &= ~AA_MS_IGNORE_MASK;
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 |
934 + error = aa_mount_change_type(profile, path, flags);
935 + else if (flags & MS_MOVE)
936 + error = aa_move_mount(profile, path, dev_name);
938 + error = aa_new_mount(profile, dev_name, path, type,
944 +static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
946 + struct aa_profile *profile;
949 + profile = __aa_current_profile();
950 + if (!unconfined(profile))
951 + error = aa_umount(profile, mnt, flags);
956 +static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
958 + struct aa_profile *profile;
961 + profile = __aa_current_profile();
962 + if (!unconfined(profile))
963 + error = aa_pivotroot(profile, old_path, new_path);
968 static int apparmor_getprocattr(struct task_struct *task, char *name,
971 @@ -722,6 +777,10 @@ static struct security_operations apparmor_ops = {
972 .capget = apparmor_capget,
973 .capable = apparmor_capable,
975 + .sb_mount = apparmor_sb_mount,
976 + .sb_umount = apparmor_sb_umount,
977 + .sb_pivotroot = apparmor_sb_pivotroot,
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
984 index 0000000..478aa4d
986 +++ b/security/apparmor/mount.c
989 + * AppArmor security module
991 + * This file contains AppArmor mediation of files
993 + * Copyright (C) 1998-2008 Novell/SUSE
994 + * Copyright 2009-2012 Canonical Ltd.
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
1002 +#include <linux/fs.h>
1003 +#include <linux/mount.h>
1004 +#include <linux/namei.h>
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"
1017 +static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
1019 + if (flags & MS_RDONLY)
1020 + audit_log_format(ab, "ro");
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" :
1052 + if (flags & MS_PRIVATE)
1053 + audit_log_format(ab, flags & MS_REC ? ", rprivate" :
1055 + if (flags & MS_SLAVE)
1056 + audit_log_format(ab, flags & MS_REC ? ", rslave" :
1058 + if (flags & MS_SHARED)
1059 + audit_log_format(ab, flags & MS_REC ? ", rshared" :
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");
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)
1076 +static void audit_cb(struct audit_buffer *ab, void *va)
1078 + struct common_audit_data *sa = va;
1080 + if (sa->aad->mnt.type) {
1081 + audit_log_format(ab, " fstype=");
1082 + audit_log_untrustedstring(ab, sa->aad->mnt.type);
1084 + if (sa->aad->mnt.src_name) {
1085 + audit_log_format(ab, " srcname=");
1086 + audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
1088 + if (sa->aad->mnt.trans) {
1089 + audit_log_format(ab, " trans=");
1090 + audit_log_untrustedstring(ab, sa->aad->mnt.trans);
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, "\"");
1097 + if (sa->aad->mnt.data) {
1098 + audit_log_format(ab, " options=");
1099 + audit_log_untrustedstring(ab, sa->aad->mnt.data);
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
1119 + * Returns: %0 or error on failure
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)
1127 + int audit_type = AUDIT_APPARMOR_AUTO;
1128 + struct common_audit_data sa = { };
1129 + struct apparmor_audit_data aad = { };
1131 + if (likely(!error)) {
1132 + u32 mask = perms->audit;
1134 + if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
1137 + /* mask off perms that are not being force audited */
1140 + if (likely(!request))
1142 + audit_type = AUDIT_APPARMOR_AUDIT;
1144 + /* only report permissions that were denied */
1145 + request = request & ~perms->allow;
1147 + if (request & perms->kill)
1148 + audit_type = AUDIT_APPARMOR_KILL;
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;
1157 + return COMPLAIN_MODE(profile) ?
1158 + complain_error(error) : error;
1161 + sa.type = LSM_AUDIT_DATA_NONE;
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;
1174 + return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
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
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
1187 + * Returns: next state after flags match
1189 +static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
1190 + unsigned long flags)
1194 + for (i = 0; i <= 31 ; ++i) {
1195 + if ((1 << i) & flags)
1196 + state = aa_dfa_next(dfa, state, i + 1);
1203 + * compute_mnt_perms - compute mount permission associated with @state
1204 + * @dfa: dfa to match against (NOT NULL)
1205 + * @state: state match finished in
1207 + * Returns: mount permissions
1209 +static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
1210 + unsigned int state)
1212 + struct file_perms perms;
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);
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"
1233 + * Returns 0 on success else element that match failed in, this is the
1234 + * index into the mnt_info_table above
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)
1241 + unsigned int state;
1243 + state = aa_dfa_match(dfa, start, mntpnt);
1244 + state = aa_dfa_null_transition(dfa, state);
1249 + state = aa_dfa_match(dfa, state, devname);
1250 + state = aa_dfa_null_transition(dfa, state);
1255 + state = aa_dfa_match(dfa, state, type);
1256 + state = aa_dfa_null_transition(dfa, state);
1260 + state = match_mnt_flags(dfa, state, flags);
1263 + *perms = compute_mnt_perms(dfa, state);
1264 + if (perms->allow & AA_MAY_MOUNT)
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);
1273 + state = aa_dfa_match(dfa, state, data);
1276 + *perms = compute_mnt_perms(dfa, state);
1277 + if (perms->allow & AA_MAY_MOUNT)
1281 + /* failed at end of flags match */
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
1297 + * Returns: 0 on success else error
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)
1306 + if (!profile->policy.dfa)
1309 + pos = do_match_mnt(profile->policy.dfa,
1310 + profile->policy.start[AA_CLASS_MOUNT],
1311 + mntpnt, devname, type, flags, data, binary, perms);
1313 + *info = mnt_info_table[pos];
1320 +static int path_flags(struct aa_profile *profile, struct path *path)
1322 + return profile->path_flags |
1323 + S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
1326 +int aa_remount(struct aa_profile *profile, struct path *path,
1327 + unsigned long flags, void *data)
1329 + struct file_perms perms = { };
1330 + const char *name, *info = NULL;
1331 + char *buffer = NULL;
1332 + int binary, error;
1334 + binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
1336 + error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1341 + error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
1345 + error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1346 + NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1353 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
1354 + const char *dev_name, unsigned long flags)
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;
1362 + if (!dev_name || !*dev_name)
1365 + flags &= MS_REC | MS_BIND;
1367 + error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1372 + error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1376 + error = aa_path_name(&old_path, path_flags(profile, &old_path),
1377 + &old_buffer, &old_name, &info);
1378 + path_put(&old_path);
1382 + error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
1386 + error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1387 + NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
1390 + kfree(old_buffer);
1395 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
1396 + unsigned long flags)
1398 + struct file_perms perms = { };
1399 + char *buffer = NULL;
1400 + const char *name, *info = NULL;
1403 + /* These are the flags allowed by do_change_type() */
1404 + flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
1407 + error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1412 + error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
1416 + error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1417 + NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
1424 +int aa_move_mount(struct aa_profile *profile, struct path *path,
1425 + const char *orig_name)
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;
1433 + if (!orig_name || !*orig_name)
1436 + error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1441 + error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
1445 + error = aa_path_name(&old_path, path_flags(profile, &old_path),
1446 + &old_buffer, &old_name, &info);
1447 + path_put(&old_path);
1451 + error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
1455 + error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1456 + NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
1459 + kfree(old_buffer);
1464 +int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
1465 + struct path *path, const char *type, unsigned long flags,
1468 + struct file_perms perms = { };
1469 + char *buffer = NULL, *dev_buffer = NULL;
1470 + const char *name = NULL, *dev_name = NULL, *info = NULL;
1474 + dev_name = orig_dev_name;
1477 + struct file_system_type *fstype = get_fs_type(type);
1481 + binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
1482 + requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
1483 + put_filesystem(fstype);
1485 + if (requires_dev) {
1486 + struct path dev_path;
1488 + if (!dev_name || !*dev_name) {
1493 + error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
1497 + error = aa_path_name(&dev_path,
1498 + path_flags(profile, &dev_path),
1499 + &dev_buffer, &dev_name, &info);
1500 + path_put(&dev_path);
1506 + error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1511 + error = match_mnt(profile, name, dev_name, type, flags, data, binary,
1515 + error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, dev_name,
1516 + type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1519 + kfree(dev_buffer);
1526 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
1528 + struct file_perms perms = { };
1529 + char *buffer = NULL;
1530 + const char *name, *info = NULL;
1533 + struct path path = { mnt, mnt->mnt_root };
1534 + error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
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],
1544 + perms = compute_mnt_perms(profile->policy.dfa, state);
1547 + if (AA_MAY_UMOUNT & ~perms.allow)
1551 + error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
1552 + NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
1558 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
1559 + struct path *new_path)
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;
1567 + error = aa_path_name(old_path, path_flags(profile, old_path),
1568 + &old_buffer, &old_name, &info);
1572 + error = aa_path_name(new_path, path_flags(profile, new_path),
1573 + &new_buffer, &new_name, &info);
1577 + if (profile->policy.dfa) {
1578 + unsigned int state;
1579 + state = aa_dfa_match(profile->policy.dfa,
1580 + profile->policy.start[AA_CLASS_MOUNT],
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);
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);
1593 + error = aa_replace_current_profile(target);
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);
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
1616 References: boo#941867
1618 Buglink: https://bugzilla.opensuse.org/show_bug.cgi?id=941867
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.
1625 Signed-off-by: John Johansen <john.johansen@canonical.com>
1626 Acked-by: Takashi Iwai <tiwai@suse.de>
1629 security/apparmor/policy.c | 2 --
1630 1 file changed, 2 deletions(-)
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);
1640 if (on_list_rcu(&policy->list)) {
1641 AA_ERROR("%s: internal error, policy '%s' still on list\n",
1642 __func__, policy->name);
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
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>
1661 security/apparmor/policy.c | 4 ++--
1662 1 file changed, 2 insertions(+), 2 deletions(-)
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);
1671 - aa_put_profile(newest);
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);
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
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
1697 Apparmor: policy_destroy: internal error, policy '<profile/name>' still
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>
1705 security/apparmor/policy.c | 2 +-
1706 1 file changed, 1 insertion(+), 1 deletion(-)
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);
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
1728 Buglink: http://bugs.launchpad.net/bugs/1268727
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
1733 Bug: unable to handle kernel paging request at 0000002fbead7d08
1734 Ip: [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
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
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
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>
1774 security/apparmor/audit.c | 3 ++-
1775 security/apparmor/file.c | 3 ++-
1776 2 files changed, 4 insertions(+), 2 deletions(-)
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
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);
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;
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
1811 The current behavior is confusing as it causes exec failures to report
1812 the executable is missing instead of identifying that apparmor
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>
1820 security/apparmor/domain.c | 2 +-
1821 1 file changed, 1 insertion(+), 1 deletion(-)
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";
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
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>
1848 security/apparmor/apparmorfs.c | 2 ++
1849 1 file changed, 2 insertions(+)
1851 --- a/security/apparmor/apparmorfs.c
1852 +++ b/security/apparmor/apparmorfs.c
1853 @@ -380,6 +380,8 @@ void __aa_fs_profile_migrate_dents(struc
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;
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
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
1875 Buglink: http://bugs.launchpad.net/bugs/1319984
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>
1882 security/apparmor/path.c | 5 ++++-
1883 1 file changed, 4 insertions(+), 1 deletion(-)
1885 --- a/security/apparmor/path.c
1886 +++ b/security/apparmor/path.c
1887 @@ -141,7 +141,10 @@ static int d_namespace_path(struct path
1892 + } else if (*res != '/')
1893 + /* CONNECT_PATH with missing root */
1894 + error = prepend(name, *name - buf, "/", 1);
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
1908 Internal mounts are not mounted anywhere and as such should be treated
1909 as disconnected paths.
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>
1916 security/apparmor/path.c | 64 ++++++++++++++++++++++++++---------------------
1917 1 file changed, 36 insertions(+), 28 deletions(-)
1919 --- a/security/apparmor/path.c
1920 +++ b/security/apparmor/path.c
1922 #include "include/path.h"
1923 #include "include/policy.h"
1926 /* modified from dcache.c */
1927 static int prepend(char **buffer, int buflen, const char *str, int namelen)
1929 @@ -39,6 +38,38 @@ static int prepend(char **buffer, int bu
1931 #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
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.
1937 + * specifically directed to connect the path,
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
1944 +static int disconnect(const struct path *path, char *buf, char **name,
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
1956 + if (**name == '/')
1957 + *name = *name + 1;
1958 + } else if (**name != '/')
1959 + /* CONNECT_PATH with missing root */
1960 + error = prepend(name, *name - buf, "/", 1);
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
1971 return prepend(name, *name - buf, "/proc", 5);
1974 + return disconnect(path, buf, name, flags);
1978 @@ -120,32 +152,8 @@ static int d_namespace_path(struct path
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.
1986 - * specifically directed to connect the path,
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
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
2003 - } else if (*res != '/')
2004 - /* CONNECT_PATH with missing root */
2005 - error = prepend(name, *name - buf, "/", 1);
2009 + error = disconnect(path, buf, name, flags);
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
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>
2027 security/apparmor/policy.c | 2 +-
2028 1 file changed, 1 insertion(+), 1 deletion(-)
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);
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
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.
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>
2061 security/apparmor/policy.c | 29 +++++++++++++++++++----------
2062 1 file changed, 19 insertions(+), 10 deletions(-)
2064 --- a/security/apparmor/policy.c
2065 +++ b/security/apparmor/policy.c
2066 @@ -1066,7 +1066,7 @@ static int __lookup_replace(struct aa_na
2068 ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
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);
2079 - info = "failed to prepare namespace";
2083 + error = audit_policy(op, GFP_KERNEL, ns_name,
2084 + "failed to prepare namespace", -ENOMEM);
2088 mutex_lock(&ns->lock);
2089 /* setup parent and ns info */
2090 list_for_each_entry(ent, &lh, list) {
2091 struct aa_policy *policy;
2093 - name = ent->new->base.hname;
2094 error = __lookup_replace(ns, ent->new->base.hname, noreplace,
2097 @@ -1120,7 +1117,6 @@ ssize_t aa_replace_profiles(void *udata,
2100 info = "parent does not exist";
2101 - name = ent->new->base.hname;
2104 rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
2105 @@ -1213,9 +1209,22 @@ out:
2108 mutex_unlock(&ns->lock);
2110 - error = audit_policy(op, GFP_KERNEL, name, info, error);
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) {
2119 + info = "unchecked profile in failed atomic policy load";
2120 + /* skip entry that caused failure */
2123 + op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
2124 + audit_policy(op, GFP_KERNEL, tmp->new->base.hname, info, error);
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
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.
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>
2149 security/apparmor/policy.c | 2 +-
2150 1 file changed, 1 insertion(+), 1 deletion(-)
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;
2158 - audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
2159 + audit_policy(op, GFP_ATOMIC, ent->new->base.hname, NULL, error);
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
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:
2176 Since it is always based on new_profile just drop the target var
2177 and conditionally report based on new_profile.
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>
2184 security/apparmor/domain.c | 20 +++++++++-----------
2185 1 file changed, 9 insertions(+), 11 deletions(-)
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
2193 - const char *name = NULL, *target = NULL, *info = NULL;
2194 + const char *name = NULL, *info = NULL;
2195 int error = cap_bprm_set_creds(bprm);
2198 @@ -401,6 +401,7 @@ int apparmor_bprm_set_creds(struct linux
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))
2206 @@ -415,7 +416,6 @@ int apparmor_bprm_set_creds(struct linux
2208 if (!(cp.allow & AA_MAY_ONEXEC))
2210 - new_profile = aa_get_newest_profile(cxt->onexec);
2214 @@ -447,10 +447,8 @@ int apparmor_bprm_set_creds(struct linux
2217 info = "could not create null profile";
2221 - target = new_profile->base.hname;
2223 perms.xindex |= AA_X_UNSAFE;
2226 @@ -461,7 +459,6 @@ int apparmor_bprm_set_creds(struct linux
2229 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
2230 - aa_put_profile(new_profile);
2234 @@ -476,10 +473,8 @@ int apparmor_bprm_set_creds(struct linux
2236 if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
2237 error = may_change_ptraced_domain(new_profile);
2239 - aa_put_profile(new_profile);
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;
2250 - target = new_profile->base.hname;
2251 /* when transitioning profiles clear unsafe personality bits */
2252 bprm->per_clear |= PER_CLEAR_ON_SETID;
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;
2260 /* clear out all temporary/transitional state from the context */
2261 aa_clear_task_cxt_trans(cxt);
2264 error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
2265 - name, target, cond.uid, info, error);
2267 + new_profile ? new_profile->base.hname : NULL,
2268 + cond.uid, info, error);
2271 + aa_put_profile(new_profile);
2272 aa_put_profile(profile);
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
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>
2289 security/apparmor/policy_unpack.c | 2 +-
2290 1 file changed, 1 insertion(+), 1 deletion(-)
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
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)
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
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.
2316 Protect against this by repeating the lookup if the profiles refcount
2317 is 0 and is one its way to deletion.
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>
2324 security/apparmor/policy.c | 4 +++-
2325 1 file changed, 3 insertions(+), 1 deletion(-)
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;
2333 - profile = aa_get_profile(__find_child(&parent->base.profiles, name));
2335 + profile = __find_child(&parent->base.profiles, name);
2336 + } while (profile && !aa_get_profile_not0(profile));
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
2349 list_next_entry has been defined in list.h, so I replace list_entry_next
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>
2358 security/apparmor/apparmorfs.c | 8 +++-----
2359 1 file changed, 3 insertions(+), 5 deletions(-)
2361 --- a/security/apparmor/apparmorfs.c
2362 +++ b/security/apparmor/apparmorfs.c
2363 @@ -552,8 +552,6 @@ fail2:
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))
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);
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));
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))
2390 @@ -647,7 +645,7 @@ static struct aa_profile *__next_profile
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))
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
2408 Signed-off-by: John Johansen <john.johansen@canonical.com>
2409 Acked-by: Takashi Iwai <tiwai@suse.de>
2412 security/apparmor/include/match.h | 1 +
2413 security/apparmor/match.c | 2 ++
2414 2 files changed, 3 insertions(+)
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
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
2431 th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
2432 + if (th.td_id > YYTD_ID_MAX)
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
2446 Signed-off-by: John Johansen <john.johansen@canonical.com>
2447 Acked-by: Takashi Iwai <tiwai@suse.de>
2450 security/apparmor/match.c | 10 +++++-----
2451 1 file changed, 5 insertions(+), 5 deletions(-)
2453 --- a/security/apparmor/match.c
2454 +++ b/security/apparmor/match.c
2455 @@ -75,14 +75,14 @@ static struct table_header *unpack_table
2459 + /* if table was vmalloced make sure the page tables are synced
2460 + * before it is used, as it goes live to all cpus.
2462 + if (is_vmalloc_addr(table))
2463 + vm_unmap_aliases();
2467 - /* if table was vmalloced make sure the page tables are synced
2468 - * before it is used, as it goes live to all cpus.
2470 - if (is_vmalloc_addr(table))
2471 - vm_unmap_aliases();
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
2484 Buglink: http://bugs.launchpad.net/bugs/1592547
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).
2489 Signed-off-by: John Johansen <john.johansen@canonical.com>
2490 Acked-by: Takashi Iwai <tiwai@suse.de>
2493 security/apparmor/policy_unpack.c | 3 +++
2494 1 file changed, 3 insertions(+)
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;
2502 + } else if (!profile->policy.dfa) {
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
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.
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.
2524 Signed-off-by: John Johansen <john.johansen@canonical.com>
2525 Acked-by: Takashi Iwai <tiwai@suse.de>
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(-)
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;
2539 +bool policy_view_capable(void);
2540 +bool policy_admin_capable(void);
2541 bool aa_may_manage_policy(int op);
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)
2550 - if (!capable(CAP_MAC_ADMIN))
2551 + if (!policy_admin_capable())
2553 - if (aa_g_lock_policy)
2555 return param_set_bool(val, kp);
2558 static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp)
2560 - if (!capable(CAP_MAC_ADMIN))
2561 + if (!policy_view_capable())
2563 return param_get_bool(buffer, kp);
2566 static int param_set_aabool(const char *val, const struct kernel_param *kp)
2568 - if (!capable(CAP_MAC_ADMIN))
2569 + if (!policy_admin_capable())
2571 return param_set_bool(val, kp);
2574 static int param_get_aabool(char *buffer, const struct kernel_param *kp)
2576 - if (!capable(CAP_MAC_ADMIN))
2577 + if (!policy_view_capable())
2579 return param_get_bool(buffer, kp);
2582 static int param_set_aauint(const char *val, const struct kernel_param *kp)
2584 - if (!capable(CAP_MAC_ADMIN))
2585 + if (!policy_admin_capable())
2587 return param_set_uint(val, kp);
2590 static int param_get_aauint(char *buffer, const struct kernel_param *kp)
2592 - if (!capable(CAP_MAC_ADMIN))
2593 + if (!policy_view_capable())
2595 return param_get_uint(buffer, kp);
2598 static int param_get_audit(char *buffer, struct kernel_param *kp)
2600 - if (!capable(CAP_MAC_ADMIN))
2601 + if (!policy_view_capable())
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)
2609 - if (!capable(CAP_MAC_ADMIN))
2610 + if (!policy_admin_capable())
2613 if (!apparmor_enabled)
2614 @@ -951,7 +949,7 @@ static int param_set_audit(const char *v
2616 static int param_get_mode(char *buffer, struct kernel_param *kp)
2618 - if (!capable(CAP_MAC_ADMIN))
2619 + if (!policy_admin_capable())
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)
2627 - if (!capable(CAP_MAC_ADMIN))
2628 + if (!policy_admin_capable())
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
2638 +bool policy_view_capable(void)
2640 + struct user_namespace *user_ns = current_user_ns();
2641 + bool response = false;
2643 + if (ns_capable(user_ns, CAP_MAC_ADMIN))
2649 +bool policy_admin_capable(void)
2651 + return policy_view_capable() && !aa_g_lock_policy;
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)
2661 - if (!capable(CAP_MAC_ADMIN)) {
2662 + if (!policy_admin_capable()) {
2663 audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
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
2675 Do not copy uninitalized fields th.td_hilen, th.td_data.
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>
2682 security/apparmor/match.c | 4 +++-
2683 1 file changed, 3 insertions(+), 1 deletion(-)
2685 --- a/security/apparmor/match.c
2686 +++ b/security/apparmor/match.c
2687 @@ -63,7 +63,9 @@ static struct table_header *unpack_table
2689 table = kvzalloc(tsize);
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,
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
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.
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>
2717 security/apparmor/domain.c | 6 ++++--
2718 1 file changed, 4 insertions(+), 2 deletions(-)
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);
2733 if (unconfined(profile)) {
2734 info = "unconfined";
2735 @@ -718,6 +718,8 @@ audit:
2737 aa_put_profile(hat);
2739 + aa_put_profile(profile);
2740 + aa_put_profile(previous_profile);