]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-apparmor.patch
- fix for 3.0.3
[packages/kernel.git] / kernel-apparmor.patch
CommitLineData
948a1326 1From 0ae314bc92d8b22250f04f85e4bd36ee9ed30890 Mon Sep 17 00:00:00 2001
76514441 2From: John Johansen <john.johansen@canonical.com>
fc63ffa9
AM
3Date: Mon, 4 Oct 2010 15:03:36 -0700
4Subject: [PATCH 1/3] AppArmor: compatibility patch for v5 network controll
76514441 5
fc63ffa9 6Add compatibility for v5 network rules.
76514441
AM
7
8Signed-off-by: John Johansen <john.johansen@canonical.com>
9---
fc63ffa9 10 include/linux/lsm_audit.h | 4 +
948a1326 11 security/apparmor/Makefile | 19 ++++-
fc63ffa9
AM
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 ++++++++++-
948a1326 18 8 files changed, 394 insertions(+), 3 deletions(-)
76514441 19 create mode 100644 security/apparmor/include/net.h
76514441 20 create mode 100644 security/apparmor/net.c
76514441 21
76514441 22diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
fc63ffa9 23index 112a550..d5f3dd7 100644
76514441
AM
24--- a/include/linux/lsm_audit.h
25+++ b/include/linux/lsm_audit.h
fc63ffa9
AM
26@@ -123,6 +123,10 @@ struct common_audit_data {
27 u32 denied;
28 uid_t ouid;
29 } fs;
76514441
AM
30+ struct {
31+ int type, protocol;
32+ struct sock *sk;
33+ } net;
fc63ffa9
AM
34 };
35 } apparmor_audit_data;
36 #endif
37diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
948a1326 38index 2dafe50..7cefef9 100644
fc63ffa9
AM
39--- a/security/apparmor/Makefile
40+++ b/security/apparmor/Makefile
948a1326 41@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
ceaf2cfb 42
fc63ffa9
AM
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
ceaf2cfb 47
948a1326
JR
48-clean-files := capability_names.h rlim_names.h
49+clean-files := capability_names.h rlim_names.h af_names.h
ceaf2cfb 50
ceaf2cfb 51
948a1326
JR
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" $< >> $@ ;\
55 echo "};" >> $@
56
57+# Build a lower case string table of address family names.
58+# Transform lines from
59+# #define AF_INET 2 /* Internet IP Protocol */
60+# to
61+# [2] = "inet",
ceaf2cfb 62+quiet_cmd_make-af = GEN $@
948a1326
JR
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';\
66+ echo "};" >> $@
67+
ceaf2cfb 68+
fc63ffa9 69 $(obj)/capability.o : $(obj)/capability_names.h
fc63ffa9 70 $(obj)/resource.o : $(obj)/rlim_names.h
948a1326 71+$(obj)/net.o : $(obj)/af_names.h
fc63ffa9
AM
72 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
73 $(call cmd,make-caps)
948a1326
JR
74 $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
75 $(call cmd,make-rlim)
76+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
77+ $(call cmd,make-af)
78\ No newline at end of file
fc63ffa9 79diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
ceaf2cfb 80new file mode 100644
fc63ffa9 81index 0000000..3c7d599
ceaf2cfb 82--- /dev/null
fc63ffa9
AM
83+++ b/security/apparmor/include/net.h
84@@ -0,0 +1,40 @@
9474138d
AM
85+/*
86+ * AppArmor security module
87+ *
fc63ffa9 88+ * This file contains AppArmor network mediation definitions.
9474138d
AM
89+ *
90+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 91+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
92+ *
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
96+ * License.
97+ */
98+
fc63ffa9
AM
99+#ifndef __AA_NET_H
100+#define __AA_NET_H
2380c486 101+
fc63ffa9 102+#include <net/sock.h>
9474138d 103+
fc63ffa9
AM
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
108+ */
109+struct aa_net {
110+ u16 allow[AF_MAX];
111+ u16 audit[AF_MAX];
112+ u16 quiet[AF_MAX];
113+};
ceaf2cfb 114+
fc63ffa9
AM
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);
ceaf2cfb 118+
fc63ffa9
AM
119+static inline void aa_free_net_rules(struct aa_net *new)
120+{
121+ /* NOP */
ceaf2cfb
AM
122+}
123+
fc63ffa9
AM
124+#endif /* __AA_NET_H */
125diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
126index aeda5cf..6776929 100644
127--- a/security/apparmor/include/policy.h
128+++ b/security/apparmor/include/policy.h
129@@ -27,6 +27,7 @@
130 #include "capability.h"
131 #include "domain.h"
132 #include "file.h"
133+#include "net.h"
134 #include "resource.h"
135
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
143 *
144 * The AppArmor profile contains the basic confinement data. Each profile
145@@ -181,6 +183,7 @@ struct aa_profile {
146
147 struct aa_file_rules file;
148 struct aa_caps caps;
149+ struct aa_net net;
150 struct aa_rlimit rlimits;
151 };
152
153diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
948a1326 154index ae3a698..05c018b 100644
fc63ffa9
AM
155--- a/security/apparmor/lsm.c
156+++ b/security/apparmor/lsm.c
948a1326 157@@ -32,6 +32,7 @@
fc63ffa9
AM
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"
0fb6093f
AM
165@@ -651,6 +750,19 @@ static struct security_operations apparmor_ops = {
166 .getprocattr = apparmor_getprocattr,
167 .setprocattr = apparmor_setprocattr,
168
169+ .socket_create = apparmor_socket_create,
170+ .socket_bind = apparmor_socket_bind,
171+ .socket_connect = apparmor_socket_connect,
172+ .socket_listen = apparmor_socket_listen,
173+ .socket_accept = apparmor_socket_accept,
174+ .socket_sendmsg = apparmor_socket_sendmsg,
175+ .socket_recvmsg = apparmor_socket_recvmsg,
176+ .socket_getsockname = apparmor_socket_getsockname,
177+ .socket_getpeername = apparmor_socket_getpeername,
178+ .socket_getsockopt = apparmor_socket_getsockopt,
179+ .socket_setsockopt = apparmor_socket_setsockopt,
180+ .socket_shutdown = apparmor_socket_shutdown,
181+
182 .cred_alloc_blank = apparmor_cred_alloc_blank,
183 .cred_free = apparmor_cred_free,
184 .cred_prepare = apparmor_cred_prepare,
185@@ -949,4 +950,102 @@ static int apparmor_task_setrlimit(struct task_struct *task,
fc63ffa9
AM
186 return error;
187 }
188
189+static int apparmor_socket_create(int family, int type, int protocol, int kern)
ceaf2cfb 190+{
fc63ffa9
AM
191+ struct aa_profile *profile;
192+ int error = 0;
ceaf2cfb 193+
fc63ffa9
AM
194+ if (kern)
195+ return 0;
ceaf2cfb 196+
fc63ffa9
AM
197+ profile = __aa_current_profile();
198+ if (!unconfined(profile))
199+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
200+ NULL);
201+ return error;
202+}
ceaf2cfb 203+
fc63ffa9
AM
204+static int apparmor_socket_bind(struct socket *sock,
205+ struct sockaddr *address, int addrlen)
9474138d 206+{
fc63ffa9 207+ struct sock *sk = sock->sk;
9474138d 208+
fc63ffa9
AM
209+ return aa_revalidate_sk(OP_BIND, sk);
210+}
ceaf2cfb 211+
fc63ffa9
AM
212+static int apparmor_socket_connect(struct socket *sock,
213+ struct sockaddr *address, int addrlen)
214+{
215+ struct sock *sk = sock->sk;
ceaf2cfb 216+
fc63ffa9 217+ return aa_revalidate_sk(OP_CONNECT, sk);
9474138d
AM
218+}
219+
fc63ffa9 220+static int apparmor_socket_listen(struct socket *sock, int backlog)
9474138d 221+{
fc63ffa9
AM
222+ struct sock *sk = sock->sk;
223+
224+ return aa_revalidate_sk(OP_LISTEN, sk);
9474138d
AM
225+}
226+
fc63ffa9 227+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
9474138d 228+{
fc63ffa9 229+ struct sock *sk = sock->sk;
9474138d 230+
fc63ffa9
AM
231+ return aa_revalidate_sk(OP_ACCEPT, sk);
232+}
9474138d 233+
fc63ffa9
AM
234+static int apparmor_socket_sendmsg(struct socket *sock,
235+ struct msghdr *msg, int size)
76514441 236+{
fc63ffa9 237+ struct sock *sk = sock->sk;
76514441 238+
fc63ffa9 239+ return aa_revalidate_sk(OP_SENDMSG, sk);
76514441
AM
240+}
241+
fc63ffa9
AM
242+static int apparmor_socket_recvmsg(struct socket *sock,
243+ struct msghdr *msg, int size, int flags)
244+{
245+ struct sock *sk = sock->sk;
ceaf2cfb 246+
fc63ffa9
AM
247+ return aa_revalidate_sk(OP_RECVMSG, sk);
248+}
ceaf2cfb 249+
fc63ffa9
AM
250+static int apparmor_socket_getsockname(struct socket *sock)
251+{
252+ struct sock *sk = sock->sk;
ceaf2cfb 253+
fc63ffa9 254+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
9474138d
AM
255+}
256+
fc63ffa9 257+static int apparmor_socket_getpeername(struct socket *sock)
9474138d 258+{
fc63ffa9 259+ struct sock *sk = sock->sk;
9474138d 260+
fc63ffa9
AM
261+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
262+}
ceaf2cfb 263+
fc63ffa9
AM
264+static int apparmor_socket_getsockopt(struct socket *sock, int level,
265+ int optname)
266+{
267+ struct sock *sk = sock->sk;
ceaf2cfb 268+
fc63ffa9
AM
269+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
270+}
ceaf2cfb 271+
fc63ffa9
AM
272+static int apparmor_socket_setsockopt(struct socket *sock, int level,
273+ int optname)
274+{
275+ struct sock *sk = sock->sk;
2380c486 276+
fc63ffa9
AM
277+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
278+}
ceaf2cfb 279+
fc63ffa9
AM
280+static int apparmor_socket_shutdown(struct socket *sock, int how)
281+{
282+ struct sock *sk = sock->sk;
ceaf2cfb 283+
fc63ffa9 284+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
ceaf2cfb 285+}
948a1326 286+
0fb6093f
AM
287 security_initcall(apparmor_init);
288
fc63ffa9 289diff --git a/security/apparmor/net.c b/security/apparmor/net.c
ceaf2cfb 290new file mode 100644
fc63ffa9 291index 0000000..1765901
ceaf2cfb 292--- /dev/null
fc63ffa9
AM
293+++ b/security/apparmor/net.c
294@@ -0,0 +1,170 @@
2380c486 295+/*
9474138d
AM
296+ * AppArmor security module
297+ *
fc63ffa9 298+ * This file contains AppArmor network mediation
2380c486 299+ *
9474138d 300+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 301+ * Copyright 2009-2010 Canonical Ltd.
2380c486 302+ *
9474138d
AM
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
306+ * License.
2380c486
JR
307+ */
308+
9474138d
AM
309+#include "include/apparmor.h"
310+#include "include/audit.h"
311+#include "include/context.h"
fc63ffa9 312+#include "include/net.h"
9474138d 313+#include "include/policy.h"
2380c486 314+
fc63ffa9 315+#include "af_names.h"
2380c486 316+
fc63ffa9
AM
317+static const char *sock_type_names[] = {
318+ "unknown(0)",
319+ "stream",
320+ "dgram",
321+ "raw",
322+ "rdm",
323+ "seqpacket",
324+ "dccp",
325+ "unknown(7)",
326+ "unknown(8)",
327+ "unknown(9)",
328+ "packet",
9474138d
AM
329+};
330+
fc63ffa9 331+/* audit callback for net specific fields */
76514441 332+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 333+{
76514441 334+ struct common_audit_data *sa = va;
9474138d 335+
fc63ffa9
AM
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]);
339+ } else {
340+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
341+ }
2380c486 342+
fc63ffa9
AM
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]);
346+ } else {
347+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
348+ }
2380c486 349+
fc63ffa9 350+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
2380c486
JR
351+}
352+
353+/**
fc63ffa9
AM
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
ceaf2cfb 362+ *
fc63ffa9 363+ * Returns: %0 or sa->error else other errorcode on failure
2380c486 364+ */
fc63ffa9
AM
365+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
366+ int protocol, struct sock *sk, int error)
2380c486 367+{
fc63ffa9
AM
368+ int audit_type = AUDIT_APPARMOR_AUTO;
369+ struct common_audit_data sa;
370+ if (sk) {
371+ COMMON_AUDIT_DATA_INIT(&sa, NET);
372+ } else {
373+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
2380c486 374+ }
fc63ffa9 375+ /* todo fill in socket addr info */
2380c486 376+
fc63ffa9
AM
377+ sa.aad.op = op,
378+ sa.u.net.family = family;
379+ sa.u.net.sk = sk;
380+ sa.aad.net.type = type;
381+ sa.aad.net.protocol = protocol;
382+ sa.aad.error = error;
2380c486 383+
fc63ffa9
AM
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)))
ceaf2cfb 388+ return 0;
fc63ffa9
AM
389+ audit_type = AUDIT_APPARMOR_AUDIT;
390+ } else {
391+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
392+ u16 kill_mask = 0;
393+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
9474138d 394+
fc63ffa9
AM
395+ if (denied & kill_mask)
396+ audit_type = AUDIT_APPARMOR_KILL;
9474138d 397+
fc63ffa9
AM
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;
9474138d
AM
402+ }
403+
fc63ffa9 404+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
ceaf2cfb
AM
405+}
406+
2380c486 407+/**
fc63ffa9
AM
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
2380c486 414+ *
fc63ffa9 415+ * Returns: %0 else error if permission denied
2380c486 416+ */
fc63ffa9
AM
417+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
418+ int protocol, struct sock *sk)
2380c486 419+{
fc63ffa9
AM
420+ u16 family_mask;
421+ int error;
ceaf2cfb 422+
fc63ffa9
AM
423+ if ((family < 0) || (family >= AF_MAX))
424+ return -EINVAL;
ceaf2cfb 425+
fc63ffa9
AM
426+ if ((type < 0) || (type >= SOCK_MAX))
427+ return -EINVAL;
76514441 428+
fc63ffa9
AM
429+ /* unix domain and netlink sockets are handled by ipc */
430+ if (family == AF_UNIX || family == AF_NETLINK)
431+ return 0;
76514441 432+
fc63ffa9 433+ family_mask = profile->net.allow[family];
2380c486 434+
fc63ffa9 435+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
ceaf2cfb 436+
fc63ffa9 437+ return audit_net(profile, op, family, type, protocol, sk, error);
2380c486
JR
438+}
439+
76514441 440+/**
fc63ffa9
AM
441+ * aa_revalidate_sk - Revalidate access to a sock
442+ * @op: operation being checked
443+ * @sk: sock being revalidated (NOT NULL)
76514441 444+ *
fc63ffa9 445+ * Returns: %0 else error if permission denied
76514441 446+ */
fc63ffa9 447+int aa_revalidate_sk(int op, struct sock *sk)
2380c486 448+{
fc63ffa9
AM
449+ struct aa_profile *profile;
450+ int error = 0;
2380c486 451+
fc63ffa9
AM
452+ /* aa_revalidate_sk should not be called from interrupt context
453+ * don't mediate these calls as they are not task related
454+ */
455+ if (in_interrupt())
456+ return 0;
ceaf2cfb 457+
fc63ffa9
AM
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);
2380c486 462+
fc63ffa9 463+ return error;
2380c486 464+}
fc63ffa9 465diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
948a1326 466index 4f0eade..4d5ce13 100644
fc63ffa9
AM
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)
470
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);
475
476 aa_free_sid(profile->sid);
477diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
948a1326 478index e33aaf7..fa3f1b4 100644
fc63ffa9
AM
479--- a/security/apparmor/policy_unpack.c
480+++ b/security/apparmor/policy_unpack.c
481@@ -190,6 +190,19 @@ fail:
482 return 0;
483 }
484
485+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
2380c486 486+{
fc63ffa9
AM
487+ if (unpack_nameX(e, AA_U16, name)) {
488+ if (!inbounds(e, sizeof(u16)))
489+ return 0;
490+ if (data)
491+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
492+ e->pos += sizeof(u16);
493+ return 1;
2380c486 494+ }
2380c486
JR
495+ return 0;
496+}
497+
fc63ffa9
AM
498 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
499 {
500 if (unpack_nameX(e, AA_U32, name)) {
501@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
502 {
503 struct aa_profile *profile = NULL;
504 const char *name = NULL;
505- int error = -EPROTO;
2380c486
JR
506+ size_t size = 0;
507+ int i, error = -EPROTO;
fc63ffa9
AM
508 kernel_cap_t tmpcap;
509 u32 tmp;
510
511@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
512 if (!unpack_rlimits(e, profile))
513 goto fail;
514
ceaf2cfb 515+ size = unpack_array(e, "net_allowed_af");
2380c486 516+ if (size) {
2380c486
JR
517+
518+ for (i = 0; i < size; i++) {
fc63ffa9
AM
519+ /* discard extraneous rules that this kernel will
520+ * never request
521+ */
522+ if (i > AF_MAX) {
523+ u16 tmp;
524+ if (!unpack_u16(e, &tmp, NULL) ||
525+ !unpack_u16(e, &tmp, NULL) ||
526+ !unpack_u16(e, &tmp, NULL))
527+ goto fail;
528+ continue;
529+ }
76514441 530+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
2380c486 531+ goto fail;
ceaf2cfb 532+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
2380c486 533+ goto fail;
ceaf2cfb 534+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
2380c486
JR
535+ goto fail;
536+ }
ceaf2cfb 537+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
2380c486 538+ goto fail;
ceaf2cfb
AM
539+ /*
540+ * allow unix domain and netlink sockets they are handled
2380c486
JR
541+ * by IPC
542+ */
543+ }
76514441
AM
544+ profile->net.allow[AF_UNIX] = 0xffff;
545+ profile->net.allow[AF_NETLINK] = 0xffff;
2380c486 546+
fc63ffa9
AM
547 /* get file rules */
548 profile->file.dfa = unpack_dfa(e);
549 if (IS_ERR(profile->file.dfa)) {
550--
948a1326 5511.7.0.4
fc63ffa9 552
948a1326 553From cdc6b35345e5bcfe92bb2b52ef003f94ceedd40d Mon Sep 17 00:00:00 2001
fc63ffa9
AM
554From: John Johansen <john.johansen@canonical.com>
555Date: Thu, 22 Jul 2010 02:32:02 -0700
556Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
557
558Signed-off-by: John Johansen <john.johansen@canonical.com>
559---
560 security/apparmor/Kconfig | 9 +
948a1326 561 security/apparmor/Makefile | 1 +
fc63ffa9
AM
562 security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
563 security/apparmor/apparmorfs.c | 18 ++-
564 security/apparmor/include/apparmorfs.h | 6 +
948a1326 565 5 files changed, 319 insertions(+), 2 deletions(-)
fc63ffa9
AM
566 create mode 100644 security/apparmor/apparmorfs-24.c
567
568diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
569index 9b9013b..51ebf96 100644
570--- a/security/apparmor/Kconfig
571+++ b/security/apparmor/Kconfig
572@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
573 boot.
574
575 If you are unsure how to answer this question, answer 1.
2380c486 576+
fc63ffa9
AM
577+config SECURITY_APPARMOR_COMPAT_24
578+ bool "Enable AppArmor 2.4 compatability"
579+ depends on SECURITY_APPARMOR
580+ default y
581+ help
582+ This option enables compatability with AppArmor 2.4. It is
583+ recommended if compatability with older versions of AppArmor
584+ is desired.
585diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
948a1326 586index 7cefef9..0bb604b 100644
fc63ffa9
AM
587--- a/security/apparmor/Makefile
588+++ b/security/apparmor/Makefile
948a1326
JR
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 \
fc63ffa9
AM
591 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
592 resource.o sid.o file.o net.o
fc63ffa9 593+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
fc63ffa9 594
948a1326
JR
595 clean-files := capability_names.h rlim_names.h af_names.h
596
fc63ffa9 597diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
ceaf2cfb 598new file mode 100644
fc63ffa9 599index 0000000..dc8c744
ceaf2cfb 600--- /dev/null
fc63ffa9
AM
601+++ b/security/apparmor/apparmorfs-24.c
602@@ -0,0 +1,287 @@
2380c486 603+/*
9474138d
AM
604+ * AppArmor security module
605+ *
fc63ffa9 606+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
2380c486 607+ *
9474138d 608+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 609+ * Copyright 2009-2010 Canonical Ltd.
2380c486 610+ *
9474138d
AM
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
614+ * License.
fc63ffa9
AM
615+ *
616+ *
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).
2380c486
JR
620+ */
621+
fc63ffa9
AM
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>
628+
9474138d 629+#include "include/apparmor.h"
fc63ffa9 630+#include "include/audit.h"
76514441 631+#include "include/context.h"
9474138d 632+#include "include/policy.h"
2380c486 633+
76514441 634+
fc63ffa9
AM
635+/* apparmor/matching */
636+static ssize_t aa_matching_read(struct file *file, char __user *buf,
637+ size_t size, loff_t *ppos)
638+{
639+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
640+ "user::other";
641+
642+ return simple_read_from_buffer(buf, size, ppos, matching,
643+ sizeof(matching) - 1);
644+}
645+
646+const struct file_operations aa_fs_matching_fops = {
647+ .read = aa_matching_read,
648+};
649+
650+/* apparmor/features */
651+static ssize_t aa_features_read(struct file *file, char __user *buf,
652+ size_t size, loff_t *ppos)
653+{
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";
656+
657+ return simple_read_from_buffer(buf, size, ppos, features,
658+ sizeof(features) - 1);
659+}
660+
661+const struct file_operations aa_fs_features_fops = {
662+ .read = aa_features_read,
663+};
664+
ceaf2cfb 665+/**
fc63ffa9
AM
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)
ceaf2cfb 669+ *
fc63ffa9
AM
670+ * Find the next namespace from @ns under @root and handle all locking needed
671+ * while switching current namespace.
ceaf2cfb 672+ *
fc63ffa9
AM
673+ * Returns: next namespace or NULL if at last namespace under @root
674+ * NOTE: will not unlock root->lock
ceaf2cfb 675+ */
fc63ffa9
AM
676+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
677+ struct aa_namespace *ns)
2380c486 678+{
fc63ffa9 679+ struct aa_namespace *parent;
76514441 680+
fc63ffa9
AM
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);
686+ return next;
687+ }
2380c486 688+
fc63ffa9
AM
689+ /* check if the next ns is a sibling, parent, gp, .. */
690+ parent = ns->parent;
691+ while (parent) {
692+ read_unlock(&ns->lock);
693+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
694+ read_lock(&ns->lock);
695+ return ns;
696+ }
697+ if (parent == root)
698+ return NULL;
699+ ns = parent;
700+ parent = parent->parent;
2380c486 701+ }
2380c486 702+
fc63ffa9 703+ return NULL;
2380c486
JR
704+}
705+
ceaf2cfb 706+/**
fc63ffa9
AM
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)
ceaf2cfb 710+ *
fc63ffa9 711+ * Returns: unrefcounted profile or NULL if no profile
ceaf2cfb 712+ */
fc63ffa9
AM
713+static struct aa_profile *__first_profile(struct aa_namespace *root,
714+ struct aa_namespace *ns)
2380c486 715+{
fc63ffa9
AM
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);
2380c486 720+ }
fc63ffa9 721+ return NULL;
2380c486
JR
722+}
723+
ceaf2cfb 724+/**
fc63ffa9
AM
725+ * __next_profile - step to the next profile in a profile tree
726+ * @profile: current profile in tree (NOT NULL)
727+ *
728+ * Perform a depth first taversal on the profile tree in a namespace
ceaf2cfb 729+ *
fc63ffa9
AM
730+ * Returns: next profile or NULL if done
731+ * Requires: profile->ns.lock to be held
ceaf2cfb 732+ */
fc63ffa9 733+static struct aa_profile *__next_profile(struct aa_profile *p)
2380c486 734+{
fc63ffa9
AM
735+ struct aa_profile *parent;
736+ struct aa_namespace *ns = p->ns;
2380c486 737+
fc63ffa9
AM
738+ /* is next profile a child */
739+ if (!list_empty(&p->base.profiles))
740+ return list_first_entry(&p->base.profiles, typeof(*p),
741+ base.list);
2380c486 742+
fc63ffa9
AM
743+ /* is next profile a sibling, parent sibling, gp, subling, .. */
744+ parent = p->parent;
745+ while (parent) {
746+ list_for_each_entry_continue(p, &parent->base.profiles,
747+ base.list)
748+ return p;
749+ p = parent;
750+ parent = parent->parent;
ceaf2cfb
AM
751+ }
752+
fc63ffa9
AM
753+ /* is next another profile in the namespace */
754+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
755+ return p;
2380c486 756+
fc63ffa9 757+ return NULL;
2380c486
JR
758+}
759+
ceaf2cfb 760+/**
fc63ffa9
AM
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)
ceaf2cfb 764+ *
fc63ffa9 765+ * Returns: next profile or NULL if there isn't one
ceaf2cfb 766+ */
fc63ffa9
AM
767+static struct aa_profile *next_profile(struct aa_namespace *root,
768+ struct aa_profile *profile)
2380c486 769+{
fc63ffa9
AM
770+ struct aa_profile *next = __next_profile(profile);
771+ if (next)
772+ return next;
9474138d 773+
fc63ffa9
AM
774+ /* finished all profiles in namespace move to next namespace */
775+ return __first_profile(root, __next_namespace(root, profile->ns));
9474138d 776+}
2380c486 777+
fc63ffa9
AM
778+/**
779+ * p_start - start a depth first traversal of profile tree
780+ * @f: seq_file to fill
781+ * @pos: current position
9474138d 782+ *
fc63ffa9 783+ * Returns: first profile under current namespace or NULL if none found
9474138d 784+ *
fc63ffa9 785+ * acquires first ns->lock
76514441 786+ */
fc63ffa9
AM
787+static void *p_start(struct seq_file *f, loff_t *pos)
788+ __acquires(root->lock)
2380c486 789+{
fc63ffa9
AM
790+ struct aa_profile *profile = NULL;
791+ struct aa_namespace *root = aa_current_profile()->ns;
792+ loff_t l = *pos;
793+ f->private = aa_get_namespace(root);
9474138d 794+
9474138d 795+
fc63ffa9
AM
796+ /* find the first profile */
797+ read_lock(&root->lock);
798+ profile = __first_profile(root, root);
76514441 799+
fc63ffa9
AM
800+ /* skip to position */
801+ for (; profile && l > 0; l--)
802+ profile = next_profile(root, profile);
803+
804+ return profile;
76514441
AM
805+}
806+
807+/**
fc63ffa9
AM
808+ * p_next - read the next profile entry
809+ * @f: seq_file to fill
810+ * @p: profile previously returned
811+ * @pos: current position
76514441 812+ *
fc63ffa9 813+ * Returns: next profile after @p or NULL if none
76514441 814+ *
fc63ffa9 815+ * may acquire/release locks in namespace tree as necessary
76514441 816+ */
fc63ffa9 817+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
9474138d 818+{
fc63ffa9
AM
819+ struct aa_profile *profile = p;
820+ struct aa_namespace *root = f->private;
821+ (*pos)++;
822+
823+ return next_profile(root, profile);
9474138d
AM
824+}
825+
826+/**
fc63ffa9
AM
827+ * p_stop - stop depth first traversal
828+ * @f: seq_file we are filling
829+ * @p: the last profile writen
ceaf2cfb 830+ *
fc63ffa9 831+ * Release all locking done by p_start/p_next on namespace tree
9474138d 832+ */
fc63ffa9
AM
833+static void p_stop(struct seq_file *f, void *p)
834+ __releases(root->lock)
9474138d 835+{
fc63ffa9
AM
836+ struct aa_profile *profile = p;
837+ struct aa_namespace *root = f->private, *ns;
2380c486 838+
fc63ffa9
AM
839+ if (profile) {
840+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
841+ read_unlock(&ns->lock);
842+ }
843+ read_unlock(&root->lock);
844+ aa_put_namespace(root);
9474138d
AM
845+}
846+
ceaf2cfb 847+/**
fc63ffa9
AM
848+ * seq_show_profile - show a profile entry
849+ * @f: seq_file to file
850+ * @p: current position (profile) (NOT NULL)
851+ *
852+ * Returns: error on failure
ceaf2cfb 853+ */
fc63ffa9 854+static int seq_show_profile(struct seq_file *f, void *p)
9474138d 855+{
fc63ffa9
AM
856+ struct aa_profile *profile = (struct aa_profile *)p;
857+ struct aa_namespace *root = f->private;
2380c486 858+
fc63ffa9
AM
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");
2380c486 863+
fc63ffa9 864+ return 0;
9474138d 865+}
9474138d 866+
fc63ffa9
AM
867+static const struct seq_operations aa_fs_profiles_op = {
868+ .start = p_start,
869+ .next = p_next,
870+ .stop = p_stop,
871+ .show = seq_show_profile,
872+};
9474138d 873+
fc63ffa9 874+static int profiles_open(struct inode *inode, struct file *file)
9474138d 875+{
fc63ffa9 876+ return seq_open(file, &aa_fs_profiles_op);
9474138d
AM
877+}
878+
fc63ffa9 879+static int profiles_release(struct inode *inode, struct file *file)
9474138d 880+{
fc63ffa9 881+ return seq_release(inode, file);
9474138d 882+}
fc63ffa9
AM
883+
884+const struct file_operations aa_fs_profiles_fops = {
885+ .open = profiles_open,
886+ .read = seq_read,
887+ .llseek = seq_lseek,
888+ .release = profiles_release,
889+};
890diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
948a1326 891index 0848292..28c52ac 100644
fc63ffa9
AM
892--- a/security/apparmor/apparmorfs.c
893+++ b/security/apparmor/apparmorfs.c
948a1326 894@@ -187,7 +187,11 @@ void __init aa_destroy_aafs(void)
fc63ffa9
AM
895 aafs_remove(".remove");
896 aafs_remove(".replace");
897 aafs_remove(".load");
898-
899+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
900+ aafs_remove("profiles");
901+ aafs_remove("matching");
902+ aafs_remove("features");
903+#endif
904 securityfs_remove(aa_fs_dentry);
905 aa_fs_dentry = NULL;
906 }
948a1326 907@@ -218,7 +222,17 @@ int __init aa_create_aafs(void)
fc63ffa9
AM
908 aa_fs_dentry = NULL;
909 goto error;
910 }
911-
912+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
913+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
914+ if (error)
915+ goto error;
916+ error = aafs_create("features", 0444, &aa_fs_features_fops);
917+ if (error)
918+ goto error;
919+#endif
920+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
921+ if (error)
922+ goto error;
923 error = aafs_create(".load", 0640, &aa_fs_profile_load);
924 if (error)
925 goto error;
926diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
927index cb1e93a..14f955c 100644
928--- a/security/apparmor/include/apparmorfs.h
929+++ b/security/apparmor/include/apparmorfs.h
930@@ -17,4 +17,10 @@
931
932 extern void __init aa_destroy_aafs(void);
933
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;
938+#endif
939+
940 #endif /* __AA_APPARMORFS_H */
76514441 941--
948a1326
JR
9421.7.0.4
943
944From f17b28f64b963c47e76737f7bb7f58ce3a7c5249 Mon Sep 17 00:00:00 2001
945From: John Johansen <john.johansen@canonical.com>
946Date: Tue, 20 Jul 2010 06:57:08 -0700
947Subject: [PATCH 3/3] AppArmor: Allow dfa backward compatibility with broken userspace
948
949The apparmor_parser when compiling policy could generate invalid dfas
950that did not have sufficient padding to avoid invalid references, when
951used by the kernel. The kernels check to verify the next/check table
952size was broken meaning invalid dfas were being created by userspace
953and not caught.
954
955To remain compatible with old tools that are not fixed, pad the loaded
956dfas next/check table. The dfa's themselves are valid except for the
957high padding for potentially invalid transitions (high bounds error),
958which have a maximimum is 256 entries. So just allocate an extra null filled
959256 entries for the next/check tables. This will guarentee all bounds
960are good and invalid transitions go to the null (0) state.
961
962Signed-off-by: John Johansen <john.johansen@canonical.com>
963---
964 security/apparmor/match.c | 17 +++++++++++++++++
965 1 files changed, 17 insertions(+), 0 deletions(-)
966
967diff --git a/security/apparmor/match.c b/security/apparmor/match.c
968index 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)
972 if (bsize < tsize)
973 goto out;
974
975+ /* Pad table allocation for next/check by 256 entries to remain
976+ * backwards compatible with old (buggy) tools and remain safe without
977+ * run time checks
978+ */
979+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
980+ tsize += 256 * th.td_flags;
981+
982 table = kvmalloc(tsize);
983 if (table) {
984+ /* ensure the pad is clear, else there will be errors */
985+ memset(table, 0, tsize);
986 *table = th;
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)
990 goto out;
991
992 if (flags & DFA_FLAG_VERIFY_STATES) {
993+ int warning = 0;
994 for (i = 0; i < state_count; i++) {
995 if (DEFAULT_TABLE(dfa)[i] >= state_count)
996 goto out;
997 /* TODO: do check that DEF state recursion terminates */
998 if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
999+ if (warning)
1000+ continue;
1001+ printk(KERN_WARNING "AppArmor DFA next/check "
1002+ "upper bounds error fixed, upgrade "
1003+ "user space tools \n");
1004+ warning = 1;
1005+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
1006 printk(KERN_ERR "AppArmor DFA next/check upper "
1007 "bounds error\n");
1008 goto out;
1009--
10101.7.0.4
76514441 1011
This page took 0.228489 seconds and 4 git commands to generate.