1 From 0ae314bc92d8b22250f04f85e4bd36ee9ed30890 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] AppArmor: compatibility patch for v5 network controll
6 Add compatibility for v5 network rules.
8 Signed-off-by: John Johansen <john.johansen@canonical.com>
10 include/linux/lsm_audit.h | 4 +
11 security/apparmor/Makefile | 19 ++++-
12 security/apparmor/include/net.h | 40 +++++++++
13 security/apparmor/include/policy.h | 3 +
14 security/apparmor/lsm.c | 112 +++++++++++++++++++++++
15 security/apparmor/net.c | 170 ++++++++++++++++++++++++++++++++++++
16 security/apparmor/policy.c | 1 +
17 security/apparmor/policy_unpack.c | 48 ++++++++++-
18 8 files changed, 394 insertions(+), 3 deletions(-)
19 create mode 100644 security/apparmor/include/net.h
20 create mode 100644 security/apparmor/net.c
22 diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
23 index 112a550..d5f3dd7 100644
24 --- a/include/linux/lsm_audit.h
25 +++ b/include/linux/lsm_audit.h
26 @@ -123,6 +123,10 @@ struct common_audit_data {
35 } apparmor_audit_data;
37 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
38 index 2dafe50..7cefef9 100644
39 --- a/security/apparmor/Makefile
40 +++ b/security/apparmor/Makefile
41 @@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
43 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
44 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
45 - resource.o sid.o file.o
46 + resource.o sid.o file.o net.o
48 -clean-files := capability_names.h rlim_names.h
49 +clean-files := capability_names.h rlim_names.h af_names.h
52 # Build a lower case string table of capability names
53 @@ -44,9 +44,24 @@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
54 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
57 +# Build a lower case string table of address family names.
58 +# Transform lines from
59 +# #define AF_INET 2 /* Internet IP Protocol */
62 +quiet_cmd_make-af = GEN $@
63 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
64 + sed $< >> $@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
65 + 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+).*/[\2] = "\L\1",/p';\
69 $(obj)/capability.o : $(obj)/capability_names.h
70 $(obj)/resource.o : $(obj)/rlim_names.h
71 +$(obj)/net.o : $(obj)/af_names.h
72 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
74 $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
76 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
78 \ No newline at end of file
79 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
81 index 0000000..3c7d599
83 +++ b/security/apparmor/include/net.h
86 + * AppArmor security module
88 + * This file contains AppArmor network mediation definitions.
90 + * Copyright (C) 1998-2008 Novell/SUSE
91 + * Copyright 2009-2010 Canonical Ltd.
93 + * This program is free software; you can redistribute it and/or
94 + * modify it under the terms of the GNU General Public License as
95 + * published by the Free Software Foundation, version 2 of the
102 +#include <net/sock.h>
104 +/* struct aa_net - network confinement data
105 + * @allowed: basic network families permissions
106 + * @audit_network: which network permissions to force audit
107 + * @quiet_network: which network permissions to quiet rejects
115 +extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
116 + int type, int protocol, struct sock *sk);
117 +extern int aa_revalidate_sk(int op, struct sock *sk);
119 +static inline void aa_free_net_rules(struct aa_net *new)
124 +#endif /* __AA_NET_H */
125 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
126 index aeda5cf..6776929 100644
127 --- a/security/apparmor/include/policy.h
128 +++ b/security/apparmor/include/policy.h
130 #include "capability.h"
134 #include "resource.h"
136 extern const char *profile_mode_names[];
137 @@ -145,6 +146,7 @@ struct aa_namespace {
138 * @size: the memory consumed by this profiles rules
139 * @file: The set of rules governing basic file access and domain transitions
140 * @caps: capabilities for the profile
141 + * @net: network controls for the profile
142 * @rlimits: rlimits for the profile
144 * The AppArmor profile contains the basic confinement data. Each profile
145 @@ -181,6 +183,7 @@ struct aa_profile {
147 struct aa_file_rules file;
150 struct aa_rlimit rlimits;
153 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
154 index ae3a698..05c018b 100644
155 --- a/security/apparmor/lsm.c
156 +++ b/security/apparmor/lsm.c
158 #include "include/context.h"
159 #include "include/file.h"
160 #include "include/ipc.h"
161 +#include "include/net.h"
162 #include "include/path.h"
163 #include "include/policy.h"
164 #include "include/procattr.h"
165 @@ -610,5 +611,103 @@ static int apparmor_task_setrlimit(struct task_struct *task,
169 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
171 + struct aa_profile *profile;
177 + profile = __aa_current_profile();
178 + if (!unconfined(profile))
179 + error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
184 +static int apparmor_socket_bind(struct socket *sock,
185 + struct sockaddr *address, int addrlen)
187 + struct sock *sk = sock->sk;
189 + return aa_revalidate_sk(OP_BIND, sk);
192 +static int apparmor_socket_connect(struct socket *sock,
193 + struct sockaddr *address, int addrlen)
195 + struct sock *sk = sock->sk;
197 + return aa_revalidate_sk(OP_CONNECT, sk);
200 +static int apparmor_socket_listen(struct socket *sock, int backlog)
202 + struct sock *sk = sock->sk;
204 + return aa_revalidate_sk(OP_LISTEN, sk);
207 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
209 + struct sock *sk = sock->sk;
211 + return aa_revalidate_sk(OP_ACCEPT, sk);
214 +static int apparmor_socket_sendmsg(struct socket *sock,
215 + struct msghdr *msg, int size)
217 + struct sock *sk = sock->sk;
219 + return aa_revalidate_sk(OP_SENDMSG, sk);
222 +static int apparmor_socket_recvmsg(struct socket *sock,
223 + struct msghdr *msg, int size, int flags)
225 + struct sock *sk = sock->sk;
227 + return aa_revalidate_sk(OP_RECVMSG, sk);
230 +static int apparmor_socket_getsockname(struct socket *sock)
232 + struct sock *sk = sock->sk;
234 + return aa_revalidate_sk(OP_GETSOCKNAME, sk);
237 +static int apparmor_socket_getpeername(struct socket *sock)
239 + struct sock *sk = sock->sk;
241 + return aa_revalidate_sk(OP_GETPEERNAME, sk);
244 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
247 + struct sock *sk = sock->sk;
249 + return aa_revalidate_sk(OP_GETSOCKOPT, sk);
252 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
255 + struct sock *sk = sock->sk;
257 + return aa_revalidate_sk(OP_SETSOCKOPT, sk);
260 +static int apparmor_socket_shutdown(struct socket *sock, int how)
262 + struct sock *sk = sock->sk;
264 + return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
267 static int apparmor_task_setrlimit(struct task_struct *task,
268 unsigned int resource, struct rlimit *new_rlim)
269 @@ -651,6 +750,19 @@ static struct security_operations apparmor_ops = {
270 .getprocattr = apparmor_getprocattr,
271 .setprocattr = apparmor_setprocattr,
273 + .socket_create = apparmor_socket_create,
274 + .socket_bind = apparmor_socket_bind,
275 + .socket_connect = apparmor_socket_connect,
276 + .socket_listen = apparmor_socket_listen,
277 + .socket_accept = apparmor_socket_accept,
278 + .socket_sendmsg = apparmor_socket_sendmsg,
279 + .socket_recvmsg = apparmor_socket_recvmsg,
280 + .socket_getsockname = apparmor_socket_getsockname,
281 + .socket_getpeername = apparmor_socket_getpeername,
282 + .socket_getsockopt = apparmor_socket_getsockopt,
283 + .socket_setsockopt = apparmor_socket_setsockopt,
284 + .socket_shutdown = apparmor_socket_shutdown,
286 .cred_alloc_blank = apparmor_cred_alloc_blank,
287 .cred_free = apparmor_cred_free,
288 .cred_prepare = apparmor_cred_prepare,
289 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
291 index 0000000..1765901
293 +++ b/security/apparmor/net.c
296 + * AppArmor security module
298 + * This file contains AppArmor network mediation
300 + * Copyright (C) 1998-2008 Novell/SUSE
301 + * Copyright 2009-2010 Canonical Ltd.
303 + * This program is free software; you can redistribute it and/or
304 + * modify it under the terms of the GNU General Public License as
305 + * published by the Free Software Foundation, version 2 of the
309 +#include "include/apparmor.h"
310 +#include "include/audit.h"
311 +#include "include/context.h"
312 +#include "include/net.h"
313 +#include "include/policy.h"
315 +#include "af_names.h"
317 +static const char *sock_type_names[] = {
331 +/* audit callback for net specific fields */
332 +static void audit_cb(struct audit_buffer *ab, void *va)
334 + struct common_audit_data *sa = va;
336 + audit_log_format(ab, " family=");
337 + if (address_family_names[sa->u.net.family]) {
338 + audit_log_string(ab, address_family_names[sa->u.net.family]);
340 + audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
343 + audit_log_format(ab, " sock_type=");
344 + if (sock_type_names[sa->aad.net.type]) {
345 + audit_log_string(ab, sock_type_names[sa->aad.net.type]);
347 + audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
350 + audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
354 + * audit_net - audit network access
355 + * @profile: profile being enforced (NOT NULL)
356 + * @op: operation being checked
357 + * @family: network family
358 + * @type: network type
359 + * @protocol: network protocol
360 + * @sk: socket auditing is being applied to
361 + * @error: error code for failure else 0
363 + * Returns: %0 or sa->error else other errorcode on failure
365 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
366 + int protocol, struct sock *sk, int error)
368 + int audit_type = AUDIT_APPARMOR_AUTO;
369 + struct common_audit_data sa;
371 + COMMON_AUDIT_DATA_INIT(&sa, NET);
373 + COMMON_AUDIT_DATA_INIT(&sa, NONE);
375 + /* todo fill in socket addr info */
378 + sa.u.net.family = family;
380 + sa.aad.net.type = type;
381 + sa.aad.net.protocol = protocol;
382 + sa.aad.error = error;
384 + if (likely(!sa.aad.error)) {
385 + u16 audit_mask = profile->net.audit[sa.u.net.family];
386 + if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
387 + !(1 << sa.aad.net.type & audit_mask)))
389 + audit_type = AUDIT_APPARMOR_AUDIT;
391 + u16 quiet_mask = profile->net.quiet[sa.u.net.family];
393 + u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
395 + if (denied & kill_mask)
396 + audit_type = AUDIT_APPARMOR_KILL;
398 + if ((denied & quiet_mask) &&
399 + AUDIT_MODE(profile) != AUDIT_NOQUIET &&
400 + AUDIT_MODE(profile) != AUDIT_ALL)
401 + return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
404 + return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
408 + * aa_net_perm - very course network access check
409 + * @op: operation being checked
410 + * @profile: profile being enforced (NOT NULL)
411 + * @family: network family
412 + * @type: network type
413 + * @protocol: network protocol
415 + * Returns: %0 else error if permission denied
417 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
418 + int protocol, struct sock *sk)
423 + if ((family < 0) || (family >= AF_MAX))
426 + if ((type < 0) || (type >= SOCK_MAX))
429 + /* unix domain and netlink sockets are handled by ipc */
430 + if (family == AF_UNIX || family == AF_NETLINK)
433 + family_mask = profile->net.allow[family];
435 + error = (family_mask & (1 << type)) ? 0 : -EACCES;
437 + return audit_net(profile, op, family, type, protocol, sk, error);
441 + * aa_revalidate_sk - Revalidate access to a sock
442 + * @op: operation being checked
443 + * @sk: sock being revalidated (NOT NULL)
445 + * Returns: %0 else error if permission denied
447 +int aa_revalidate_sk(int op, struct sock *sk)
449 + struct aa_profile *profile;
452 + /* aa_revalidate_sk should not be called from interrupt context
453 + * don't mediate these calls as they are not task related
455 + if (in_interrupt())
458 + profile = __aa_current_profile();
459 + if (!unconfined(profile))
460 + error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
461 + sk->sk_protocol, sk);
465 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
466 index 4f0eade..4d5ce13 100644
467 --- a/security/apparmor/policy.c
468 +++ b/security/apparmor/policy.c
469 @@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
471 aa_free_file_rules(&profile->file);
472 aa_free_cap_rules(&profile->caps);
473 + aa_free_net_rules(&profile->net);
474 aa_free_rlimit_rules(&profile->rlimits);
476 aa_free_sid(profile->sid);
477 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
478 index e33aaf7..fa3f1b4 100644
479 --- a/security/apparmor/policy_unpack.c
480 +++ b/security/apparmor/policy_unpack.c
481 @@ -190,6 +190,19 @@ fail:
485 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
487 + if (unpack_nameX(e, AA_U16, name)) {
488 + if (!inbounds(e, sizeof(u16)))
491 + *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
492 + e->pos += sizeof(u16);
498 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
500 if (unpack_nameX(e, AA_U32, name)) {
501 @@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
503 struct aa_profile *profile = NULL;
504 const char *name = NULL;
505 - int error = -EPROTO;
507 + int i, error = -EPROTO;
511 @@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
512 if (!unpack_rlimits(e, profile))
515 + size = unpack_array(e, "net_allowed_af");
518 + for (i = 0; i < size; i++) {
519 + /* discard extraneous rules that this kernel will
524 + if (!unpack_u16(e, &tmp, NULL) ||
525 + !unpack_u16(e, &tmp, NULL) ||
526 + !unpack_u16(e, &tmp, NULL))
530 + if (!unpack_u16(e, &profile->net.allow[i], NULL))
532 + if (!unpack_u16(e, &profile->net.audit[i], NULL))
534 + if (!unpack_u16(e, &profile->net.quiet[i], NULL))
537 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
540 + * allow unix domain and netlink sockets they are handled
544 + profile->net.allow[AF_UNIX] = 0xffff;
545 + profile->net.allow[AF_NETLINK] = 0xffff;
548 profile->file.dfa = unpack_dfa(e);
549 if (IS_ERR(profile->file.dfa)) {
553 From cdc6b35345e5bcfe92bb2b52ef003f94ceedd40d Mon Sep 17 00:00:00 2001
554 From: John Johansen <john.johansen@canonical.com>
555 Date: Thu, 22 Jul 2010 02:32:02 -0700
556 Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
558 Signed-off-by: John Johansen <john.johansen@canonical.com>
560 security/apparmor/Kconfig | 9 +
561 security/apparmor/Makefile | 1 +
562 security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
563 security/apparmor/apparmorfs.c | 18 ++-
564 security/apparmor/include/apparmorfs.h | 6 +
565 5 files changed, 319 insertions(+), 2 deletions(-)
566 create mode 100644 security/apparmor/apparmorfs-24.c
568 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
569 index 9b9013b..51ebf96 100644
570 --- a/security/apparmor/Kconfig
571 +++ b/security/apparmor/Kconfig
572 @@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
575 If you are unsure how to answer this question, answer 1.
577 +config SECURITY_APPARMOR_COMPAT_24
578 + bool "Enable AppArmor 2.4 compatability"
579 + depends on SECURITY_APPARMOR
582 + This option enables compatability with AppArmor 2.4. It is
583 + recommended if compatability with older versions of AppArmor
585 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
586 index 7cefef9..0bb604b 100644
587 --- a/security/apparmor/Makefile
588 +++ b/security/apparmor/Makefile
589 @@ -5,6 +5,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
590 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
591 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
592 resource.o sid.o file.o net.o
593 +apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
595 clean-files := capability_names.h rlim_names.h af_names.h
597 diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
599 index 0000000..dc8c744
601 +++ b/security/apparmor/apparmorfs-24.c
604 + * AppArmor security module
606 + * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
608 + * Copyright (C) 1998-2008 Novell/SUSE
609 + * Copyright 2009-2010 Canonical Ltd.
611 + * This program is free software; you can redistribute it and/or
612 + * modify it under the terms of the GNU General Public License as
613 + * published by the Free Software Foundation, version 2 of the
617 + * This file contain functions providing an interface for <= AppArmor 2.4
618 + * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
619 + * being set (see Makefile).
622 +#include <linux/security.h>
623 +#include <linux/vmalloc.h>
624 +#include <linux/module.h>
625 +#include <linux/seq_file.h>
626 +#include <linux/uaccess.h>
627 +#include <linux/namei.h>
629 +#include "include/apparmor.h"
630 +#include "include/audit.h"
631 +#include "include/context.h"
632 +#include "include/policy.h"
635 +/* apparmor/matching */
636 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
637 + size_t size, loff_t *ppos)
639 + const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
642 + return simple_read_from_buffer(buf, size, ppos, matching,
643 + sizeof(matching) - 1);
646 +const struct file_operations aa_fs_matching_fops = {
647 + .read = aa_matching_read,
650 +/* apparmor/features */
651 +static ssize_t aa_features_read(struct file *file, char __user *buf,
652 + size_t size, loff_t *ppos)
654 + const char features[] = "file=3.1 capability=2.0 network=1.0 "
655 + "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
657 + return simple_read_from_buffer(buf, size, ppos, features,
658 + sizeof(features) - 1);
661 +const struct file_operations aa_fs_features_fops = {
662 + .read = aa_features_read,
666 + * __next_namespace - find the next namespace to list
667 + * @root: root namespace to stop search at (NOT NULL)
668 + * @ns: current ns position (NOT NULL)
670 + * Find the next namespace from @ns under @root and handle all locking needed
671 + * while switching current namespace.
673 + * Returns: next namespace or NULL if at last namespace under @root
674 + * NOTE: will not unlock root->lock
676 +static struct aa_namespace *__next_namespace(struct aa_namespace *root,
677 + struct aa_namespace *ns)
679 + struct aa_namespace *parent;
681 + /* is next namespace a child */
682 + if (!list_empty(&ns->sub_ns)) {
683 + struct aa_namespace *next;
684 + next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
685 + read_lock(&next->lock);
689 + /* check if the next ns is a sibling, parent, gp, .. */
690 + parent = ns->parent;
692 + read_unlock(&ns->lock);
693 + list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
694 + read_lock(&ns->lock);
697 + if (parent == root)
700 + parent = parent->parent;
707 + * __first_profile - find the first profile in a namespace
708 + * @root: namespace that is root of profiles being displayed (NOT NULL)
709 + * @ns: namespace to start in (NOT NULL)
711 + * Returns: unrefcounted profile or NULL if no profile
713 +static struct aa_profile *__first_profile(struct aa_namespace *root,
714 + struct aa_namespace *ns)
716 + for ( ; ns; ns = __next_namespace(root, ns)) {
717 + if (!list_empty(&ns->base.profiles))
718 + return list_first_entry(&ns->base.profiles,
719 + struct aa_profile, base.list);
725 + * __next_profile - step to the next profile in a profile tree
726 + * @profile: current profile in tree (NOT NULL)
728 + * Perform a depth first taversal on the profile tree in a namespace
730 + * Returns: next profile or NULL if done
731 + * Requires: profile->ns.lock to be held
733 +static struct aa_profile *__next_profile(struct aa_profile *p)
735 + struct aa_profile *parent;
736 + struct aa_namespace *ns = p->ns;
738 + /* is next profile a child */
739 + if (!list_empty(&p->base.profiles))
740 + return list_first_entry(&p->base.profiles, typeof(*p),
743 + /* is next profile a sibling, parent sibling, gp, subling, .. */
744 + parent = p->parent;
746 + list_for_each_entry_continue(p, &parent->base.profiles,
750 + parent = parent->parent;
753 + /* is next another profile in the namespace */
754 + list_for_each_entry_continue(p, &ns->base.profiles, base.list)
761 + * next_profile - step to the next profile in where ever it may be
762 + * @root: root namespace (NOT NULL)
763 + * @profile: current profile (NOT NULL)
765 + * Returns: next profile or NULL if there isn't one
767 +static struct aa_profile *next_profile(struct aa_namespace *root,
768 + struct aa_profile *profile)
770 + struct aa_profile *next = __next_profile(profile);
774 + /* finished all profiles in namespace move to next namespace */
775 + return __first_profile(root, __next_namespace(root, profile->ns));
779 + * p_start - start a depth first traversal of profile tree
780 + * @f: seq_file to fill
781 + * @pos: current position
783 + * Returns: first profile under current namespace or NULL if none found
785 + * acquires first ns->lock
787 +static void *p_start(struct seq_file *f, loff_t *pos)
788 + __acquires(root->lock)
790 + struct aa_profile *profile = NULL;
791 + struct aa_namespace *root = aa_current_profile()->ns;
793 + f->private = aa_get_namespace(root);
796 + /* find the first profile */
797 + read_lock(&root->lock);
798 + profile = __first_profile(root, root);
800 + /* skip to position */
801 + for (; profile && l > 0; l--)
802 + profile = next_profile(root, profile);
808 + * p_next - read the next profile entry
809 + * @f: seq_file to fill
810 + * @p: profile previously returned
811 + * @pos: current position
813 + * Returns: next profile after @p or NULL if none
815 + * may acquire/release locks in namespace tree as necessary
817 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
819 + struct aa_profile *profile = p;
820 + struct aa_namespace *root = f->private;
823 + return next_profile(root, profile);
827 + * p_stop - stop depth first traversal
828 + * @f: seq_file we are filling
829 + * @p: the last profile writen
831 + * Release all locking done by p_start/p_next on namespace tree
833 +static void p_stop(struct seq_file *f, void *p)
834 + __releases(root->lock)
836 + struct aa_profile *profile = p;
837 + struct aa_namespace *root = f->private, *ns;
840 + for (ns = profile->ns; ns && ns != root; ns = ns->parent)
841 + read_unlock(&ns->lock);
843 + read_unlock(&root->lock);
844 + aa_put_namespace(root);
848 + * seq_show_profile - show a profile entry
849 + * @f: seq_file to file
850 + * @p: current position (profile) (NOT NULL)
852 + * Returns: error on failure
854 +static int seq_show_profile(struct seq_file *f, void *p)
856 + struct aa_profile *profile = (struct aa_profile *)p;
857 + struct aa_namespace *root = f->private;
859 + if (profile->ns != root)
860 + seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
861 + seq_printf(f, "%s (%s)\n", profile->base.hname,
862 + COMPLAIN_MODE(profile) ? "complain" : "enforce");
867 +static const struct seq_operations aa_fs_profiles_op = {
871 + .show = seq_show_profile,
874 +static int profiles_open(struct inode *inode, struct file *file)
876 + return seq_open(file, &aa_fs_profiles_op);
879 +static int profiles_release(struct inode *inode, struct file *file)
881 + return seq_release(inode, file);
884 +const struct file_operations aa_fs_profiles_fops = {
885 + .open = profiles_open,
887 + .llseek = seq_lseek,
888 + .release = profiles_release,
890 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
891 index 0848292..28c52ac 100644
892 --- a/security/apparmor/apparmorfs.c
893 +++ b/security/apparmor/apparmorfs.c
894 @@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
895 aafs_remove(".remove");
896 aafs_remove(".replace");
897 aafs_remove(".load");
899 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
900 + aafs_remove("profiles");
901 + aafs_remove("matching");
902 + aafs_remove("features");
904 securityfs_remove(aa_fs_dentry);
907 @@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
912 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
913 + error = aafs_create("matching", 0444, &aa_fs_matching_fops);
916 + error = aafs_create("features", 0444, &aa_fs_features_fops);
920 + error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
923 error = aafs_create(".load", 0640, &aa_fs_profile_load);
926 diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
927 index cb1e93a..14f955c 100644
928 --- a/security/apparmor/include/apparmorfs.h
929 +++ b/security/apparmor/include/apparmorfs.h
932 extern void __init aa_destroy_aafs(void);
934 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
935 +extern const struct file_operations aa_fs_matching_fops;
936 +extern const struct file_operations aa_fs_features_fops;
937 +extern const struct file_operations aa_fs_profiles_fops;
940 #endif /* __AA_APPARMORFS_H */
944 From f17b28f64b963c47e76737f7bb7f58ce3a7c5249 Mon Sep 17 00:00:00 2001
945 From: John Johansen <john.johansen@canonical.com>
946 Date: Tue, 20 Jul 2010 06:57:08 -0700
947 Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken userspace
949 The apparmor_parser when compiling policy could generate invalid dfas
950 that did not have sufficient padding to avoid invalid references, when
951 used by the kernel. The kernels check to verify the next/check table
952 size was broken meaning invalid dfas were being created by userspace
955 To remain compatible with old tools that are not fixed, pad the loaded
956 dfas next/check table. The dfa's themselves are valid except for the
957 high padding for potentially invalid transitions (high bounds error),
958 which have a maximimum is 256 entries. So just allocate an extra null filled
959 256 entries for the next/check tables. This will guarentee all bounds
960 are good and invalid transitions go to the null (0) state.
962 Signed-off-by: John Johansen <john.johansen@canonical.com>
964 security/apparmor/match.c | 17 +++++++++++++++++
965 1 files changed, 17 insertions(+), 0 deletions(-)
967 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
968 index 06d764c..cf92856 100644
969 --- a/security/apparmor/match.c
970 +++ b/security/apparmor/match.c
971 @@ -57,8 +57,17 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
975 + /* Pad table allocation for next/check by 256 entries to remain
976 + * backwards compatible with old (buggy) tools and remain safe without
979 + if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
980 + tsize += 256 * th.td_flags;
982 table = kvmalloc(tsize);
984 + /* ensure the pad is clear, else there will be errors */
985 + memset(table, 0, tsize);
987 if (th.td_flags == YYTD_DATA8)
988 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
989 @@ -134,11 +143,19 @@ static int verify_dfa(struct aa_dfa *dfa, int flags)
992 if (flags & DFA_FLAG_VERIFY_STATES) {
994 for (i = 0; i < state_count; i++) {
995 if (DEFAULT_TABLE(dfa)[i] >= state_count)
997 /* TODO: do check that DEF state recursion terminates */
998 if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
1001 + printk(KERN_WARNING "AppArmor DFA next/check "
1002 + "upper bounds error fixed, upgrade "
1003 + "user space tools \n");
1005 + } else if (BASE_TABLE(dfa)[i] >= trans_count) {
1006 printk(KERN_ERR "AppArmor DFA next/check upper "