]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
- reorder so without grsecurity works
[packages/kernel.git] / kernel-apparmor.patch
1 From 6ab924a333c81d552eb92900509113bdf2fccb2e 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 1/3] AppArmor: compatibility patch for v5 network controll
5
6 Add compatibility for v5 network rules.
7
8 Signed-off-by: John Johansen <john.johansen@canonical.com>
9 ---
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(-)
19  create mode 100644 security/apparmor/include/net.h
20  create mode 100644 security/apparmor/net.c
21
22 diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
23 index 112a550..d5f3dd7 100644
24 --- a/include/linux/lsm_audit.h
25 +++ b/include/linux/lsm_audit.h
26 @@ -123,6 +123,10 @@ struct common_audit_data {
27                                         u32 denied;
28                                         uid_t ouid;
29                                 } fs;
30 +                               struct {
31 +                                       int type, protocol;
32 +                                       struct sock *sk;
33 +                               } net;
34                         };
35                 } apparmor_audit_data;
36  #endif
37 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
38 index f204869..a9a1db0 100644
39 --- a/security/apparmor/Makefile
40 +++ b/security/apparmor/Makefile
41 @@ -4,17 +4,21 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
42  
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
47  
48  clean-files: capability_names.h af_names.h
49  
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 "};" >> $@
52  
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 +
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
60 +$(obj)/net.o : $(obj)/af_names.h
61  $(obj)/resource.o : $(obj)/rlim_names.h
62  $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
63         $(call cmd,make-caps)
64 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
65 new file mode 100644
66 index 0000000..3c7d599
67 --- /dev/null
68 +++ b/security/apparmor/include/net.h
69 @@ -0,0 +1,40 @@
70 +/*
71 + * AppArmor security module
72 + *
73 + * This file contains AppArmor network mediation definitions.
74 + *
75 + * Copyright (C) 1998-2008 Novell/SUSE
76 + * Copyright 2009-2010 Canonical Ltd.
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 +
84 +#ifndef __AA_NET_H
85 +#define __AA_NET_H
86 +
87 +#include <net/sock.h>
88 +
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 +};
99 +
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);
103 +
104 +static inline void aa_free_net_rules(struct aa_net *new)
105 +{
106 +       /* NOP */
107 +}
108 +
109 +#endif /* __AA_NET_H */
110 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
111 index 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  
138 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
139 index 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"
150 @@ -607,6 +608,103 @@ static int apparmor_setprocattr(struct t
151         return error;
152  }
153  
154 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
155 +{
156 +       struct aa_profile *profile;
157 +       int error = 0;
158 +
159 +       if (kern)
160 +               return 0;
161 +
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 +}
168 +
169 +static int apparmor_socket_bind(struct socket *sock,
170 +                               struct sockaddr *address, int addrlen)
171 +{
172 +       struct sock *sk = sock->sk;
173 +
174 +       return aa_revalidate_sk(OP_BIND, sk);
175 +}
176 +
177 +static int apparmor_socket_connect(struct socket *sock,
178 +                                  struct sockaddr *address, int addrlen)
179 +{
180 +       struct sock *sk = sock->sk;
181 +
182 +       return aa_revalidate_sk(OP_CONNECT, sk);
183 +}
184 +
185 +static int apparmor_socket_listen(struct socket *sock, int backlog)
186 +{
187 +       struct sock *sk = sock->sk;
188 +
189 +       return aa_revalidate_sk(OP_LISTEN, sk);
190 +}
191 +
192 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
193 +{
194 +       struct sock *sk = sock->sk;
195 +
196 +       return aa_revalidate_sk(OP_ACCEPT, sk);
197 +}
198 +
199 +static int apparmor_socket_sendmsg(struct socket *sock,
200 +                                  struct msghdr *msg, int size)
201 +{
202 +       struct sock *sk = sock->sk;
203 +
204 +       return aa_revalidate_sk(OP_SENDMSG, sk);
205 +}
206 +
207 +static int apparmor_socket_recvmsg(struct socket *sock,
208 +                                  struct msghdr *msg, int size, int flags)
209 +{
210 +       struct sock *sk = sock->sk;
211 +
212 +       return aa_revalidate_sk(OP_RECVMSG, sk);
213 +}
214 +
215 +static int apparmor_socket_getsockname(struct socket *sock)
216 +{
217 +       struct sock *sk = sock->sk;
218 +
219 +       return aa_revalidate_sk(OP_GETSOCKNAME, sk);
220 +}
221 +
222 +static int apparmor_socket_getpeername(struct socket *sock)
223 +{
224 +       struct sock *sk = sock->sk;
225 +
226 +       return aa_revalidate_sk(OP_GETPEERNAME, sk);
227 +}
228 +
229 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
230 +                                     int optname)
231 +{
232 +       struct sock *sk = sock->sk;
233 +
234 +       return aa_revalidate_sk(OP_GETSOCKOPT, sk);
235 +}
236 +
237 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
238 +                                     int optname)
239 +{
240 +       struct sock *sk = sock->sk;
241 +
242 +       return aa_revalidate_sk(OP_SETSOCKOPT, sk);
243 +}
244 +
245 +static int apparmor_socket_shutdown(struct socket *sock, int how)
246 +{
247 +       struct sock *sk = sock->sk;
248 +
249 +       return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
250 +}
251  static int apparmor_task_setrlimit(struct task_struct *task,
252                 unsigned int resource, struct rlimit *new_rlim)
253  {
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,
274 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
275 new file mode 100644
276 index 0000000..1765901
277 --- /dev/null
278 +++ b/security/apparmor/net.c
279 @@ -0,0 +1,170 @@
280 +/*
281 + * AppArmor security module
282 + *
283 + * This file contains AppArmor network mediation
284 + *
285 + * Copyright (C) 1998-2008 Novell/SUSE
286 + * Copyright 2009-2010 Canonical Ltd.
287 + *
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.
292 + */
293 +
294 +#include "include/apparmor.h"
295 +#include "include/audit.h"
296 +#include "include/context.h"
297 +#include "include/net.h"
298 +#include "include/policy.h"
299 +
300 +#include "af_names.h"
301 +
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",
314 +};
315 +
316 +/* audit callback for net specific fields */
317 +static void audit_cb(struct audit_buffer *ab, void *va)
318 +{
319 +       struct common_audit_data *sa = va;
320 +
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 +       }
327 +
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 +       }
334 +
335 +       audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
336 +}
337 +
338 +/**
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
347 + *
348 + * Returns: %0 or sa->error else other errorcode on failure
349 + */
350 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
351 +                    int protocol, struct sock *sk, int error)
352 +{
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);
359 +       }
360 +       /* todo fill in socket addr info */
361 +
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;
368 +
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)))
373 +                       return 0;
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;
379 +
380 +               if (denied & kill_mask)
381 +                       audit_type = AUDIT_APPARMOR_KILL;
382 +
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;
387 +       }
388 +
389 +       return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
390 +}
391 +
392 +/**
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
399 + *
400 + * Returns: %0 else error if permission denied
401 + */
402 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
403 +               int protocol, struct sock *sk)
404 +{
405 +       u16 family_mask;
406 +       int error;
407 +
408 +       if ((family < 0) || (family >= AF_MAX))
409 +               return -EINVAL;
410 +
411 +       if ((type < 0) || (type >= SOCK_MAX))
412 +               return -EINVAL;
413 +
414 +       /* unix domain and netlink sockets are handled by ipc */
415 +       if (family == AF_UNIX || family == AF_NETLINK)
416 +               return 0;
417 +
418 +       family_mask = profile->net.allow[family];
419 +
420 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
421 +
422 +       return audit_net(profile, op, family, type, protocol, sk, error);
423 +}
424 +
425 +/**
426 + * aa_revalidate_sk - Revalidate access to a sock
427 + * @op: operation being checked
428 + * @sk: sock being revalidated  (NOT NULL)
429 + *
430 + * Returns: %0 else error if permission denied
431 + */
432 +int aa_revalidate_sk(int op, struct sock *sk)
433 +{
434 +       struct aa_profile *profile;
435 +       int error = 0;
436 +
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;
442 +
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);
447 +
448 +       return error;
449 +}
450 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
451 index 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);
462 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
463 index 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)
471 +{
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;
479 +       }
480 +       return 0;
481 +}
482 +
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;
491 +       size_t size = 0;
492 +       int i, error = -EPROTO;
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  
500 +       size = unpack_array(e, "net_allowed_af");
501 +       if (size) {
502 +
503 +               for (i = 0; i < size; i++) {
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 +                       }
515 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
516 +                               goto fail;
517 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
518 +                               goto fail;
519 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
520 +                               goto fail;
521 +               }
522 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
523 +                       goto fail;
524 +               /*
525 +                * allow unix domain and netlink sockets they are handled
526 +                * by IPC
527 +                */
528 +       }
529 +       profile->net.allow[AF_UNIX] = 0xffff;
530 +       profile->net.allow[AF_NETLINK] = 0xffff;
531 +
532         /* get file rules */
533         profile->file.dfa = unpack_dfa(e);
534         if (IS_ERR(profile->file.dfa)) {
535 -- 
536 1.7.1
537
538 From 5f034900aa447abea213c434d6d262d28fd168e7 Mon Sep 17 00:00:00 2001
539 From: John Johansen <john.johansen@canonical.com>
540 Date: Thu, 22 Jul 2010 02:32:02 -0700
541 Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
542
543 Signed-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
553 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
554 index 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.
561 +
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.
570 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
571 index 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
579 +
580  clean-files: capability_names.h af_names.h
581  
582  quiet_cmd_make-caps = GEN     $@
583 diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
584 new file mode 100644
585 index 0000000..dc8c744
586 --- /dev/null
587 +++ b/security/apparmor/apparmorfs-24.c
588 @@ -0,0 +1,287 @@
589 +/*
590 + * AppArmor security module
591 + *
592 + * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
593 + *
594 + * Copyright (C) 1998-2008 Novell/SUSE
595 + * Copyright 2009-2010 Canonical Ltd.
596 + *
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.
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).
606 + */
607 +
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 +
615 +#include "include/apparmor.h"
616 +#include "include/audit.h"
617 +#include "include/context.h"
618 +#include "include/policy.h"
619 +
620 +
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 +
651 +/**
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)
655 + *
656 + * Find the next namespace from @ns under @root and handle all locking needed
657 + * while switching current namespace.
658 + *
659 + * Returns: next namespace or NULL if at last namespace under @root
660 + * NOTE: will not unlock root->lock
661 + */
662 +static struct aa_namespace *__next_namespace(struct aa_namespace *root,
663 +                                            struct aa_namespace *ns)
664 +{
665 +       struct aa_namespace *parent;
666 +
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 +       }
674 +
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;
687 +       }
688 +
689 +       return NULL;
690 +}
691 +
692 +/**
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)
696 + *
697 + * Returns: unrefcounted profile or NULL if no profile
698 + */
699 +static struct aa_profile *__first_profile(struct aa_namespace *root,
700 +                                         struct aa_namespace *ns)
701 +{
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);
706 +       }
707 +       return NULL;
708 +}
709 +
710 +/**
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
715 + *
716 + * Returns: next profile or NULL if done
717 + * Requires: profile->ns.lock to be held
718 + */
719 +static struct aa_profile *__next_profile(struct aa_profile *p)
720 +{
721 +       struct aa_profile *parent;
722 +       struct aa_namespace *ns = p->ns;
723 +
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);
728 +
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;
737 +       }
738 +
739 +       /* is next another profile in the namespace */
740 +       list_for_each_entry_continue(p, &ns->base.profiles, base.list)
741 +               return p;
742 +
743 +       return NULL;
744 +}
745 +
746 +/**
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)
750 + *
751 + * Returns: next profile or NULL if there isn't one
752 + */
753 +static struct aa_profile *next_profile(struct aa_namespace *root,
754 +                                      struct aa_profile *profile)
755 +{
756 +       struct aa_profile *next = __next_profile(profile);
757 +       if (next)
758 +               return next;
759 +
760 +       /* finished all profiles in namespace move to next namespace */
761 +       return __first_profile(root, __next_namespace(root, profile->ns));
762 +}
763 +
764 +/**
765 + * p_start - start a depth first traversal of profile tree
766 + * @f: seq_file to fill
767 + * @pos: current position
768 + *
769 + * Returns: first profile under current namespace or NULL if none found
770 + *
771 + * acquires first ns->lock
772 + */
773 +static void *p_start(struct seq_file *f, loff_t *pos)
774 +       __acquires(root->lock)
775 +{
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);
780 +
781 +
782 +       /* find the first profile */
783 +       read_lock(&root->lock);
784 +       profile = __first_profile(root, root);
785 +
786 +       /* skip to position */
787 +       for (; profile && l > 0; l--)
788 +               profile = next_profile(root, profile);
789 +
790 +       return profile;
791 +}
792 +
793 +/**
794 + * p_next - read the next profile entry
795 + * @f: seq_file to fill
796 + * @p: profile previously returned
797 + * @pos: current position
798 + *
799 + * Returns: next profile after @p or NULL if none
800 + *
801 + * may acquire/release locks in namespace tree as necessary
802 + */
803 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
804 +{
805 +       struct aa_profile *profile = p;
806 +       struct aa_namespace *root = f->private;
807 +       (*pos)++;
808 +
809 +       return next_profile(root, profile);
810 +}
811 +
812 +/**
813 + * p_stop - stop depth first traversal
814 + * @f: seq_file we are filling
815 + * @p: the last profile writen
816 + *
817 + * Release all locking done by p_start/p_next on namespace tree
818 + */
819 +static void p_stop(struct seq_file *f, void *p)
820 +       __releases(root->lock)
821 +{
822 +       struct aa_profile *profile = p;
823 +       struct aa_namespace *root = f->private, *ns;
824 +
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);
831 +}
832 +
833 +/**
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
839 + */
840 +static int seq_show_profile(struct seq_file *f, void *p)
841 +{
842 +       struct aa_profile *profile = (struct aa_profile *)p;
843 +       struct aa_namespace *root = f->private;
844 +
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");
849 +
850 +       return 0;
851 +}
852 +
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 +};
859 +
860 +static int profiles_open(struct inode *inode, struct file *file)
861 +{
862 +       return seq_open(file, &aa_fs_profiles_op);
863 +}
864 +
865 +static int profiles_release(struct inode *inode, struct file *file)
866 +{
867 +       return seq_release(inode, file);
868 +}
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 +};
876 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
877 index 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;
912 diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
913 index 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 */
927 -- 
928 1.7.1
929
This page took 0.88618 seconds and 4 git commands to generate.