]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
- add missing features in 2.6.36 apparmor
[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 @@ -619,6 +620,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
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 +
252  static struct security_operations apparmor_ops = {
253         .name =                         "apparmor",
254  
255 @@ -650,6 +749,19 @@ static struct security_operations apparmor_ops = {
256         .getprocattr =                  apparmor_getprocattr,
257         .setprocattr =                  apparmor_setprocattr,
258  
259 +       .socket_create =                apparmor_socket_create,
260 +       .socket_bind =                  apparmor_socket_bind,
261 +       .socket_connect =               apparmor_socket_connect,
262 +       .socket_listen =                apparmor_socket_listen,
263 +       .socket_accept =                apparmor_socket_accept,
264 +       .socket_sendmsg =               apparmor_socket_sendmsg,
265 +       .socket_recvmsg =               apparmor_socket_recvmsg,
266 +       .socket_getsockname =           apparmor_socket_getsockname,
267 +       .socket_getpeername =           apparmor_socket_getpeername,
268 +       .socket_getsockopt =            apparmor_socket_getsockopt,
269 +       .socket_setsockopt =            apparmor_socket_setsockopt,
270 +       .socket_shutdown =              apparmor_socket_shutdown,
271 +
272         .cred_alloc_blank =             apparmor_cred_alloc_blank,
273         .cred_free =                    apparmor_cred_free,
274         .cred_prepare =                 apparmor_cred_prepare,
275 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
276 new file mode 100644
277 index 0000000..1765901
278 --- /dev/null
279 +++ b/security/apparmor/net.c
280 @@ -0,0 +1,170 @@
281 +/*
282 + * AppArmor security module
283 + *
284 + * This file contains AppArmor network mediation
285 + *
286 + * Copyright (C) 1998-2008 Novell/SUSE
287 + * Copyright 2009-2010 Canonical Ltd.
288 + *
289 + * This program is free software; you can redistribute it and/or
290 + * modify it under the terms of the GNU General Public License as
291 + * published by the Free Software Foundation, version 2 of the
292 + * License.
293 + */
294 +
295 +#include "include/apparmor.h"
296 +#include "include/audit.h"
297 +#include "include/context.h"
298 +#include "include/net.h"
299 +#include "include/policy.h"
300 +
301 +#include "af_names.h"
302 +
303 +static const char *sock_type_names[] = {
304 +       "unknown(0)",
305 +       "stream",
306 +       "dgram",
307 +       "raw",
308 +       "rdm",
309 +       "seqpacket",
310 +       "dccp",
311 +       "unknown(7)",
312 +       "unknown(8)",
313 +       "unknown(9)",
314 +       "packet",
315 +};
316 +
317 +/* audit callback for net specific fields */
318 +static void audit_cb(struct audit_buffer *ab, void *va)
319 +{
320 +       struct common_audit_data *sa = va;
321 +
322 +       audit_log_format(ab, " family=");
323 +       if (address_family_names[sa->u.net.family]) {
324 +               audit_log_string(ab, address_family_names[sa->u.net.family]);
325 +       } else {
326 +               audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
327 +       }
328 +
329 +       audit_log_format(ab, " sock_type=");
330 +       if (sock_type_names[sa->aad.net.type]) {
331 +               audit_log_string(ab, sock_type_names[sa->aad.net.type]);
332 +       } else {
333 +               audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
334 +       }
335 +
336 +       audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
337 +}
338 +
339 +/**
340 + * audit_net - audit network access
341 + * @profile: profile being enforced  (NOT NULL)
342 + * @op: operation being checked
343 + * @family: network family
344 + * @type:   network type
345 + * @protocol: network protocol
346 + * @sk: socket auditing is being applied to
347 + * @error: error code for failure else 0
348 + *
349 + * Returns: %0 or sa->error else other errorcode on failure
350 + */
351 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
352 +                    int protocol, struct sock *sk, int error)
353 +{
354 +       int audit_type = AUDIT_APPARMOR_AUTO;
355 +       struct common_audit_data sa;
356 +       if (sk) {
357 +               COMMON_AUDIT_DATA_INIT(&sa, NET);
358 +       } else {
359 +               COMMON_AUDIT_DATA_INIT(&sa, NONE);
360 +       }
361 +       /* todo fill in socket addr info */
362 +
363 +       sa.aad.op = op,
364 +       sa.u.net.family = family;
365 +       sa.u.net.sk = sk;
366 +       sa.aad.net.type = type;
367 +       sa.aad.net.protocol = protocol;
368 +       sa.aad.error = error;
369 +
370 +       if (likely(!sa.aad.error)) {
371 +               u16 audit_mask = profile->net.audit[sa.u.net.family];
372 +               if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
373 +                          !(1 << sa.aad.net.type & audit_mask)))
374 +                       return 0;
375 +               audit_type = AUDIT_APPARMOR_AUDIT;
376 +       } else {
377 +               u16 quiet_mask = profile->net.quiet[sa.u.net.family];
378 +               u16 kill_mask = 0;
379 +               u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
380 +
381 +               if (denied & kill_mask)
382 +                       audit_type = AUDIT_APPARMOR_KILL;
383 +
384 +               if ((denied & quiet_mask) &&
385 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
386 +                   AUDIT_MODE(profile) != AUDIT_ALL)
387 +                       return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
388 +       }
389 +
390 +       return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
391 +}
392 +
393 +/**
394 + * aa_net_perm - very course network access check
395 + * @op: operation being checked
396 + * @profile: profile being enforced  (NOT NULL)
397 + * @family: network family
398 + * @type:   network type
399 + * @protocol: network protocol
400 + *
401 + * Returns: %0 else error if permission denied
402 + */
403 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
404 +               int protocol, struct sock *sk)
405 +{
406 +       u16 family_mask;
407 +       int error;
408 +
409 +       if ((family < 0) || (family >= AF_MAX))
410 +               return -EINVAL;
411 +
412 +       if ((type < 0) || (type >= SOCK_MAX))
413 +               return -EINVAL;
414 +
415 +       /* unix domain and netlink sockets are handled by ipc */
416 +       if (family == AF_UNIX || family == AF_NETLINK)
417 +               return 0;
418 +
419 +       family_mask = profile->net.allow[family];
420 +
421 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
422 +
423 +       return audit_net(profile, op, family, type, protocol, sk, error);
424 +}
425 +
426 +/**
427 + * aa_revalidate_sk - Revalidate access to a sock
428 + * @op: operation being checked
429 + * @sk: sock being revalidated  (NOT NULL)
430 + *
431 + * Returns: %0 else error if permission denied
432 + */
433 +int aa_revalidate_sk(int op, struct sock *sk)
434 +{
435 +       struct aa_profile *profile;
436 +       int error = 0;
437 +
438 +       /* aa_revalidate_sk should not be called from interrupt context
439 +        * don't mediate these calls as they are not task related
440 +        */
441 +       if (in_interrupt())
442 +               return 0;
443 +
444 +       profile = __aa_current_profile();
445 +       if (!unconfined(profile))
446 +               error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
447 +                                   sk->sk_protocol, sk);
448 +
449 +       return error;
450 +}
451 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
452 index 52cc865..3b5da44 100644
453 --- a/security/apparmor/policy.c
454 +++ b/security/apparmor/policy.c
455 @@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
456  
457         aa_free_file_rules(&profile->file);
458         aa_free_cap_rules(&profile->caps);
459 +       aa_free_net_rules(&profile->net);
460         aa_free_rlimit_rules(&profile->rlimits);
461  
462         aa_free_sid(profile->sid);
463 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
464 index eb3700e..c2b6225 100644
465 --- a/security/apparmor/policy_unpack.c
466 +++ b/security/apparmor/policy_unpack.c
467 @@ -190,6 +190,19 @@ fail:
468         return 0;
469  }
470  
471 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
472 +{
473 +       if (unpack_nameX(e, AA_U16, name)) {
474 +               if (!inbounds(e, sizeof(u16)))
475 +                       return 0;
476 +               if (data)
477 +                       *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
478 +               e->pos += sizeof(u16);
479 +               return 1;
480 +       }
481 +       return 0;
482 +}
483 +
484  static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
485  {
486         if (unpack_nameX(e, AA_U32, name)) {
487 @@ -468,7 +481,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
488  {
489         struct aa_profile *profile = NULL;
490         const char *name = NULL;
491 -       int error = -EPROTO;
492 +       size_t size = 0;
493 +       int i, error = -EPROTO;
494         kernel_cap_t tmpcap;
495         u32 tmp;
496  
497 @@ -559,6 +573,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
498         if (!unpack_rlimits(e, profile))
499                 goto fail;
500  
501 +       size = unpack_array(e, "net_allowed_af");
502 +       if (size) {
503 +
504 +               for (i = 0; i < size; i++) {
505 +                       /* discard extraneous rules that this kernel will
506 +                        * never request
507 +                        */
508 +                       if (i > AF_MAX) {
509 +                               u16 tmp;
510 +                               if (!unpack_u16(e, &tmp, NULL) ||
511 +                                   !unpack_u16(e, &tmp, NULL) ||
512 +                                   !unpack_u16(e, &tmp, NULL))
513 +                                       goto fail;
514 +                               continue;
515 +                       }
516 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
517 +                               goto fail;
518 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
519 +                               goto fail;
520 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
521 +                               goto fail;
522 +               }
523 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
524 +                       goto fail;
525 +               /*
526 +                * allow unix domain and netlink sockets they are handled
527 +                * by IPC
528 +                */
529 +       }
530 +       profile->net.allow[AF_UNIX] = 0xffff;
531 +       profile->net.allow[AF_NETLINK] = 0xffff;
532 +
533         /* get file rules */
534         profile->file.dfa = unpack_dfa(e);
535         if (IS_ERR(profile->file.dfa)) {
536 -- 
537 1.7.1
538
539 From 5f034900aa447abea213c434d6d262d28fd168e7 Mon Sep 17 00:00:00 2001
540 From: John Johansen <john.johansen@canonical.com>
541 Date: Thu, 22 Jul 2010 02:32:02 -0700
542 Subject: [PATCH 2/3] AppArmor: compatibility patch for v5 interface
543
544 Signed-off-by: John Johansen <john.johansen@canonical.com>
545 ---
546  security/apparmor/Kconfig              |    9 +
547  security/apparmor/Makefile             |    2 +
548  security/apparmor/apparmorfs-24.c      |  287 ++++++++++++++++++++++++++++++++
549  security/apparmor/apparmorfs.c         |   18 ++-
550  security/apparmor/include/apparmorfs.h |    6 +
551  5 files changed, 320 insertions(+), 2 deletions(-)
552  create mode 100644 security/apparmor/apparmorfs-24.c
553
554 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
555 index 9b9013b..51ebf96 100644
556 --- a/security/apparmor/Kconfig
557 +++ b/security/apparmor/Kconfig
558 @@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
559           boot.
560  
561           If you are unsure how to answer this question, answer 1.
562 +
563 +config SECURITY_APPARMOR_COMPAT_24
564 +       bool "Enable AppArmor 2.4 compatability"
565 +       depends on SECURITY_APPARMOR
566 +       default y
567 +       help
568 +         This option enables compatability with AppArmor 2.4.  It is
569 +          recommended if compatability with older versions of AppArmor
570 +          is desired.
571 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
572 index a9a1db0..e5e8968 100644
573 --- a/security/apparmor/Makefile
574 +++ b/security/apparmor/Makefile
575 @@ -6,6 +6,8 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
576                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
577                resource.o sid.o file.o net.o
578  
579 +apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
580 +
581  clean-files: capability_names.h af_names.h
582  
583  quiet_cmd_make-caps = GEN     $@
584 diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
585 new file mode 100644
586 index 0000000..dc8c744
587 --- /dev/null
588 +++ b/security/apparmor/apparmorfs-24.c
589 @@ -0,0 +1,287 @@
590 +/*
591 + * AppArmor security module
592 + *
593 + * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
594 + *
595 + * Copyright (C) 1998-2008 Novell/SUSE
596 + * Copyright 2009-2010 Canonical Ltd.
597 + *
598 + * This program is free software; you can redistribute it and/or
599 + * modify it under the terms of the GNU General Public License as
600 + * published by the Free Software Foundation, version 2 of the
601 + * License.
602 + *
603 + *
604 + * This file contain functions providing an interface for <= AppArmor 2.4
605 + * compatibility.  It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
606 + * being set (see Makefile).
607 + */
608 +
609 +#include <linux/security.h>
610 +#include <linux/vmalloc.h>
611 +#include <linux/module.h>
612 +#include <linux/seq_file.h>
613 +#include <linux/uaccess.h>
614 +#include <linux/namei.h>
615 +
616 +#include "include/apparmor.h"
617 +#include "include/audit.h"
618 +#include "include/context.h"
619 +#include "include/policy.h"
620 +
621 +
622 +/* apparmor/matching */
623 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
624 +                               size_t size, loff_t *ppos)
625 +{
626 +       const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
627 +           "user::other";
628 +
629 +       return simple_read_from_buffer(buf, size, ppos, matching,
630 +                                      sizeof(matching) - 1);
631 +}
632 +
633 +const struct file_operations aa_fs_matching_fops = {
634 +       .read = aa_matching_read,
635 +};
636 +
637 +/* apparmor/features */
638 +static ssize_t aa_features_read(struct file *file, char __user *buf,
639 +                               size_t size, loff_t *ppos)
640 +{
641 +       const char features[] = "file=3.1 capability=2.0 network=1.0 "
642 +           "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
643 +
644 +       return simple_read_from_buffer(buf, size, ppos, features,
645 +                                      sizeof(features) - 1);
646 +}
647 +
648 +const struct file_operations aa_fs_features_fops = {
649 +       .read = aa_features_read,
650 +};
651 +
652 +/**
653 + * __next_namespace - find the next namespace to list
654 + * @root: root namespace to stop search at (NOT NULL)
655 + * @ns: current ns position (NOT NULL)
656 + *
657 + * Find the next namespace from @ns under @root and handle all locking needed
658 + * while switching current namespace.
659 + *
660 + * Returns: next namespace or NULL if at last namespace under @root
661 + * NOTE: will not unlock root->lock
662 + */
663 +static struct aa_namespace *__next_namespace(struct aa_namespace *root,
664 +                                            struct aa_namespace *ns)
665 +{
666 +       struct aa_namespace *parent;
667 +
668 +       /* is next namespace a child */
669 +       if (!list_empty(&ns->sub_ns)) {
670 +               struct aa_namespace *next;
671 +               next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
672 +               read_lock(&next->lock);
673 +               return next;
674 +       }
675 +
676 +       /* check if the next ns is a sibling, parent, gp, .. */
677 +       parent = ns->parent;
678 +       while (parent) {
679 +               read_unlock(&ns->lock);
680 +               list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
681 +                       read_lock(&ns->lock);
682 +                       return ns;
683 +               }
684 +               if (parent == root)
685 +                       return NULL;
686 +               ns = parent;
687 +               parent = parent->parent;
688 +       }
689 +
690 +       return NULL;
691 +}
692 +
693 +/**
694 + * __first_profile - find the first profile in a namespace
695 + * @root: namespace that is root of profiles being displayed (NOT NULL)
696 + * @ns: namespace to start in   (NOT NULL)
697 + *
698 + * Returns: unrefcounted profile or NULL if no profile
699 + */
700 +static struct aa_profile *__first_profile(struct aa_namespace *root,
701 +                                         struct aa_namespace *ns)
702 +{
703 +       for ( ; ns; ns = __next_namespace(root, ns)) {
704 +               if (!list_empty(&ns->base.profiles))
705 +                       return list_first_entry(&ns->base.profiles,
706 +                                               struct aa_profile, base.list);
707 +       }
708 +       return NULL;
709 +}
710 +
711 +/**
712 + * __next_profile - step to the next profile in a profile tree
713 + * @profile: current profile in tree (NOT NULL)
714 + *
715 + * Perform a depth first taversal on the profile tree in a namespace
716 + *
717 + * Returns: next profile or NULL if done
718 + * Requires: profile->ns.lock to be held
719 + */
720 +static struct aa_profile *__next_profile(struct aa_profile *p)
721 +{
722 +       struct aa_profile *parent;
723 +       struct aa_namespace *ns = p->ns;
724 +
725 +       /* is next profile a child */
726 +       if (!list_empty(&p->base.profiles))
727 +               return list_first_entry(&p->base.profiles, typeof(*p),
728 +                                       base.list);
729 +
730 +       /* is next profile a sibling, parent sibling, gp, subling, .. */
731 +       parent = p->parent;
732 +       while (parent) {
733 +               list_for_each_entry_continue(p, &parent->base.profiles,
734 +                                            base.list)
735 +                               return p;
736 +               p = parent;
737 +               parent = parent->parent;
738 +       }
739 +
740 +       /* is next another profile in the namespace */
741 +       list_for_each_entry_continue(p, &ns->base.profiles, base.list)
742 +               return p;
743 +
744 +       return NULL;
745 +}
746 +
747 +/**
748 + * next_profile - step to the next profile in where ever it may be
749 + * @root: root namespace  (NOT NULL)
750 + * @profile: current profile  (NOT NULL)
751 + *
752 + * Returns: next profile or NULL if there isn't one
753 + */
754 +static struct aa_profile *next_profile(struct aa_namespace *root,
755 +                                      struct aa_profile *profile)
756 +{
757 +       struct aa_profile *next = __next_profile(profile);
758 +       if (next)
759 +               return next;
760 +
761 +       /* finished all profiles in namespace move to next namespace */
762 +       return __first_profile(root, __next_namespace(root, profile->ns));
763 +}
764 +
765 +/**
766 + * p_start - start a depth first traversal of profile tree
767 + * @f: seq_file to fill
768 + * @pos: current position
769 + *
770 + * Returns: first profile under current namespace or NULL if none found
771 + *
772 + * acquires first ns->lock
773 + */
774 +static void *p_start(struct seq_file *f, loff_t *pos)
775 +       __acquires(root->lock)
776 +{
777 +       struct aa_profile *profile = NULL;
778 +       struct aa_namespace *root = aa_current_profile()->ns;
779 +       loff_t l = *pos;
780 +       f->private = aa_get_namespace(root);
781 +
782 +
783 +       /* find the first profile */
784 +       read_lock(&root->lock);
785 +       profile = __first_profile(root, root);
786 +
787 +       /* skip to position */
788 +       for (; profile && l > 0; l--)
789 +               profile = next_profile(root, profile);
790 +
791 +       return profile;
792 +}
793 +
794 +/**
795 + * p_next - read the next profile entry
796 + * @f: seq_file to fill
797 + * @p: profile previously returned
798 + * @pos: current position
799 + *
800 + * Returns: next profile after @p or NULL if none
801 + *
802 + * may acquire/release locks in namespace tree as necessary
803 + */
804 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
805 +{
806 +       struct aa_profile *profile = p;
807 +       struct aa_namespace *root = f->private;
808 +       (*pos)++;
809 +
810 +       return next_profile(root, profile);
811 +}
812 +
813 +/**
814 + * p_stop - stop depth first traversal
815 + * @f: seq_file we are filling
816 + * @p: the last profile writen
817 + *
818 + * Release all locking done by p_start/p_next on namespace tree
819 + */
820 +static void p_stop(struct seq_file *f, void *p)
821 +       __releases(root->lock)
822 +{
823 +       struct aa_profile *profile = p;
824 +       struct aa_namespace *root = f->private, *ns;
825 +
826 +       if (profile) {
827 +               for (ns = profile->ns; ns && ns != root; ns = ns->parent)
828 +                       read_unlock(&ns->lock);
829 +       }
830 +       read_unlock(&root->lock);
831 +       aa_put_namespace(root);
832 +}
833 +
834 +/**
835 + * seq_show_profile - show a profile entry
836 + * @f: seq_file to file
837 + * @p: current position (profile)    (NOT NULL)
838 + *
839 + * Returns: error on failure
840 + */
841 +static int seq_show_profile(struct seq_file *f, void *p)
842 +{
843 +       struct aa_profile *profile = (struct aa_profile *)p;
844 +       struct aa_namespace *root = f->private;
845 +
846 +       if (profile->ns != root)
847 +               seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
848 +       seq_printf(f, "%s (%s)\n", profile->base.hname,
849 +                  COMPLAIN_MODE(profile) ? "complain" : "enforce");
850 +
851 +       return 0;
852 +}
853 +
854 +static const struct seq_operations aa_fs_profiles_op = {
855 +       .start = p_start,
856 +       .next = p_next,
857 +       .stop = p_stop,
858 +       .show = seq_show_profile,
859 +};
860 +
861 +static int profiles_open(struct inode *inode, struct file *file)
862 +{
863 +       return seq_open(file, &aa_fs_profiles_op);
864 +}
865 +
866 +static int profiles_release(struct inode *inode, struct file *file)
867 +{
868 +       return seq_release(inode, file);
869 +}
870 +
871 +const struct file_operations aa_fs_profiles_fops = {
872 +       .open = profiles_open,
873 +       .read = seq_read,
874 +       .llseek = seq_lseek,
875 +       .release = profiles_release,
876 +};
877 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
878 index 7320331..0e27449 100644
879 --- a/security/apparmor/apparmorfs.c
880 +++ b/security/apparmor/apparmorfs.c
881 @@ -182,7 +182,11 @@ void __init aa_destroy_aafs(void)
882                 aafs_remove(".remove");
883                 aafs_remove(".replace");
884                 aafs_remove(".load");
885 -
886 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
887 +               aafs_remove("profiles");
888 +               aafs_remove("matching");
889 +               aafs_remove("features");
890 +#endif
891                 securityfs_remove(aa_fs_dentry);
892                 aa_fs_dentry = NULL;
893         }
894 @@ -213,7 +217,17 @@ int __init aa_create_aafs(void)
895                 aa_fs_dentry = NULL;
896                 goto error;
897         }
898 -
899 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
900 +       error = aafs_create("matching", 0444, &aa_fs_matching_fops);
901 +       if (error)
902 +               goto error;
903 +       error = aafs_create("features", 0444, &aa_fs_features_fops);
904 +       if (error)
905 +               goto error;
906 +#endif
907 +       error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
908 +       if (error)
909 +               goto error;
910         error = aafs_create(".load", 0640, &aa_fs_profile_load);
911         if (error)
912                 goto error;
913 diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
914 index cb1e93a..14f955c 100644
915 --- a/security/apparmor/include/apparmorfs.h
916 +++ b/security/apparmor/include/apparmorfs.h
917 @@ -17,4 +17,10 @@
918  
919  extern void __init aa_destroy_aafs(void);
920  
921 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
922 +extern const struct file_operations aa_fs_matching_fops;
923 +extern const struct file_operations aa_fs_features_fops;
924 +extern const struct file_operations aa_fs_profiles_fops;
925 +#endif
926 +
927  #endif /* __AA_APPARMORFS_H */
928 -- 
929 1.7.1
930
This page took 0.167496 seconds and 4 git commands to generate.