]> git.proxmox.com Git - pve-kernel-3.10.0.git/blob - 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
1 From e83b058f391e96a2a640fb2e2812d50ef67e0f43 Mon Sep 17 00:00:00 2001
2 From: John Johansen <john.johansen@canonical.com>
3 Date: Mon, 4 Oct 2010 15:03:36 -0700
4 Subject: [PATCH 2/4] UBUNTU: SAUCE: AppArmor: basic networking rules
5
6 Base support for network mediation.
7
8 Signed-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
24 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
25 index 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
35 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
36 index 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)
107 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
108 index 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 { }
119 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
120 index 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
134 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
135 new file mode 100644
136 index 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 */
184 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
185 index 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
212 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
213 index 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,
349 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
350 new file mode 100644
351 index 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 +}
517 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
518 index 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);
529 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
530 index 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 --
601 1.8.3.2
602