]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-apparmor.patch
- updated for linux 3.0-rc6
[packages/kernel.git] / kernel-apparmor.patch
CommitLineData
fc63ffa9 1From 6ab924a333c81d552eb92900509113bdf2fccb2e 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
AM
10 include/linux/lsm_audit.h | 4 +
11 security/apparmor/Makefile | 6 +-
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, 382 insertions(+), 2 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
38index f204869..a9a1db0 100644
39--- a/security/apparmor/Makefile
40+++ b/security/apparmor/Makefile
41@@ -4,17 +4,21 @@ 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
fc63ffa9 48 clean-files: capability_names.h af_names.h
ceaf2cfb 49
fc63ffa9
AM
50 quiet_cmd_make-caps = GEN $@
51 cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
ceaf2cfb 52
ceaf2cfb
AM
53+quiet_cmd_make-af = GEN $@
54+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
55+
fc63ffa9
AM
56 quiet_cmd_make-rlim = GEN $@
57 cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
58
59 $(obj)/capability.o : $(obj)/capability_names.h
ceaf2cfb 60+$(obj)/net.o : $(obj)/af_names.h
fc63ffa9
AM
61 $(obj)/resource.o : $(obj)/rlim_names.h
62 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
63 $(call cmd,make-caps)
64diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
ceaf2cfb 65new file mode 100644
fc63ffa9 66index 0000000..3c7d599
ceaf2cfb 67--- /dev/null
fc63ffa9
AM
68+++ b/security/apparmor/include/net.h
69@@ -0,0 +1,40 @@
9474138d
AM
70+/*
71+ * AppArmor security module
72+ *
fc63ffa9 73+ * This file contains AppArmor network mediation definitions.
9474138d
AM
74+ *
75+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 76+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
77+ *
78+ * This program is free software; you can redistribute it and/or
79+ * modify it under the terms of the GNU General Public License as
80+ * published by the Free Software Foundation, version 2 of the
81+ * License.
82+ */
83+
fc63ffa9
AM
84+#ifndef __AA_NET_H
85+#define __AA_NET_H
2380c486 86+
fc63ffa9 87+#include <net/sock.h>
9474138d 88+
fc63ffa9
AM
89+/* struct aa_net - network confinement data
90+ * @allowed: basic network families permissions
91+ * @audit_network: which network permissions to force audit
92+ * @quiet_network: which network permissions to quiet rejects
93+ */
94+struct aa_net {
95+ u16 allow[AF_MAX];
96+ u16 audit[AF_MAX];
97+ u16 quiet[AF_MAX];
98+};
ceaf2cfb 99+
fc63ffa9
AM
100+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
101+ int type, int protocol, struct sock *sk);
102+extern int aa_revalidate_sk(int op, struct sock *sk);
ceaf2cfb 103+
fc63ffa9
AM
104+static inline void aa_free_net_rules(struct aa_net *new)
105+{
106+ /* NOP */
ceaf2cfb
AM
107+}
108+
fc63ffa9
AM
109+#endif /* __AA_NET_H */
110diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
111index aeda5cf..6776929 100644
112--- a/security/apparmor/include/policy.h
113+++ b/security/apparmor/include/policy.h
114@@ -27,6 +27,7 @@
115 #include "capability.h"
116 #include "domain.h"
117 #include "file.h"
118+#include "net.h"
119 #include "resource.h"
120
121 extern const char *profile_mode_names[];
122@@ -145,6 +146,7 @@ struct aa_namespace {
123 * @size: the memory consumed by this profiles rules
124 * @file: The set of rules governing basic file access and domain transitions
125 * @caps: capabilities for the profile
126+ * @net: network controls for the profile
127 * @rlimits: rlimits for the profile
128 *
129 * The AppArmor profile contains the basic confinement data. Each profile
130@@ -181,6 +183,7 @@ struct aa_profile {
131
132 struct aa_file_rules file;
133 struct aa_caps caps;
134+ struct aa_net net;
135 struct aa_rlimit rlimits;
136 };
137
138diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
139index cf1de44..324ab91 100644
140--- a/security/apparmor/lsm.c
141+++ b/security/apparmor/lsm.c
142@@ -31,6 +31,7 @@
143 #include "include/context.h"
144 #include "include/file.h"
145 #include "include/ipc.h"
146+#include "include/net.h"
147 #include "include/path.h"
148 #include "include/policy.h"
149 #include "include/procattr.h"
b7f5100c 150@@ -607,6 +608,103 @@ static int apparmor_setprocattr(struct t
fc63ffa9
AM
151 return error;
152 }
153
154+static int apparmor_socket_create(int family, int type, int protocol, int kern)
ceaf2cfb 155+{
fc63ffa9
AM
156+ struct aa_profile *profile;
157+ int error = 0;
ceaf2cfb 158+
fc63ffa9
AM
159+ if (kern)
160+ return 0;
ceaf2cfb 161+
fc63ffa9
AM
162+ profile = __aa_current_profile();
163+ if (!unconfined(profile))
164+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
165+ NULL);
166+ return error;
167+}
ceaf2cfb 168+
fc63ffa9
AM
169+static int apparmor_socket_bind(struct socket *sock,
170+ struct sockaddr *address, int addrlen)
9474138d 171+{
fc63ffa9 172+ struct sock *sk = sock->sk;
9474138d 173+
fc63ffa9
AM
174+ return aa_revalidate_sk(OP_BIND, sk);
175+}
ceaf2cfb 176+
fc63ffa9
AM
177+static int apparmor_socket_connect(struct socket *sock,
178+ struct sockaddr *address, int addrlen)
179+{
180+ struct sock *sk = sock->sk;
ceaf2cfb 181+
fc63ffa9 182+ return aa_revalidate_sk(OP_CONNECT, sk);
9474138d
AM
183+}
184+
fc63ffa9 185+static int apparmor_socket_listen(struct socket *sock, int backlog)
9474138d 186+{
fc63ffa9
AM
187+ struct sock *sk = sock->sk;
188+
189+ return aa_revalidate_sk(OP_LISTEN, sk);
9474138d
AM
190+}
191+
fc63ffa9 192+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
9474138d 193+{
fc63ffa9 194+ struct sock *sk = sock->sk;
9474138d 195+
fc63ffa9
AM
196+ return aa_revalidate_sk(OP_ACCEPT, sk);
197+}
9474138d 198+
fc63ffa9
AM
199+static int apparmor_socket_sendmsg(struct socket *sock,
200+ struct msghdr *msg, int size)
76514441 201+{
fc63ffa9 202+ struct sock *sk = sock->sk;
76514441 203+
fc63ffa9 204+ return aa_revalidate_sk(OP_SENDMSG, sk);
76514441
AM
205+}
206+
fc63ffa9
AM
207+static int apparmor_socket_recvmsg(struct socket *sock,
208+ struct msghdr *msg, int size, int flags)
209+{
210+ struct sock *sk = sock->sk;
ceaf2cfb 211+
fc63ffa9
AM
212+ return aa_revalidate_sk(OP_RECVMSG, sk);
213+}
ceaf2cfb 214+
fc63ffa9
AM
215+static int apparmor_socket_getsockname(struct socket *sock)
216+{
217+ struct sock *sk = sock->sk;
ceaf2cfb 218+
fc63ffa9 219+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
9474138d
AM
220+}
221+
fc63ffa9 222+static int apparmor_socket_getpeername(struct socket *sock)
9474138d 223+{
fc63ffa9 224+ struct sock *sk = sock->sk;
9474138d 225+
fc63ffa9
AM
226+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
227+}
ceaf2cfb 228+
fc63ffa9
AM
229+static int apparmor_socket_getsockopt(struct socket *sock, int level,
230+ int optname)
231+{
232+ struct sock *sk = sock->sk;
ceaf2cfb 233+
fc63ffa9
AM
234+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
235+}
ceaf2cfb 236+
fc63ffa9
AM
237+static int apparmor_socket_setsockopt(struct socket *sock, int level,
238+ int optname)
239+{
240+ struct sock *sk = sock->sk;
2380c486 241+
fc63ffa9
AM
242+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
243+}
ceaf2cfb 244+
fc63ffa9
AM
245+static int apparmor_socket_shutdown(struct socket *sock, int how)
246+{
247+ struct sock *sk = sock->sk;
ceaf2cfb 248+
fc63ffa9 249+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
ceaf2cfb 250+}
b7f5100c
AM
251 static int apparmor_task_setrlimit(struct task_struct *task,
252 unsigned int resource, struct rlimit *new_rlim)
253 {
fc63ffa9
AM
254@@ -650,6 +749,19 @@ static struct security_operations apparmor_ops = {
255 .getprocattr = apparmor_getprocattr,
256 .setprocattr = apparmor_setprocattr,
257
258+ .socket_create = apparmor_socket_create,
259+ .socket_bind = apparmor_socket_bind,
260+ .socket_connect = apparmor_socket_connect,
261+ .socket_listen = apparmor_socket_listen,
262+ .socket_accept = apparmor_socket_accept,
263+ .socket_sendmsg = apparmor_socket_sendmsg,
264+ .socket_recvmsg = apparmor_socket_recvmsg,
265+ .socket_getsockname = apparmor_socket_getsockname,
266+ .socket_getpeername = apparmor_socket_getpeername,
267+ .socket_getsockopt = apparmor_socket_getsockopt,
268+ .socket_setsockopt = apparmor_socket_setsockopt,
269+ .socket_shutdown = apparmor_socket_shutdown,
270+
271 .cred_alloc_blank = apparmor_cred_alloc_blank,
272 .cred_free = apparmor_cred_free,
273 .cred_prepare = apparmor_cred_prepare,
274diff --git a/security/apparmor/net.c b/security/apparmor/net.c
ceaf2cfb 275new file mode 100644
fc63ffa9 276index 0000000..1765901
ceaf2cfb 277--- /dev/null
fc63ffa9
AM
278+++ b/security/apparmor/net.c
279@@ -0,0 +1,170 @@
2380c486 280+/*
9474138d
AM
281+ * AppArmor security module
282+ *
fc63ffa9 283+ * This file contains AppArmor network mediation
2380c486 284+ *
9474138d 285+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 286+ * Copyright 2009-2010 Canonical Ltd.
2380c486 287+ *
9474138d
AM
288+ * This program is free software; you can redistribute it and/or
289+ * modify it under the terms of the GNU General Public License as
290+ * published by the Free Software Foundation, version 2 of the
291+ * License.
2380c486
JR
292+ */
293+
9474138d
AM
294+#include "include/apparmor.h"
295+#include "include/audit.h"
296+#include "include/context.h"
fc63ffa9 297+#include "include/net.h"
9474138d 298+#include "include/policy.h"
2380c486 299+
fc63ffa9 300+#include "af_names.h"
2380c486 301+
fc63ffa9
AM
302+static const char *sock_type_names[] = {
303+ "unknown(0)",
304+ "stream",
305+ "dgram",
306+ "raw",
307+ "rdm",
308+ "seqpacket",
309+ "dccp",
310+ "unknown(7)",
311+ "unknown(8)",
312+ "unknown(9)",
313+ "packet",
9474138d
AM
314+};
315+
fc63ffa9 316+/* audit callback for net specific fields */
76514441 317+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 318+{
76514441 319+ struct common_audit_data *sa = va;
9474138d 320+
fc63ffa9
AM
321+ audit_log_format(ab, " family=");
322+ if (address_family_names[sa->u.net.family]) {
323+ audit_log_string(ab, address_family_names[sa->u.net.family]);
324+ } else {
325+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
326+ }
2380c486 327+
fc63ffa9
AM
328+ audit_log_format(ab, " sock_type=");
329+ if (sock_type_names[sa->aad.net.type]) {
330+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
331+ } else {
332+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
333+ }
2380c486 334+
fc63ffa9 335+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
2380c486
JR
336+}
337+
338+/**
fc63ffa9
AM
339+ * audit_net - audit network access
340+ * @profile: profile being enforced (NOT NULL)
341+ * @op: operation being checked
342+ * @family: network family
343+ * @type: network type
344+ * @protocol: network protocol
345+ * @sk: socket auditing is being applied to
346+ * @error: error code for failure else 0
ceaf2cfb 347+ *
fc63ffa9 348+ * Returns: %0 or sa->error else other errorcode on failure
2380c486 349+ */
fc63ffa9
AM
350+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
351+ int protocol, struct sock *sk, int error)
2380c486 352+{
fc63ffa9
AM
353+ int audit_type = AUDIT_APPARMOR_AUTO;
354+ struct common_audit_data sa;
355+ if (sk) {
356+ COMMON_AUDIT_DATA_INIT(&sa, NET);
357+ } else {
358+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
2380c486 359+ }
fc63ffa9 360+ /* todo fill in socket addr info */
2380c486 361+
fc63ffa9
AM
362+ sa.aad.op = op,
363+ sa.u.net.family = family;
364+ sa.u.net.sk = sk;
365+ sa.aad.net.type = type;
366+ sa.aad.net.protocol = protocol;
367+ sa.aad.error = error;
2380c486 368+
fc63ffa9
AM
369+ if (likely(!sa.aad.error)) {
370+ u16 audit_mask = profile->net.audit[sa.u.net.family];
371+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
372+ !(1 << sa.aad.net.type & audit_mask)))
ceaf2cfb 373+ return 0;
fc63ffa9
AM
374+ audit_type = AUDIT_APPARMOR_AUDIT;
375+ } else {
376+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
377+ u16 kill_mask = 0;
378+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
9474138d 379+
fc63ffa9
AM
380+ if (denied & kill_mask)
381+ audit_type = AUDIT_APPARMOR_KILL;
9474138d 382+
fc63ffa9
AM
383+ if ((denied & quiet_mask) &&
384+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
385+ AUDIT_MODE(profile) != AUDIT_ALL)
386+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
9474138d
AM
387+ }
388+
fc63ffa9 389+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
ceaf2cfb
AM
390+}
391+
2380c486 392+/**
fc63ffa9
AM
393+ * aa_net_perm - very course network access check
394+ * @op: operation being checked
395+ * @profile: profile being enforced (NOT NULL)
396+ * @family: network family
397+ * @type: network type
398+ * @protocol: network protocol
2380c486 399+ *
fc63ffa9 400+ * Returns: %0 else error if permission denied
2380c486 401+ */
fc63ffa9
AM
402+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
403+ int protocol, struct sock *sk)
2380c486 404+{
fc63ffa9
AM
405+ u16 family_mask;
406+ int error;
ceaf2cfb 407+
fc63ffa9
AM
408+ if ((family < 0) || (family >= AF_MAX))
409+ return -EINVAL;
ceaf2cfb 410+
fc63ffa9
AM
411+ if ((type < 0) || (type >= SOCK_MAX))
412+ return -EINVAL;
76514441 413+
fc63ffa9
AM
414+ /* unix domain and netlink sockets are handled by ipc */
415+ if (family == AF_UNIX || family == AF_NETLINK)
416+ return 0;
76514441 417+
fc63ffa9 418+ family_mask = profile->net.allow[family];
2380c486 419+
fc63ffa9 420+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
ceaf2cfb 421+
fc63ffa9 422+ return audit_net(profile, op, family, type, protocol, sk, error);
2380c486
JR
423+}
424+
76514441 425+/**
fc63ffa9
AM
426+ * aa_revalidate_sk - Revalidate access to a sock
427+ * @op: operation being checked
428+ * @sk: sock being revalidated (NOT NULL)
76514441 429+ *
fc63ffa9 430+ * Returns: %0 else error if permission denied
76514441 431+ */
fc63ffa9 432+int aa_revalidate_sk(int op, struct sock *sk)
2380c486 433+{
fc63ffa9
AM
434+ struct aa_profile *profile;
435+ int error = 0;
2380c486 436+
fc63ffa9
AM
437+ /* aa_revalidate_sk should not be called from interrupt context
438+ * don't mediate these calls as they are not task related
439+ */
440+ if (in_interrupt())
441+ return 0;
ceaf2cfb 442+
fc63ffa9
AM
443+ profile = __aa_current_profile();
444+ if (!unconfined(profile))
445+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
446+ sk->sk_protocol, sk);
2380c486 447+
fc63ffa9 448+ return error;
2380c486 449+}
fc63ffa9
AM
450diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
451index 52cc865..3b5da44 100644
452--- a/security/apparmor/policy.c
453+++ b/security/apparmor/policy.c
454@@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
455
456 aa_free_file_rules(&profile->file);
457 aa_free_cap_rules(&profile->caps);
458+ aa_free_net_rules(&profile->net);
459 aa_free_rlimit_rules(&profile->rlimits);
460
461 aa_free_sid(profile->sid);
462diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
463index eb3700e..c2b6225 100644
464--- a/security/apparmor/policy_unpack.c
465+++ b/security/apparmor/policy_unpack.c
466@@ -190,6 +190,19 @@ fail:
467 return 0;
468 }
469
470+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
2380c486 471+{
fc63ffa9
AM
472+ if (unpack_nameX(e, AA_U16, name)) {
473+ if (!inbounds(e, sizeof(u16)))
474+ return 0;
475+ if (data)
476+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
477+ e->pos += sizeof(u16);
478+ return 1;
2380c486 479+ }
2380c486
JR
480+ return 0;
481+}
482+
fc63ffa9
AM
483 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
484 {
485 if (unpack_nameX(e, AA_U32, name)) {
486@@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
487 {
488 struct aa_profile *profile = NULL;
489 const char *name = NULL;
490- int error = -EPROTO;
2380c486
JR
491+ size_t size = 0;
492+ int i, error = -EPROTO;
fc63ffa9
AM
493 kernel_cap_t tmpcap;
494 u32 tmp;
495
496@@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
497 if (!unpack_rlimits(e, profile))
498 goto fail;
499
ceaf2cfb 500+ size = unpack_array(e, "net_allowed_af");
2380c486 501+ if (size) {
2380c486
JR
502+
503+ for (i = 0; i < size; i++) {
fc63ffa9
AM
504+ /* discard extraneous rules that this kernel will
505+ * never request
506+ */
507+ if (i > AF_MAX) {
508+ u16 tmp;
509+ if (!unpack_u16(e, &tmp, NULL) ||
510+ !unpack_u16(e, &tmp, NULL) ||
511+ !unpack_u16(e, &tmp, NULL))
512+ goto fail;
513+ continue;
514+ }
76514441 515+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
2380c486 516+ goto fail;
ceaf2cfb 517+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
2380c486 518+ goto fail;
ceaf2cfb 519+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
2380c486
JR
520+ goto fail;
521+ }
ceaf2cfb 522+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
2380c486 523+ goto fail;
ceaf2cfb
AM
524+ /*
525+ * allow unix domain and netlink sockets they are handled
2380c486
JR
526+ * by IPC
527+ */
528+ }
76514441
AM
529+ profile->net.allow[AF_UNIX] = 0xffff;
530+ profile->net.allow[AF_NETLINK] = 0xffff;
2380c486 531+
fc63ffa9
AM
532 /* get file rules */
533 profile->file.dfa = unpack_dfa(e);
534 if (IS_ERR(profile->file.dfa)) {
535--
5361.7.1
537
538From 5f034900aa447abea213c434d6d262d28fd168e7 Mon Sep 17 00:00:00 2001
539From: John Johansen <john.johansen@canonical.com>
540Date: Thu, 22 Jul 2010 02:32:02 -0700
541Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
542
543Signed-off-by: John Johansen <john.johansen@canonical.com>
544---
545 security/apparmor/Kconfig | 9 +
546 security/apparmor/Makefile | 2 +
547 security/apparmor/apparmorfs-24.c | 287 ++++++++++++++++++++++++++++++++
548 security/apparmor/apparmorfs.c | 18 ++-
549 security/apparmor/include/apparmorfs.h | 6 +
550 5 files changed, 320 insertions(+), 2 deletions(-)
551 create mode 100644 security/apparmor/apparmorfs-24.c
552
553diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
554index 9b9013b..51ebf96 100644
555--- a/security/apparmor/Kconfig
556+++ b/security/apparmor/Kconfig
557@@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
558 boot.
559
560 If you are unsure how to answer this question, answer 1.
2380c486 561+
fc63ffa9
AM
562+config SECURITY_APPARMOR_COMPAT_24
563+ bool "Enable AppArmor 2.4 compatability"
564+ depends on SECURITY_APPARMOR
565+ default y
566+ help
567+ This option enables compatability with AppArmor 2.4. It is
568+ recommended if compatability with older versions of AppArmor
569+ is desired.
570diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
571index a9a1db0..e5e8968 100644
572--- a/security/apparmor/Makefile
573+++ b/security/apparmor/Makefile
574@@ -6,6 +6,8 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
575 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
576 resource.o sid.o file.o net.o
577
578+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
9474138d 579+
fc63ffa9
AM
580 clean-files: capability_names.h af_names.h
581
582 quiet_cmd_make-caps = GEN $@
583diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
ceaf2cfb 584new file mode 100644
fc63ffa9 585index 0000000..dc8c744
ceaf2cfb 586--- /dev/null
fc63ffa9
AM
587+++ b/security/apparmor/apparmorfs-24.c
588@@ -0,0 +1,287 @@
2380c486 589+/*
9474138d
AM
590+ * AppArmor security module
591+ *
fc63ffa9 592+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
2380c486 593+ *
9474138d 594+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 595+ * Copyright 2009-2010 Canonical Ltd.
2380c486 596+ *
9474138d
AM
597+ * This program is free software; you can redistribute it and/or
598+ * modify it under the terms of the GNU General Public License as
599+ * published by the Free Software Foundation, version 2 of the
600+ * License.
fc63ffa9
AM
601+ *
602+ *
603+ * This file contain functions providing an interface for <= AppArmor 2.4
604+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
605+ * being set (see Makefile).
2380c486
JR
606+ */
607+
fc63ffa9
AM
608+#include <linux/security.h>
609+#include <linux/vmalloc.h>
610+#include <linux/module.h>
611+#include <linux/seq_file.h>
612+#include <linux/uaccess.h>
613+#include <linux/namei.h>
614+
9474138d 615+#include "include/apparmor.h"
fc63ffa9 616+#include "include/audit.h"
76514441 617+#include "include/context.h"
9474138d 618+#include "include/policy.h"
2380c486 619+
76514441 620+
fc63ffa9
AM
621+/* apparmor/matching */
622+static ssize_t aa_matching_read(struct file *file, char __user *buf,
623+ size_t size, loff_t *ppos)
624+{
625+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
626+ "user::other";
627+
628+ return simple_read_from_buffer(buf, size, ppos, matching,
629+ sizeof(matching) - 1);
630+}
631+
632+const struct file_operations aa_fs_matching_fops = {
633+ .read = aa_matching_read,
634+};
635+
636+/* apparmor/features */
637+static ssize_t aa_features_read(struct file *file, char __user *buf,
638+ size_t size, loff_t *ppos)
639+{
640+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
641+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
642+
643+ return simple_read_from_buffer(buf, size, ppos, features,
644+ sizeof(features) - 1);
645+}
646+
647+const struct file_operations aa_fs_features_fops = {
648+ .read = aa_features_read,
649+};
650+
ceaf2cfb 651+/**
fc63ffa9
AM
652+ * __next_namespace - find the next namespace to list
653+ * @root: root namespace to stop search at (NOT NULL)
654+ * @ns: current ns position (NOT NULL)
ceaf2cfb 655+ *
fc63ffa9
AM
656+ * Find the next namespace from @ns under @root and handle all locking needed
657+ * while switching current namespace.
ceaf2cfb 658+ *
fc63ffa9
AM
659+ * Returns: next namespace or NULL if at last namespace under @root
660+ * NOTE: will not unlock root->lock
ceaf2cfb 661+ */
fc63ffa9
AM
662+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
663+ struct aa_namespace *ns)
2380c486 664+{
fc63ffa9 665+ struct aa_namespace *parent;
76514441 666+
fc63ffa9
AM
667+ /* is next namespace a child */
668+ if (!list_empty(&ns->sub_ns)) {
669+ struct aa_namespace *next;
670+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
671+ read_lock(&next->lock);
672+ return next;
673+ }
2380c486 674+
fc63ffa9
AM
675+ /* check if the next ns is a sibling, parent, gp, .. */
676+ parent = ns->parent;
677+ while (parent) {
678+ read_unlock(&ns->lock);
679+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
680+ read_lock(&ns->lock);
681+ return ns;
682+ }
683+ if (parent == root)
684+ return NULL;
685+ ns = parent;
686+ parent = parent->parent;
2380c486 687+ }
2380c486 688+
fc63ffa9 689+ return NULL;
2380c486
JR
690+}
691+
ceaf2cfb 692+/**
fc63ffa9
AM
693+ * __first_profile - find the first profile in a namespace
694+ * @root: namespace that is root of profiles being displayed (NOT NULL)
695+ * @ns: namespace to start in (NOT NULL)
ceaf2cfb 696+ *
fc63ffa9 697+ * Returns: unrefcounted profile or NULL if no profile
ceaf2cfb 698+ */
fc63ffa9
AM
699+static struct aa_profile *__first_profile(struct aa_namespace *root,
700+ struct aa_namespace *ns)
2380c486 701+{
fc63ffa9
AM
702+ for ( ; ns; ns = __next_namespace(root, ns)) {
703+ if (!list_empty(&ns->base.profiles))
704+ return list_first_entry(&ns->base.profiles,
705+ struct aa_profile, base.list);
2380c486 706+ }
fc63ffa9 707+ return NULL;
2380c486
JR
708+}
709+
ceaf2cfb 710+/**
fc63ffa9
AM
711+ * __next_profile - step to the next profile in a profile tree
712+ * @profile: current profile in tree (NOT NULL)
713+ *
714+ * Perform a depth first taversal on the profile tree in a namespace
ceaf2cfb 715+ *
fc63ffa9
AM
716+ * Returns: next profile or NULL if done
717+ * Requires: profile->ns.lock to be held
ceaf2cfb 718+ */
fc63ffa9 719+static struct aa_profile *__next_profile(struct aa_profile *p)
2380c486 720+{
fc63ffa9
AM
721+ struct aa_profile *parent;
722+ struct aa_namespace *ns = p->ns;
2380c486 723+
fc63ffa9
AM
724+ /* is next profile a child */
725+ if (!list_empty(&p->base.profiles))
726+ return list_first_entry(&p->base.profiles, typeof(*p),
727+ base.list);
2380c486 728+
fc63ffa9
AM
729+ /* is next profile a sibling, parent sibling, gp, subling, .. */
730+ parent = p->parent;
731+ while (parent) {
732+ list_for_each_entry_continue(p, &parent->base.profiles,
733+ base.list)
734+ return p;
735+ p = parent;
736+ parent = parent->parent;
ceaf2cfb
AM
737+ }
738+
fc63ffa9
AM
739+ /* is next another profile in the namespace */
740+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
741+ return p;
2380c486 742+
fc63ffa9 743+ return NULL;
2380c486
JR
744+}
745+
ceaf2cfb 746+/**
fc63ffa9
AM
747+ * next_profile - step to the next profile in where ever it may be
748+ * @root: root namespace (NOT NULL)
749+ * @profile: current profile (NOT NULL)
ceaf2cfb 750+ *
fc63ffa9 751+ * Returns: next profile or NULL if there isn't one
ceaf2cfb 752+ */
fc63ffa9
AM
753+static struct aa_profile *next_profile(struct aa_namespace *root,
754+ struct aa_profile *profile)
2380c486 755+{
fc63ffa9
AM
756+ struct aa_profile *next = __next_profile(profile);
757+ if (next)
758+ return next;
9474138d 759+
fc63ffa9
AM
760+ /* finished all profiles in namespace move to next namespace */
761+ return __first_profile(root, __next_namespace(root, profile->ns));
9474138d 762+}
2380c486 763+
fc63ffa9
AM
764+/**
765+ * p_start - start a depth first traversal of profile tree
766+ * @f: seq_file to fill
767+ * @pos: current position
9474138d 768+ *
fc63ffa9 769+ * Returns: first profile under current namespace or NULL if none found
9474138d 770+ *
fc63ffa9 771+ * acquires first ns->lock
76514441 772+ */
fc63ffa9
AM
773+static void *p_start(struct seq_file *f, loff_t *pos)
774+ __acquires(root->lock)
2380c486 775+{
fc63ffa9
AM
776+ struct aa_profile *profile = NULL;
777+ struct aa_namespace *root = aa_current_profile()->ns;
778+ loff_t l = *pos;
779+ f->private = aa_get_namespace(root);
9474138d 780+
9474138d 781+
fc63ffa9
AM
782+ /* find the first profile */
783+ read_lock(&root->lock);
784+ profile = __first_profile(root, root);
76514441 785+
fc63ffa9
AM
786+ /* skip to position */
787+ for (; profile && l > 0; l--)
788+ profile = next_profile(root, profile);
789+
790+ return profile;
76514441
AM
791+}
792+
793+/**
fc63ffa9
AM
794+ * p_next - read the next profile entry
795+ * @f: seq_file to fill
796+ * @p: profile previously returned
797+ * @pos: current position
76514441 798+ *
fc63ffa9 799+ * Returns: next profile after @p or NULL if none
76514441 800+ *
fc63ffa9 801+ * may acquire/release locks in namespace tree as necessary
76514441 802+ */
fc63ffa9 803+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
9474138d 804+{
fc63ffa9
AM
805+ struct aa_profile *profile = p;
806+ struct aa_namespace *root = f->private;
807+ (*pos)++;
808+
809+ return next_profile(root, profile);
9474138d
AM
810+}
811+
812+/**
fc63ffa9
AM
813+ * p_stop - stop depth first traversal
814+ * @f: seq_file we are filling
815+ * @p: the last profile writen
ceaf2cfb 816+ *
fc63ffa9 817+ * Release all locking done by p_start/p_next on namespace tree
9474138d 818+ */
fc63ffa9
AM
819+static void p_stop(struct seq_file *f, void *p)
820+ __releases(root->lock)
9474138d 821+{
fc63ffa9
AM
822+ struct aa_profile *profile = p;
823+ struct aa_namespace *root = f->private, *ns;
2380c486 824+
fc63ffa9
AM
825+ if (profile) {
826+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
827+ read_unlock(&ns->lock);
828+ }
829+ read_unlock(&root->lock);
830+ aa_put_namespace(root);
9474138d
AM
831+}
832+
ceaf2cfb 833+/**
fc63ffa9
AM
834+ * seq_show_profile - show a profile entry
835+ * @f: seq_file to file
836+ * @p: current position (profile) (NOT NULL)
837+ *
838+ * Returns: error on failure
ceaf2cfb 839+ */
fc63ffa9 840+static int seq_show_profile(struct seq_file *f, void *p)
9474138d 841+{
fc63ffa9
AM
842+ struct aa_profile *profile = (struct aa_profile *)p;
843+ struct aa_namespace *root = f->private;
2380c486 844+
fc63ffa9
AM
845+ if (profile->ns != root)
846+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
847+ seq_printf(f, "%s (%s)\n", profile->base.hname,
848+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
2380c486 849+
fc63ffa9 850+ return 0;
9474138d 851+}
9474138d 852+
fc63ffa9
AM
853+static const struct seq_operations aa_fs_profiles_op = {
854+ .start = p_start,
855+ .next = p_next,
856+ .stop = p_stop,
857+ .show = seq_show_profile,
858+};
9474138d 859+
fc63ffa9 860+static int profiles_open(struct inode *inode, struct file *file)
9474138d 861+{
fc63ffa9 862+ return seq_open(file, &aa_fs_profiles_op);
9474138d
AM
863+}
864+
fc63ffa9 865+static int profiles_release(struct inode *inode, struct file *file)
9474138d 866+{
fc63ffa9 867+ return seq_release(inode, file);
9474138d 868+}
fc63ffa9
AM
869+
870+const struct file_operations aa_fs_profiles_fops = {
871+ .open = profiles_open,
872+ .read = seq_read,
873+ .llseek = seq_lseek,
874+ .release = profiles_release,
875+};
876diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
877index 7320331..0e27449 100644
878--- a/security/apparmor/apparmorfs.c
879+++ b/security/apparmor/apparmorfs.c
880@@ -182,7 +182,11 @@ void __init aa_destroy_aafs(void)
881 aafs_remove(".remove");
882 aafs_remove(".replace");
883 aafs_remove(".load");
884-
885+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
886+ aafs_remove("profiles");
887+ aafs_remove("matching");
888+ aafs_remove("features");
889+#endif
890 securityfs_remove(aa_fs_dentry);
891 aa_fs_dentry = NULL;
892 }
893@@ -213,7 +217,17 @@ int __init aa_create_aafs(void)
894 aa_fs_dentry = NULL;
895 goto error;
896 }
897-
898+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
899+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
900+ if (error)
901+ goto error;
902+ error = aafs_create("features", 0444, &aa_fs_features_fops);
903+ if (error)
904+ goto error;
905+#endif
906+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
907+ if (error)
908+ goto error;
909 error = aafs_create(".load", 0640, &aa_fs_profile_load);
910 if (error)
911 goto error;
912diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
913index cb1e93a..14f955c 100644
914--- a/security/apparmor/include/apparmorfs.h
915+++ b/security/apparmor/include/apparmorfs.h
916@@ -17,4 +17,10 @@
917
918 extern void __init aa_destroy_aafs(void);
919
920+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
921+extern const struct file_operations aa_fs_matching_fops;
922+extern const struct file_operations aa_fs_features_fops;
923+extern const struct file_operations aa_fs_profiles_fops;
924+#endif
925+
926 #endif /* __AA_APPARMORFS_H */
76514441
AM
927--
9281.7.1
929
This page took 3.656717 seconds and 4 git commands to generate.