]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.apparmor/apparmor-network.diff
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.apparmor / apparmor-network.diff
CommitLineData
4d1e5b62
AF
1From: John Johansen <jjohansen@suse.de>
2Subject: AppArmor: Simplified network controls for AppArmor
3
4Simple network control determining which network families a confined
5application has access to.
6
7Signed-off-by: John Johansen <jjohansen@suse.de>
8
9---
10 security/apparmor/Makefile | 7 +
11 security/apparmor/apparmor.h | 9 ++
12 security/apparmor/lsm.c | 129 ++++++++++++++++++++++++++++++++++-
13 security/apparmor/main.c | 107 ++++++++++++++++++++++++++++-
14 security/apparmor/module_interface.c | 26 ++++++-
15 5 files changed, 271 insertions(+), 7 deletions(-)
16
17--- a/security/apparmor/Makefile
18+++ b/security/apparmor/Makefile
19@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
20 quiet_cmd_make-caps = GEN $@
21 cmd_make-caps = 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 > $@
22
23-$(obj)/main.o : $(obj)/capability_names.h
24+quiet_cmd_make-af = GEN $@
25+cmd_make-af = 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 > $@
26+
27+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
28 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
29 $(call cmd,make-caps)
30+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
31+ $(call cmd,make-af)
32--- a/security/apparmor/apparmor.h
33+++ b/security/apparmor/apparmor.h
34@@ -16,6 +16,8 @@
35 #include <linux/fs.h>
36 #include <linux/binfmts.h>
37 #include <linux/rcupdate.h>
38+#include <linux/socket.h>
39+#include <net/sock.h>
40
41 /*
42 * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
43@@ -212,6 +214,9 @@ struct aa_profile {
44 struct list_head task_contexts;
45 spinlock_t lock;
46 unsigned long int_flags;
47+ u16 network_families[AF_MAX];
48+ u16 audit_network[AF_MAX];
49+ u16 quiet_network[AF_MAX];
50 };
51
52 extern struct list_head profile_ns_list;
53@@ -258,6 +263,7 @@ struct aa_audit {
54 int request_mask, denied_mask, audit_mask;
55 struct iattr *iattr;
56 pid_t task, parent;
57+ int family, type, protocol;
58 int error_code;
59 };
60
61@@ -319,6 +325,9 @@ extern void aa_change_task_context(struc
62 struct aa_profile *previous_profile);
63 extern int aa_may_ptrace(struct aa_task_context *cxt,
64 struct aa_profile *tracee);
65+extern int aa_net_perm(struct aa_profile *profile, char *operation,
66+ int family, int type, int protocol);
67+extern int aa_revalidate_sk(struct sock *sk, char *operation);
68
69 /* lsm.c */
70 extern int apparmor_initialized;
71--- a/security/apparmor/lsm.c
72+++ b/security/apparmor/lsm.c
73@@ -18,6 +18,7 @@
74 #include <linux/ctype.h>
75 #include <linux/sysctl.h>
76 #include <linux/audit.h>
77+#include <net/sock.h>
78
79 #include "apparmor.h"
80 #include "inline.h"
81@@ -680,6 +681,117 @@ static void apparmor_task_free_security(
82 aa_release(task);
83 }
84
85+static int apparmor_socket_create(int family, int type, int protocol, int kern)
86+{
87+ struct aa_profile *profile;
88+ int error = 0;
89+
90+ if (kern)
91+ return 0;
92+
93+ profile = aa_get_profile(current);
94+ if (profile)
95+ error = aa_net_perm(profile, "socket_create", family,
96+ type, protocol);
97+ aa_put_profile(profile);
98+
99+ return error;
100+}
101+
102+static int apparmor_socket_post_create(struct socket *sock, int family,
103+ int type, int protocol, int kern)
104+{
105+ struct sock *sk = sock->sk;
106+
107+ if (kern)
108+ return 0;
109+
110+ return aa_revalidate_sk(sk, "socket_post_create");
111+}
112+
113+static int apparmor_socket_bind(struct socket *sock,
114+ struct sockaddr *address, int addrlen)
115+{
116+ struct sock *sk = sock->sk;
117+
118+ return aa_revalidate_sk(sk, "socket_bind");
119+}
120+
121+static int apparmor_socket_connect(struct socket *sock,
122+ struct sockaddr *address, int addrlen)
123+{
124+ struct sock *sk = sock->sk;
125+
126+ return aa_revalidate_sk(sk, "socket_connect");
127+}
128+
129+static int apparmor_socket_listen(struct socket *sock, int backlog)
130+{
131+ struct sock *sk = sock->sk;
132+
133+ return aa_revalidate_sk(sk, "socket_listen");
134+}
135+
136+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
137+{
138+ struct sock *sk = sock->sk;
139+
140+ return aa_revalidate_sk(sk, "socket_accept");
141+}
142+
143+static int apparmor_socket_sendmsg(struct socket *sock,
144+ struct msghdr *msg, int size)
145+{
146+ struct sock *sk = sock->sk;
147+
148+ return aa_revalidate_sk(sk, "socket_sendmsg");
149+}
150+
151+static int apparmor_socket_recvmsg(struct socket *sock,
152+ struct msghdr *msg, int size, int flags)
153+{
154+ struct sock *sk = sock->sk;
155+
156+ return aa_revalidate_sk(sk, "socket_recvmsg");
157+}
158+
159+static int apparmor_socket_getsockname(struct socket *sock)
160+{
161+ struct sock *sk = sock->sk;
162+
163+ return aa_revalidate_sk(sk, "socket_getsockname");
164+}
165+
166+static int apparmor_socket_getpeername(struct socket *sock)
167+{
168+ struct sock *sk = sock->sk;
169+
170+ return aa_revalidate_sk(sk, "socket_getpeername");
171+}
172+
173+static int apparmor_socket_getsockopt(struct socket *sock, int level,
174+ int optname)
175+{
176+ struct sock *sk = sock->sk;
177+
178+ return aa_revalidate_sk(sk, "socket_getsockopt");
179+}
180+
181+static int apparmor_socket_setsockopt(struct socket *sock, int level,
182+ int optname)
183+{
184+ struct sock *sk = sock->sk;
185+
186+ return aa_revalidate_sk(sk, "socket_setsockopt");
187+}
188+
189+static int apparmor_socket_shutdown(struct socket *sock, int how)
190+{
191+ struct sock *sk = sock->sk;
192+
193+ return aa_revalidate_sk(sk, "socket_shutdown");
194+}
195+
196 static int apparmor_getprocattr(struct task_struct *task, char *name,
197 char **value)
198 {
199@@ -780,9 +892,6 @@ struct security_operations apparmor_ops
200 .capable = apparmor_capable,
201 .syslog = cap_syslog,
202
203- .netlink_send = cap_netlink_send,
204- .netlink_recv = cap_netlink_recv,
205-
206 .bprm_apply_creds = cap_bprm_apply_creds,
207 .bprm_set_security = apparmor_bprm_set_security,
208 .bprm_secureexec = apparmor_bprm_secureexec,
209@@ -820,6 +929,20 @@ struct security_operations apparmor_ops
210
211 .getprocattr = apparmor_getprocattr,
212 .setprocattr = apparmor_setprocattr,
213+
214+ .socket_create = apparmor_socket_create,
215+ .socket_post_create = apparmor_socket_post_create,
216+ .socket_bind = apparmor_socket_bind,
217+ .socket_connect = apparmor_socket_connect,
218+ .socket_listen = apparmor_socket_listen,
219+ .socket_accept = apparmor_socket_accept,
220+ .socket_sendmsg = apparmor_socket_sendmsg,
221+ .socket_recvmsg = apparmor_socket_recvmsg,
222+ .socket_getsockname = apparmor_socket_getsockname,
223+ .socket_getpeername = apparmor_socket_getpeername,
224+ .socket_getsockopt = apparmor_socket_getsockopt,
225+ .socket_setsockopt = apparmor_socket_setsockopt,
226+ .socket_shutdown = apparmor_socket_shutdown,
227 };
228
229 void info_message(const char *str)
230--- a/security/apparmor/main.c
231+++ b/security/apparmor/main.c
232@@ -14,6 +14,9 @@
233 #include <linux/audit.h>
234 #include <linux/mount.h>
235 #include <linux/ptrace.h>
236+#include <linux/socket.h>
237+#include <linux/net.h>
238+#include <net/sock.h>
239
240 #include "apparmor.h"
241
242@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
243 audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
244 }
245
246+static const char *address_families[] = {
247+#include "af_names.h"
248+};
249+
250+static const char *sock_types[] = {
251+ "unknown(0)",
252+ "stream",
253+ "dgram",
254+ "raw",
255+ "rdm",
256+ "seqpacket",
257+ "dccp",
258+ "unknown(7)",
259+ "unknown(8)",
260+ "unknown(9)",
261+ "packet",
262+};
263+
264 /**
265 * aa_audit - Log an audit event to the audit subsystem
266 * @profile: profile to check against
267@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
268 audit_log_untrustedstring(ab, sa->name2);
269 }
270
271- audit_log_format(ab, " pid=%d", current->pid);
272+ if (sa->family || sa->type) {
273+ if (address_families[sa->family])
274+ audit_log_format(ab, " family=\"%s\"",
275+ address_families[sa->family]);
276+ else
277+ audit_log_format(ab, " family=\"unknown(%d)\"",
278+ sa->family);
279+
280+ if (sock_types[sa->type])
281+ audit_log_format(ab, " sock_type=\"%s\"",
282+ sock_types[sa->type]);
283+ else
284+ audit_log_format(ab, " sock_type=\"unknown(%d)\"",
285+ sa->type);
286+
287+ audit_log_format(ab, " protocol=%d", sa->protocol);
288+ }
289+
290+ audit_log_format(ab, " pid=%d", current->pid);
291
292 if (profile) {
293 audit_log_format(ab, " profile=");
294@@ -767,6 +806,72 @@ int aa_link(struct aa_profile *profile,
295
296 return error;
297 }
298+
299+int aa_net_perm(struct aa_profile *profile, char *operation,
300+ int family, int type, int protocol)
301+{
302+ struct aa_audit sa;
303+ int error = 0;
304+ u16 family_mask, audit_mask, quiet_mask;
305+
306+ if ((family < 0) || (family >= AF_MAX))
307+ return -EINVAL;
308+
309+ if ((type < 0) || (type >= SOCK_MAX))
310+ return -EINVAL;
311+
312+ /* unix domain and netlink sockets are handled by ipc */
313+ if (family == AF_UNIX || family == AF_NETLINK)
314+ return 0;
315+
316+ family_mask = profile->network_families[family];
317+ audit_mask = profile->audit_network[family];
318+ quiet_mask = profile->quiet_network[family];
319+
320+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
321+
322+ memset(&sa, 0, sizeof(sa));
323+ sa.operation = operation;
324+ sa.gfp_mask = GFP_KERNEL;
325+ sa.family = family;
326+ sa.type = type;
327+ sa.protocol = protocol;
328+ sa.error_code = error;
329+
330+ if (likely(!error)) {
331+ if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
332+ return 0;
333+ } else if (!((1 << type) & ~quiet_mask)) {
334+ return error;
335+ }
336+
337+ error = aa_audit(profile, &sa);
338+
339+ return error;
340+}
341+
342+int aa_revalidate_sk(struct sock *sk, char *operation)
343+{
344+ struct aa_profile *profile;
345+ int error = 0;
346+
347+ /* this is some debugging code to flush out the network hooks that
348+ that are called in interrupt context */
349+ if (in_interrupt()) {
350+ printk("AppArmor Debug: Hook being called from interrupt context\n");
351+ dump_stack();
352+ return 0;
353+ }
354+
355+ profile = aa_get_profile(current);
356+ if (profile)
357+ error = aa_net_perm(profile, operation,
358+ sk->sk_family, sk->sk_type,
359+ sk->sk_protocol);
360+ aa_put_profile(profile);
361+
362+ return error;
363+}
364
365 /*******************************
366 * Global task related functions
367--- a/security/apparmor/module_interface.c
368+++ b/security/apparmor/module_interface.c
369@@ -321,8 +321,8 @@ static struct aa_profile *aa_unpack_prof
370 struct aa_audit *sa)
371 {
372 struct aa_profile *profile = NULL;
373-
374- int error = -EPROTO;
375+ size_t size = 0;
376+ int i, error = -EPROTO;
377
378 profile = alloc_aa_profile();
379 if (!profile)
380@@ -355,6 +355,28 @@ static struct aa_profile *aa_unpack_prof
381 if (!aa_is_u32(e, &(profile->set_caps), NULL))
382 goto fail;
383
384+ size = aa_is_array(e, "net_allowed_af");
385+ if (size) {
386+ if (size > AF_MAX)
387+ goto fail;
388+
389+ for (i = 0; i < size; i++) {
390+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
391+ goto fail;
392+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
393+ goto fail;
394+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
395+ goto fail;
396+ }
397+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
398+ goto fail;
399+ /* allow unix domain and netlink sockets they are handled
400+ * by IPC
401+ */
402+ }
403+ profile->network_families[AF_UNIX] = 0xffff;
404+ profile->network_families[AF_NETLINK] = 0xffff;
405+
406 /* get file rules */
407 profile->file_rules = aa_unpack_dfa(e);
408 if (IS_ERR(profile->file_rules)) {