]> git.proxmox.com Git - pve-kernel-3.10.0.git/blame - 0002-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch
update intel network drivers
[pve-kernel-3.10.0.git] / 0002-UBUNTU-SAUCE-AppArmor-basic-networking-rules.patch
CommitLineData
c3701be9
DM
1From e83b058f391e96a2a640fb2e2812d50ef67e0f43 Mon Sep 17 00:00:00 2001
2From: John Johansen <john.johansen@canonical.com>
3Date: Mon, 4 Oct 2010 15:03:36 -0700
4Subject: [PATCH 2/4] UBUNTU: SAUCE: AppArmor: basic networking rules
5
6Base support for network mediation.
7
8Signed-off-by: John Johansen <john.johansen@canonical.com>
9---
10 security/apparmor/.gitignore | 1 +
11 security/apparmor/Makefile | 42 +++++++++-
12 security/apparmor/apparmorfs.c | 1 +
13 security/apparmor/include/audit.h | 4 +
14 security/apparmor/include/net.h | 44 ++++++++++
15 security/apparmor/include/policy.h | 3 +
16 security/apparmor/lsm.c | 112 +++++++++++++++++++++++++
17 security/apparmor/net.c | 162 +++++++++++++++++++++++++++++++++++++
18 security/apparmor/policy.c | 1 +
19 security/apparmor/policy_unpack.c | 46 +++++++++++
20 10 files changed, 414 insertions(+), 2 deletions(-)
21 create mode 100644 security/apparmor/include/net.h
22 create mode 100644 security/apparmor/net.c
23
24diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
25index 9cdec70..d5b291e 100644
26--- a/security/apparmor/.gitignore
27+++ b/security/apparmor/.gitignore
28@@ -1,5 +1,6 @@
29 #
30 # Generated include files
31 #
32+net_names.h
33 capability_names.h
34 rlim_names.h
35diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
36index 5706b74..e270692 100644
37--- a/security/apparmor/Makefile
38+++ b/security/apparmor/Makefile
39@@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
40
41 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
42 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
43- resource.o sid.o file.o
44+ resource.o sid.o file.o net.o
45
46-clean-files := capability_names.h rlim_names.h
47+clean-files := capability_names.h rlim_names.h net_names.h
48
49
50 # Build a lower case string table of capability names
51@@ -20,6 +20,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
52 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
53 echo "};" >> $@
54
55+# Build a lower case string table of address family names
56+# Transform lines from
57+# define AF_LOCAL 1 /* POSIX name for AF_UNIX */
58+# #define AF_INET 2 /* Internet IP Protocol */
59+# to
60+# [1] = "local",
61+# [2] = "inet",
62+#
63+# and build the securityfs entries for the mapping.
64+# Transforms lines from
65+# #define AF_INET 2 /* Internet IP Protocol */
66+# to
67+# #define AA_FS_AF_MASK "local inet"
68+quiet_cmd_make-af = GEN $@
69+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
70+ sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
71+ 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
72+ echo "};" >> $@ ;\
73+ echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
74+ sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
75+ $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
76+
77+# Build a lower case string table of sock type names
78+# Transform lines from
79+# SOCK_STREAM = 1,
80+# to
81+# [1] = "stream",
82+quiet_cmd_make-sock = GEN $@
83+cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
84+ sed $^ >>$@ -r -n \
85+ -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
86+ echo "};" >> $@
87
88 # Build a lower case string table of rlimit names.
89 # Transforms lines from
90@@ -56,6 +88,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
91 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
92
93 $(obj)/capability.o : $(obj)/capability_names.h
94+$(obj)/net.o : $(obj)/net_names.h
95 $(obj)/resource.o : $(obj)/rlim_names.h
96 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
97 $(src)/Makefile
98@@ -63,3 +96,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
99 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
100 $(src)/Makefile
101 $(call cmd,make-rlim)
102+$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
103+ $(srctree)/include/linux/net.h \
104+ $(src)/Makefile
105+ $(call cmd,make-af)
106+ $(call cmd,make-sock)
107diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
108index 42b7c9f..114fb23 100644
109--- a/security/apparmor/apparmorfs.c
110+++ b/security/apparmor/apparmorfs.c
111@@ -429,6 +429,7 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
112 static struct aa_fs_entry aa_fs_entry_features[] = {
113 AA_FS_DIR("domain", aa_fs_entry_domain),
114 AA_FS_DIR("file", aa_fs_entry_file),
115+ AA_FS_DIR("network", aa_fs_entry_network),
116 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
117 AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
118 { }
119diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
120index 69d8cae..4af6523 100644
121--- a/security/apparmor/include/audit.h
122+++ b/security/apparmor/include/audit.h
123@@ -127,6 +127,10 @@ struct apparmor_audit_data {
124 u32 denied;
125 kuid_t ouid;
126 } fs;
127+ struct {
128+ int type, protocol;
129+ struct sock *sk;
130+ } net;
131 };
132 };
133
134diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
135new file mode 100644
136index 0000000..cb8a121
137--- /dev/null
138+++ b/security/apparmor/include/net.h
139@@ -0,0 +1,44 @@
140+/*
141+ * AppArmor security module
142+ *
143+ * This file contains AppArmor network mediation definitions.
144+ *
145+ * Copyright (C) 1998-2008 Novell/SUSE
146+ * Copyright 2009-2012 Canonical Ltd.
147+ *
148+ * This program is free software; you can redistribute it and/or
149+ * modify it under the terms of the GNU General Public License as
150+ * published by the Free Software Foundation, version 2 of the
151+ * License.
152+ */
153+
154+#ifndef __AA_NET_H
155+#define __AA_NET_H
156+
157+#include <net/sock.h>
158+
159+#include "apparmorfs.h"
160+
161+/* struct aa_net - network confinement data
162+ * @allowed: basic network families permissions
163+ * @audit_network: which network permissions to force audit
164+ * @quiet_network: which network permissions to quiet rejects
165+ */
166+struct aa_net {
167+ u16 allow[AF_MAX];
168+ u16 audit[AF_MAX];
169+ u16 quiet[AF_MAX];
170+};
171+
172+extern struct aa_fs_entry aa_fs_entry_network[];
173+
174+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
175+ int type, int protocol, struct sock *sk);
176+extern int aa_revalidate_sk(int op, struct sock *sk);
177+
178+static inline void aa_free_net_rules(struct aa_net *new)
179+{
180+ /* NOP */
181+}
182+
183+#endif /* __AA_NET_H */
184diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
185index bda4569..eb13a73 100644
186--- a/security/apparmor/include/policy.h
187+++ b/security/apparmor/include/policy.h
188@@ -27,6 +27,7 @@
189 #include "capability.h"
190 #include "domain.h"
191 #include "file.h"
192+#include "net.h"
193 #include "resource.h"
194
195 extern const char *const profile_mode_names[];
196@@ -157,6 +158,7 @@ struct aa_policydb {
197 * @policy: general match rules governing policy
198 * @file: The set of rules governing basic file access and domain transitions
199 * @caps: capabilities for the profile
200+ * @net: network controls for the profile
201 * @rlimits: rlimits for the profile
202 *
203 * The AppArmor profile contains the basic confinement data. Each profile
204@@ -194,6 +196,7 @@ struct aa_profile {
205 struct aa_policydb policy;
206 struct aa_file_rules file;
207 struct aa_caps caps;
208+ struct aa_net net;
209 struct aa_rlimit rlimits;
210 };
211
212diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
213index b21830e..1bce440 100644
214--- a/security/apparmor/lsm.c
215+++ b/security/apparmor/lsm.c
216@@ -32,6 +32,7 @@
217 #include "include/context.h"
218 #include "include/file.h"
219 #include "include/ipc.h"
220+#include "include/net.h"
221 #include "include/path.h"
222 #include "include/policy.h"
223 #include "include/procattr.h"
224@@ -614,6 +615,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
225 return error;
226 }
227
228+static int apparmor_socket_create(int family, int type, int protocol, int kern)
229+{
230+ struct aa_profile *profile;
231+ int error = 0;
232+
233+ if (kern)
234+ return 0;
235+
236+ profile = __aa_current_profile();
237+ if (!unconfined(profile))
238+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
239+ NULL);
240+ return error;
241+}
242+
243+static int apparmor_socket_bind(struct socket *sock,
244+ struct sockaddr *address, int addrlen)
245+{
246+ struct sock *sk = sock->sk;
247+
248+ return aa_revalidate_sk(OP_BIND, sk);
249+}
250+
251+static int apparmor_socket_connect(struct socket *sock,
252+ struct sockaddr *address, int addrlen)
253+{
254+ struct sock *sk = sock->sk;
255+
256+ return aa_revalidate_sk(OP_CONNECT, sk);
257+}
258+
259+static int apparmor_socket_listen(struct socket *sock, int backlog)
260+{
261+ struct sock *sk = sock->sk;
262+
263+ return aa_revalidate_sk(OP_LISTEN, sk);
264+}
265+
266+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
267+{
268+ struct sock *sk = sock->sk;
269+
270+ return aa_revalidate_sk(OP_ACCEPT, sk);
271+}
272+
273+static int apparmor_socket_sendmsg(struct socket *sock,
274+ struct msghdr *msg, int size)
275+{
276+ struct sock *sk = sock->sk;
277+
278+ return aa_revalidate_sk(OP_SENDMSG, sk);
279+}
280+
281+static int apparmor_socket_recvmsg(struct socket *sock,
282+ struct msghdr *msg, int size, int flags)
283+{
284+ struct sock *sk = sock->sk;
285+
286+ return aa_revalidate_sk(OP_RECVMSG, sk);
287+}
288+
289+static int apparmor_socket_getsockname(struct socket *sock)
290+{
291+ struct sock *sk = sock->sk;
292+
293+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
294+}
295+
296+static int apparmor_socket_getpeername(struct socket *sock)
297+{
298+ struct sock *sk = sock->sk;
299+
300+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
301+}
302+
303+static int apparmor_socket_getsockopt(struct socket *sock, int level,
304+ int optname)
305+{
306+ struct sock *sk = sock->sk;
307+
308+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
309+}
310+
311+static int apparmor_socket_setsockopt(struct socket *sock, int level,
312+ int optname)
313+{
314+ struct sock *sk = sock->sk;
315+
316+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
317+}
318+
319+static int apparmor_socket_shutdown(struct socket *sock, int how)
320+{
321+ struct sock *sk = sock->sk;
322+
323+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
324+}
325+
326 static struct security_operations apparmor_ops = {
327 .name = "apparmor",
328
329@@ -646,6 +745,19 @@ static struct security_operations apparmor_ops = {
330 .getprocattr = apparmor_getprocattr,
331 .setprocattr = apparmor_setprocattr,
332
333+ .socket_create = apparmor_socket_create,
334+ .socket_bind = apparmor_socket_bind,
335+ .socket_connect = apparmor_socket_connect,
336+ .socket_listen = apparmor_socket_listen,
337+ .socket_accept = apparmor_socket_accept,
338+ .socket_sendmsg = apparmor_socket_sendmsg,
339+ .socket_recvmsg = apparmor_socket_recvmsg,
340+ .socket_getsockname = apparmor_socket_getsockname,
341+ .socket_getpeername = apparmor_socket_getpeername,
342+ .socket_getsockopt = apparmor_socket_getsockopt,
343+ .socket_setsockopt = apparmor_socket_setsockopt,
344+ .socket_shutdown = apparmor_socket_shutdown,
345+
346 .cred_alloc_blank = apparmor_cred_alloc_blank,
347 .cred_free = apparmor_cred_free,
348 .cred_prepare = apparmor_cred_prepare,
349diff --git a/security/apparmor/net.c b/security/apparmor/net.c
350new file mode 100644
351index 0000000..003dd18
352--- /dev/null
353+++ b/security/apparmor/net.c
354@@ -0,0 +1,162 @@
355+/*
356+ * AppArmor security module
357+ *
358+ * This file contains AppArmor network mediation
359+ *
360+ * Copyright (C) 1998-2008 Novell/SUSE
361+ * Copyright 2009-2012 Canonical Ltd.
362+ *
363+ * This program is free software; you can redistribute it and/or
364+ * modify it under the terms of the GNU General Public License as
365+ * published by the Free Software Foundation, version 2 of the
366+ * License.
367+ */
368+
369+#include "include/apparmor.h"
370+#include "include/audit.h"
371+#include "include/context.h"
372+#include "include/net.h"
373+#include "include/policy.h"
374+
375+#include "net_names.h"
376+
377+struct aa_fs_entry aa_fs_entry_network[] = {
378+ AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
379+ { }
380+};
381+
382+/* audit callback for net specific fields */
383+static void audit_cb(struct audit_buffer *ab, void *va)
384+{
385+ struct common_audit_data *sa = va;
386+
387+ audit_log_format(ab, " family=");
388+ if (address_family_names[sa->u.net->family]) {
389+ audit_log_string(ab, address_family_names[sa->u.net->family]);
390+ } else {
391+ audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
392+ }
393+ audit_log_format(ab, " sock_type=");
394+ if (sock_type_names[sa->aad->net.type]) {
395+ audit_log_string(ab, sock_type_names[sa->aad->net.type]);
396+ } else {
397+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
398+ }
399+ audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
400+}
401+
402+/**
403+ * audit_net - audit network access
404+ * @profile: profile being enforced (NOT NULL)
405+ * @op: operation being checked
406+ * @family: network family
407+ * @type: network type
408+ * @protocol: network protocol
409+ * @sk: socket auditing is being applied to
410+ * @error: error code for failure else 0
411+ *
412+ * Returns: %0 or sa->error else other errorcode on failure
413+ */
414+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
415+ int protocol, struct sock *sk, int error)
416+{
417+ int audit_type = AUDIT_APPARMOR_AUTO;
418+ struct common_audit_data sa;
419+ struct apparmor_audit_data aad = { };
420+ struct lsm_network_audit net = { };
421+ if (sk) {
422+ sa.type = LSM_AUDIT_DATA_NET;
423+ } else {
424+ sa.type = LSM_AUDIT_DATA_NONE;
425+ }
426+ /* todo fill in socket addr info */
427+ sa.aad = &aad;
428+ sa.u.net = &net;
429+ sa.aad->op = op,
430+ sa.u.net->family = family;
431+ sa.u.net->sk = sk;
432+ sa.aad->net.type = type;
433+ sa.aad->net.protocol = protocol;
434+ sa.aad->error = error;
435+
436+ if (likely(!sa.aad->error)) {
437+ u16 audit_mask = profile->net.audit[sa.u.net->family];
438+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
439+ !(1 << sa.aad->net.type & audit_mask)))
440+ return 0;
441+ audit_type = AUDIT_APPARMOR_AUDIT;
442+ } else {
443+ u16 quiet_mask = profile->net.quiet[sa.u.net->family];
444+ u16 kill_mask = 0;
445+ u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
446+
447+ if (denied & kill_mask)
448+ audit_type = AUDIT_APPARMOR_KILL;
449+
450+ if ((denied & quiet_mask) &&
451+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
452+ AUDIT_MODE(profile) != AUDIT_ALL)
453+ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
454+ }
455+
456+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
457+}
458+
459+/**
460+ * aa_net_perm - very course network access check
461+ * @op: operation being checked
462+ * @profile: profile being enforced (NOT NULL)
463+ * @family: network family
464+ * @type: network type
465+ * @protocol: network protocol
466+ *
467+ * Returns: %0 else error if permission denied
468+ */
469+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
470+ int protocol, struct sock *sk)
471+{
472+ u16 family_mask;
473+ int error;
474+
475+ if ((family < 0) || (family >= AF_MAX))
476+ return -EINVAL;
477+
478+ if ((type < 0) || (type >= SOCK_MAX))
479+ return -EINVAL;
480+
481+ /* unix domain and netlink sockets are handled by ipc */
482+ if (family == AF_UNIX || family == AF_NETLINK)
483+ return 0;
484+
485+ family_mask = profile->net.allow[family];
486+
487+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
488+
489+ return audit_net(profile, op, family, type, protocol, sk, error);
490+}
491+
492+/**
493+ * aa_revalidate_sk - Revalidate access to a sock
494+ * @op: operation being checked
495+ * @sk: sock being revalidated (NOT NULL)
496+ *
497+ * Returns: %0 else error if permission denied
498+ */
499+int aa_revalidate_sk(int op, struct sock *sk)
500+{
501+ struct aa_profile *profile;
502+ int error = 0;
503+
504+ /* aa_revalidate_sk should not be called from interrupt context
505+ * don't mediate these calls as they are not task related
506+ */
507+ if (in_interrupt())
508+ return 0;
509+
510+ profile = __aa_current_profile();
511+ if (!unconfined(profile))
512+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
513+ sk->sk_protocol, sk);
514+
515+ return error;
516+}
517diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
518index 8132003..56e5304 100644
519--- a/security/apparmor/policy.c
520+++ b/security/apparmor/policy.c
521@@ -747,6 +747,7 @@ static void free_profile(struct aa_profile *profile)
522
523 aa_free_file_rules(&profile->file);
524 aa_free_cap_rules(&profile->caps);
525+ aa_free_net_rules(&profile->net);
526 aa_free_rlimit_rules(&profile->rlimits);
527
528 aa_free_sid(profile->sid);
529diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
530index 329b1fd..1b90dfa 100644
531--- a/security/apparmor/policy_unpack.c
532+++ b/security/apparmor/policy_unpack.c
533@@ -193,6 +193,19 @@ fail:
534 return 0;
535 }
536
537+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
538+{
539+ if (unpack_nameX(e, AA_U16, name)) {
540+ if (!inbounds(e, sizeof(u16)))
541+ return 0;
542+ if (data)
543+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
544+ e->pos += sizeof(u16);
545+ return 1;
546+ }
547+ return 0;
548+}
549+
550 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
551 {
552 if (unpack_nameX(e, AA_U32, name)) {
553@@ -471,6 +484,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
554 {
555 struct aa_profile *profile = NULL;
556 const char *name = NULL;
557+ size_t size = 0;
558 int i, error = -EPROTO;
559 kernel_cap_t tmpcap;
560 u32 tmp;
561@@ -564,6 +578,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
562 if (!unpack_rlimits(e, profile))
563 goto fail;
564
565+ size = unpack_array(e, "net_allowed_af");
566+ if (size) {
567+
568+ for (i = 0; i < size; i++) {
569+ /* discard extraneous rules that this kernel will
570+ * never request
571+ */
572+ if (i >= AF_MAX) {
573+ u16 tmp;
574+ if (!unpack_u16(e, &tmp, NULL) ||
575+ !unpack_u16(e, &tmp, NULL) ||
576+ !unpack_u16(e, &tmp, NULL))
577+ goto fail;
578+ continue;
579+ }
580+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
581+ goto fail;
582+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
583+ goto fail;
584+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
585+ goto fail;
586+ }
587+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
588+ goto fail;
589+ }
590+ /*
591+ * allow unix domain and netlink sockets they are handled
592+ * by IPC
593+ */
594+ profile->net.allow[AF_UNIX] = 0xffff;
595+ profile->net.allow[AF_NETLINK] = 0xffff;
596+
597 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
598 /* generic policy dfa - optional and may be NULL */
599 profile->policy.dfa = unpack_dfa(e);
600--
6011.8.3.2
602