]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.apparmor/apparmor-network.diff
Changed checkfs to auto reboot after correctable fsck fixes.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.apparmor / apparmor-network.diff
1 From: John Johansen <jjohansen@suse.de>
2 Subject: AppArmor: Simplified network controls for AppArmor
3
4 Simple network control determining which network families a confined
5 application has access to.
6
7 Signed-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)) {