]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
add vserver patch info to package description
[packages/kernel.git] / kernel-apparmor.patch
1 From 05bf1eb7276886a3eda0588a8e012b558b693e96 Mon Sep 17 00:00:00 2001
2 From: John Johansen <john.johansen@canonical.com>
3 Date: Thu, 22 Jul 2010 02:32:02 -0700
4 Subject: [PATCH] UBUNTU: SAUCE: AppArmor: Add profile introspection file to
5  interface
6
7 Add the dynamic profiles file to the interace, to allow load policy
8 introspection.
9
10 Signed-off-by: John Johansen <john.johansen@canonical.com>
11 Acked-by: Kees Cook <kees@ubuntu.com>
12 ---
13  security/apparmor/Kconfig      |    9 ++
14  security/apparmor/apparmorfs.c |  231 ++++++++++++++++++++++++++++++++++++++++
15  2 files changed, 240 insertions(+), 0 deletions(-)
16
17 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
18 index 9b9013b..51ebf96 100644
19 --- a/security/apparmor/Kconfig
20 +++ b/security/apparmor/Kconfig
21 @@ -29,3 +29,12 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
22           boot.
23  
24           If you are unsure how to answer this question, answer 1.
25 +
26 +config SECURITY_APPARMOR_COMPAT_24
27 +       bool "Enable AppArmor 2.4 compatability"
28 +       depends on SECURITY_APPARMOR
29 +       default y
30 +       help
31 +         This option enables compatability with AppArmor 2.4.  It is
32 +          recommended if compatability with older versions of AppArmor
33 +          is desired.
34 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
35 index 16c15ec..42b7c9f 100644
36 --- a/security/apparmor/apparmorfs.c
37 +++ b/security/apparmor/apparmorfs.c
38 @@ -182,6 +182,234 @@ const struct file_operations aa_fs_seq_file_ops = {
39         .release        = single_release,
40  };
41  
42 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
43 +/**
44 + * __next_namespace - find the next namespace to list
45 + * @root: root namespace to stop search at (NOT NULL)
46 + * @ns: current ns position (NOT NULL)
47 + *
48 + * Find the next namespace from @ns under @root and handle all locking needed
49 + * while switching current namespace.
50 + *
51 + * Returns: next namespace or NULL if at last namespace under @root
52 + * NOTE: will not unlock root->lock
53 + */
54 +static struct aa_namespace *__next_namespace(struct aa_namespace *root,
55 +                                            struct aa_namespace *ns)
56 +{
57 +       struct aa_namespace *parent;
58 +
59 +       /* is next namespace a child */
60 +       if (!list_empty(&ns->sub_ns)) {
61 +               struct aa_namespace *next;
62 +               next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
63 +               read_lock(&next->lock);
64 +               return next;
65 +       }
66 +
67 +       /* check if the next ns is a sibling, parent, gp, .. */
68 +       parent = ns->parent;
69 +       while (parent) {
70 +               read_unlock(&ns->lock);
71 +               list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
72 +                       read_lock(&ns->lock);
73 +                       return ns;
74 +               }
75 +               if (parent == root)
76 +                       return NULL;
77 +               ns = parent;
78 +               parent = parent->parent;
79 +       }
80 +
81 +       return NULL;
82 +}
83 +
84 +/**
85 + * __first_profile - find the first profile in a namespace
86 + * @root: namespace that is root of profiles being displayed (NOT NULL)
87 + * @ns: namespace to start in   (NOT NULL)
88 + *
89 + * Returns: unrefcounted profile or NULL if no profile
90 + */
91 +static struct aa_profile *__first_profile(struct aa_namespace *root,
92 +                                         struct aa_namespace *ns)
93 +{
94 +       for ( ; ns; ns = __next_namespace(root, ns)) {
95 +               if (!list_empty(&ns->base.profiles))
96 +                       return list_first_entry(&ns->base.profiles,
97 +                                               struct aa_profile, base.list);
98 +       }
99 +       return NULL;
100 +}
101 +
102 +/**
103 + * __next_profile - step to the next profile in a profile tree
104 + * @profile: current profile in tree (NOT NULL)
105 + *
106 + * Perform a depth first taversal on the profile tree in a namespace
107 + *
108 + * Returns: next profile or NULL if done
109 + * Requires: profile->ns.lock to be held
110 + */
111 +static struct aa_profile *__next_profile(struct aa_profile *p)
112 +{
113 +       struct aa_profile *parent;
114 +       struct aa_namespace *ns = p->ns;
115 +
116 +       /* is next profile a child */
117 +       if (!list_empty(&p->base.profiles))
118 +               return list_first_entry(&p->base.profiles, typeof(*p),
119 +                                       base.list);
120 +
121 +       /* is next profile a sibling, parent sibling, gp, subling, .. */
122 +       parent = p->parent;
123 +       while (parent) {
124 +               list_for_each_entry_continue(p, &parent->base.profiles,
125 +                                            base.list)
126 +                               return p;
127 +               p = parent;
128 +               parent = parent->parent;
129 +       }
130 +
131 +       /* is next another profile in the namespace */
132 +       list_for_each_entry_continue(p, &ns->base.profiles, base.list)
133 +               return p;
134 +
135 +       return NULL;
136 +}
137 +
138 +/**
139 + * next_profile - step to the next profile in where ever it may be
140 + * @root: root namespace  (NOT NULL)
141 + * @profile: current profile  (NOT NULL)
142 + *
143 + * Returns: next profile or NULL if there isn't one
144 + */
145 +static struct aa_profile *next_profile(struct aa_namespace *root,
146 +                                      struct aa_profile *profile)
147 +{
148 +       struct aa_profile *next = __next_profile(profile);
149 +       if (next)
150 +               return next;
151 +
152 +       /* finished all profiles in namespace move to next namespace */
153 +       return __first_profile(root, __next_namespace(root, profile->ns));
154 +}
155 +
156 +/**
157 + * p_start - start a depth first traversal of profile tree
158 + * @f: seq_file to fill
159 + * @pos: current position
160 + *
161 + * Returns: first profile under current namespace or NULL if none found
162 + *
163 + * acquires first ns->lock
164 + */
165 +static void *p_start(struct seq_file *f, loff_t *pos)
166 +       __acquires(root->lock)
167 +{
168 +       struct aa_profile *profile = NULL;
169 +       struct aa_namespace *root = aa_current_profile()->ns;
170 +       loff_t l = *pos;
171 +       f->private = aa_get_namespace(root);
172 +
173 +
174 +       /* find the first profile */
175 +       read_lock(&root->lock);
176 +       profile = __first_profile(root, root);
177 +
178 +       /* skip to position */
179 +       for (; profile && l > 0; l--)
180 +               profile = next_profile(root, profile);
181 +
182 +       return profile;
183 +}
184 +
185 +/**
186 + * p_next - read the next profile entry
187 + * @f: seq_file to fill
188 + * @p: profile previously returned
189 + * @pos: current position
190 + *
191 + * Returns: next profile after @p or NULL if none
192 + *
193 + * may acquire/release locks in namespace tree as necessary
194 + */
195 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
196 +{
197 +       struct aa_profile *profile = p;
198 +       struct aa_namespace *root = f->private;
199 +       (*pos)++;
200 +
201 +       return next_profile(root, profile);
202 +}
203 +
204 +/**
205 + * p_stop - stop depth first traversal
206 + * @f: seq_file we are filling
207 + * @p: the last profile writen
208 + *
209 + * Release all locking done by p_start/p_next on namespace tree
210 + */
211 +static void p_stop(struct seq_file *f, void *p)
212 +       __releases(root->lock)
213 +{
214 +       struct aa_profile *profile = p;
215 +       struct aa_namespace *root = f->private, *ns;
216 +
217 +       if (profile) {
218 +               for (ns = profile->ns; ns && ns != root; ns = ns->parent)
219 +                       read_unlock(&ns->lock);
220 +       }
221 +       read_unlock(&root->lock);
222 +       aa_put_namespace(root);
223 +}
224 +
225 +/**
226 + * seq_show_profile - show a profile entry
227 + * @f: seq_file to file
228 + * @p: current position (profile)    (NOT NULL)
229 + *
230 + * Returns: error on failure
231 + */
232 +static int seq_show_profile(struct seq_file *f, void *p)
233 +{
234 +       struct aa_profile *profile = (struct aa_profile *)p;
235 +       struct aa_namespace *root = f->private;
236 +
237 +       if (profile->ns != root)
238 +               seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
239 +       seq_printf(f, "%s (%s)\n", profile->base.hname,
240 +                  COMPLAIN_MODE(profile) ? "complain" : "enforce");
241 +
242 +       return 0;
243 +}
244 +
245 +static const struct seq_operations aa_fs_profiles_op = {
246 +       .start = p_start,
247 +       .next = p_next,
248 +       .stop = p_stop,
249 +       .show = seq_show_profile,
250 +};
251 +
252 +static int profiles_open(struct inode *inode, struct file *file)
253 +{
254 +       return seq_open(file, &aa_fs_profiles_op);
255 +}
256 +
257 +static int profiles_release(struct inode *inode, struct file *file)
258 +{
259 +       return seq_release(inode, file);
260 +}
261 +
262 +const struct file_operations aa_fs_profiles_fops = {
263 +       .open = profiles_open,
264 +       .read = seq_read,
265 +       .llseek = seq_lseek,
266 +       .release = profiles_release,
267 +};
268 +#endif /* CONFIG_SECURITY_APPARMOR_COMPAT_24 */
269 +
270  /** Base file system setup **/
271  
272  static struct aa_fs_entry aa_fs_entry_file[] = {
273 @@ -210,6 +438,9 @@ static struct aa_fs_entry aa_fs_entry_apparmor[] = {
274         AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
275         AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
276         AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
277 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
278 +       AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops),
279 +#endif
280         AA_FS_DIR("features", aa_fs_entry_features),
281         { }
282  };
283 -- 
284 1.7.6.5
285
286 From 4facdf9db37c12ff655c91270d9030e2ed805ca2 Mon Sep 17 00:00:00 2001
287 From: John Johansen <john.johansen@canonical.com>
288 Date: Mon, 4 Oct 2010 15:03:36 -0700
289 Subject: [PATCH] UBUNTU: SAUCE: AppArmor: basic networking rules
290
291 Base support for network mediation.
292
293 Signed-off-by: John Johansen <john.johansen@canonical.com>
294 ---
295  security/apparmor/.gitignore       |    2 +-
296  security/apparmor/Makefile         |   42 +++++++++-
297  security/apparmor/apparmorfs.c     |    1 +
298  security/apparmor/include/audit.h  |    4 +
299  security/apparmor/include/net.h    |   44 ++++++++++
300  security/apparmor/include/policy.h |    3 +
301  security/apparmor/lsm.c            |  112 +++++++++++++++++++++++++
302  security/apparmor/net.c            |  162 ++++++++++++++++++++++++++++++++++++
303  security/apparmor/policy.c         |    1 +
304  security/apparmor/policy_unpack.c  |   46 ++++++++++
305  10 files changed, 414 insertions(+), 3 deletions(-)
306  create mode 100644 security/apparmor/include/net.h
307  create mode 100644 security/apparmor/net.c
308
309 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
310 index 806bd19..19daa85 100644
311 --- a/security/apparmor/Makefile
312 +++ b/security/apparmor/Makefile
313 @@ -4,9 +4,9 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
314  
315  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
316                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
317 -              resource.o sid.o file.o
318 +              resource.o sid.o file.o net.o
319  
320 -clean-files := capability_names.h rlim_names.h
321 +clean-files := capability_names.h rlim_names.h net_names.h
322  
323  
324  # Build a lower case string table of capability names
325 @@ -20,6 +20,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
326         -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
327         echo "};" >> $@
328  
329 +# Build a lower case string table of address family names
330 +# Transform lines from
331 +#    define AF_LOCAL   1       /* POSIX name for AF_UNIX       */
332 +#    #define AF_INET           2       /* Internet IP Protocol         */
333 +# to
334 +#    [1] = "local",
335 +#    [2] = "inet",
336 +#
337 +# and build the securityfs entries for the mapping.
338 +# Transforms lines from
339 +#    #define AF_INET           2       /* Internet IP Protocol         */
340 +# to
341 +#    #define AA_FS_AF_MASK "local inet"
342 +quiet_cmd_make-af = GEN     $@
343 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
344 +       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
345 +        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
346 +       echo "};" >> $@ ;\
347 +       echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
348 +       sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
349 +        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
350 +
351 +# Build a lower case string table of sock type names
352 +# Transform lines from
353 +#    SOCK_STREAM       = 1,
354 +# to
355 +#    [1] = "stream",
356 +quiet_cmd_make-sock = GEN     $@
357 +cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
358 +       sed $^ >>$@ -r -n \
359 +       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
360 +       echo "};" >> $@
361  
362  # Build a lower case string table of rlimit names.
363  # Transforms lines from
364 @@ -56,6 +88,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
365             tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
366  
367  $(obj)/capability.o : $(obj)/capability_names.h
368 +$(obj)/net.o : $(obj)/net_names.h
369  $(obj)/resource.o : $(obj)/rlim_names.h
370  $(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
371                             $(src)/Makefile
372 @@ -63,3 +96,8 @@ $(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
373  $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \
374                       $(src)/Makefile
375         $(call cmd,make-rlim)
376 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
377 +                    $(srctree)/include/linux/net.h \
378 +                    $(src)/Makefile
379 +       $(call cmd,make-af)
380 +       $(call cmd,make-sock)
381 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
382 index 42b7c9f..114fb23 100644
383 --- a/security/apparmor/apparmorfs.c
384 +++ b/security/apparmor/apparmorfs.c
385 @@ -429,6 +429,7 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
386  static struct aa_fs_entry aa_fs_entry_features[] = {
387         AA_FS_DIR("domain",                     aa_fs_entry_domain),
388         AA_FS_DIR("file",                       aa_fs_entry_file),
389 +       AA_FS_DIR("network",                    aa_fs_entry_network),
390         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
391         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
392         { }
393 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
394 index 4b7e189..17734f9 100644
395 --- a/security/apparmor/include/audit.h
396 +++ b/security/apparmor/include/audit.h
397 @@ -127,6 +127,10 @@ struct apparmor_audit_data {
398                         u32 denied;
399                         uid_t ouid;
400                 } fs;
401 +               struct {
402 +                       int type, protocol;
403 +                       struct sock *sk;
404 +               } net;
405         };
406  };
407  
408 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
409 new file mode 100644
410 index 0000000..cb8a121
411 --- /dev/null
412 +++ b/security/apparmor/include/net.h
413 @@ -0,0 +1,44 @@
414 +/*
415 + * AppArmor security module
416 + *
417 + * This file contains AppArmor network mediation definitions.
418 + *
419 + * Copyright (C) 1998-2008 Novell/SUSE
420 + * Copyright 2009-2012 Canonical Ltd.
421 + *
422 + * This program is free software; you can redistribute it and/or
423 + * modify it under the terms of the GNU General Public License as
424 + * published by the Free Software Foundation, version 2 of the
425 + * License.
426 + */
427 +
428 +#ifndef __AA_NET_H
429 +#define __AA_NET_H
430 +
431 +#include <net/sock.h>
432 +
433 +#include "apparmorfs.h"
434 +
435 +/* struct aa_net - network confinement data
436 + * @allowed: basic network families permissions
437 + * @audit_network: which network permissions to force audit
438 + * @quiet_network: which network permissions to quiet rejects
439 + */
440 +struct aa_net {
441 +       u16 allow[AF_MAX];
442 +       u16 audit[AF_MAX];
443 +       u16 quiet[AF_MAX];
444 +};
445 +
446 +extern struct aa_fs_entry aa_fs_entry_network[];
447 +
448 +extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
449 +                      int type, int protocol, struct sock *sk);
450 +extern int aa_revalidate_sk(int op, struct sock *sk);
451 +
452 +static inline void aa_free_net_rules(struct aa_net *new)
453 +{
454 +       /* NOP */
455 +}
456 +
457 +#endif /* __AA_NET_H */
458 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
459 index bda4569..eb13a73 100644
460 --- a/security/apparmor/include/policy.h
461 +++ b/security/apparmor/include/policy.h
462 @@ -27,6 +27,7 @@
463  #include "capability.h"
464  #include "domain.h"
465  #include "file.h"
466 +#include "net.h"
467  #include "resource.h"
468  
469  extern const char *const profile_mode_names[];
470 @@ -157,6 +158,7 @@ struct aa_policydb {
471   * @policy: general match rules governing policy
472   * @file: The set of rules governing basic file access and domain transitions
473   * @caps: capabilities for the profile
474 + * @net: network controls for the profile
475   * @rlimits: rlimits for the profile
476   *
477   * The AppArmor profile contains the basic confinement data.  Each profile
478 @@ -194,6 +196,7 @@ struct aa_profile {
479         struct aa_policydb policy;
480         struct aa_file_rules file;
481         struct aa_caps caps;
482 +       struct aa_net net;
483         struct aa_rlimit rlimits;
484  };
485  
486 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
487 index 8ea39aa..f628734 100644
488 --- a/security/apparmor/lsm.c
489 +++ b/security/apparmor/lsm.c
490 @@ -32,6 +32,7 @@
491  #include "include/context.h"
492  #include "include/file.h"
493  #include "include/ipc.h"
494 +#include "include/net.h"
495  #include "include/path.h"
496  #include "include/policy.h"
497  #include "include/procattr.h"
498 @@ -614,6 +615,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
499         return error;
500  }
501  
502 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
503 +{
504 +       struct aa_profile *profile;
505 +       int error = 0;
506 +
507 +       if (kern)
508 +               return 0;
509 +
510 +       profile = __aa_current_profile();
511 +       if (!unconfined(profile))
512 +               error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
513 +                                   NULL);
514 +       return error;
515 +}
516 +
517 +static int apparmor_socket_bind(struct socket *sock,
518 +                               struct sockaddr *address, int addrlen)
519 +{
520 +       struct sock *sk = sock->sk;
521 +
522 +       return aa_revalidate_sk(OP_BIND, sk);
523 +}
524 +
525 +static int apparmor_socket_connect(struct socket *sock,
526 +                                  struct sockaddr *address, int addrlen)
527 +{
528 +       struct sock *sk = sock->sk;
529 +
530 +       return aa_revalidate_sk(OP_CONNECT, sk);
531 +}
532 +
533 +static int apparmor_socket_listen(struct socket *sock, int backlog)
534 +{
535 +       struct sock *sk = sock->sk;
536 +
537 +       return aa_revalidate_sk(OP_LISTEN, sk);
538 +}
539 +
540 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
541 +{
542 +       struct sock *sk = sock->sk;
543 +
544 +       return aa_revalidate_sk(OP_ACCEPT, sk);
545 +}
546 +
547 +static int apparmor_socket_sendmsg(struct socket *sock,
548 +                                  struct msghdr *msg, int size)
549 +{
550 +       struct sock *sk = sock->sk;
551 +
552 +       return aa_revalidate_sk(OP_SENDMSG, sk);
553 +}
554 +
555 +static int apparmor_socket_recvmsg(struct socket *sock,
556 +                                  struct msghdr *msg, int size, int flags)
557 +{
558 +       struct sock *sk = sock->sk;
559 +
560 +       return aa_revalidate_sk(OP_RECVMSG, sk);
561 +}
562 +
563 +static int apparmor_socket_getsockname(struct socket *sock)
564 +{
565 +       struct sock *sk = sock->sk;
566 +
567 +       return aa_revalidate_sk(OP_GETSOCKNAME, sk);
568 +}
569 +
570 +static int apparmor_socket_getpeername(struct socket *sock)
571 +{
572 +       struct sock *sk = sock->sk;
573 +
574 +       return aa_revalidate_sk(OP_GETPEERNAME, sk);
575 +}
576 +
577 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
578 +                                     int optname)
579 +{
580 +       struct sock *sk = sock->sk;
581 +
582 +       return aa_revalidate_sk(OP_GETSOCKOPT, sk);
583 +}
584 +
585 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
586 +                                     int optname)
587 +{
588 +       struct sock *sk = sock->sk;
589 +
590 +       return aa_revalidate_sk(OP_SETSOCKOPT, sk);
591 +}
592 +
593 +static int apparmor_socket_shutdown(struct socket *sock, int how)
594 +{
595 +       struct sock *sk = sock->sk;
596 +
597 +       return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
598 +}
599 +
600  static struct security_operations apparmor_ops = {
601         .name =                         "apparmor",
602  
603 @@ -646,6 +745,19 @@ static struct security_operations apparmor_ops = {
604         .getprocattr =                  apparmor_getprocattr,
605         .setprocattr =                  apparmor_setprocattr,
606  
607 +       .socket_create =                apparmor_socket_create,
608 +       .socket_bind =                  apparmor_socket_bind,
609 +       .socket_connect =               apparmor_socket_connect,
610 +       .socket_listen =                apparmor_socket_listen,
611 +       .socket_accept =                apparmor_socket_accept,
612 +       .socket_sendmsg =               apparmor_socket_sendmsg,
613 +       .socket_recvmsg =               apparmor_socket_recvmsg,
614 +       .socket_getsockname =           apparmor_socket_getsockname,
615 +       .socket_getpeername =           apparmor_socket_getpeername,
616 +       .socket_getsockopt =            apparmor_socket_getsockopt,
617 +       .socket_setsockopt =            apparmor_socket_setsockopt,
618 +       .socket_shutdown =              apparmor_socket_shutdown,
619 +
620         .cred_alloc_blank =             apparmor_cred_alloc_blank,
621         .cred_free =                    apparmor_cred_free,
622         .cred_prepare =                 apparmor_cred_prepare,
623 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
624 new file mode 100644
625 index 0000000..003dd18
626 --- /dev/null
627 +++ b/security/apparmor/net.c
628 @@ -0,0 +1,162 @@
629 +/*
630 + * AppArmor security module
631 + *
632 + * This file contains AppArmor network mediation
633 + *
634 + * Copyright (C) 1998-2008 Novell/SUSE
635 + * Copyright 2009-2012 Canonical Ltd.
636 + *
637 + * This program is free software; you can redistribute it and/or
638 + * modify it under the terms of the GNU General Public License as
639 + * published by the Free Software Foundation, version 2 of the
640 + * License.
641 + */
642 +
643 +#include "include/apparmor.h"
644 +#include "include/audit.h"
645 +#include "include/context.h"
646 +#include "include/net.h"
647 +#include "include/policy.h"
648 +
649 +#include "net_names.h"
650 +
651 +struct aa_fs_entry aa_fs_entry_network[] = {
652 +       AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
653 +       { }
654 +};
655 +
656 +/* audit callback for net specific fields */
657 +static void audit_cb(struct audit_buffer *ab, void *va)
658 +{
659 +       struct common_audit_data *sa = va;
660 +
661 +       audit_log_format(ab, " family=");
662 +       if (address_family_names[sa->u.net->family]) {
663 +               audit_log_string(ab, address_family_names[sa->u.net->family]);
664 +       } else {
665 +               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
666 +       }
667 +       audit_log_format(ab, " sock_type=");
668 +       if (sock_type_names[sa->aad->net.type]) {
669 +               audit_log_string(ab, sock_type_names[sa->aad->net.type]);
670 +       } else {
671 +               audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
672 +       }
673 +       audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
674 +}
675 +
676 +/**
677 + * audit_net - audit network access
678 + * @profile: profile being enforced  (NOT NULL)
679 + * @op: operation being checked
680 + * @family: network family
681 + * @type:   network type
682 + * @protocol: network protocol
683 + * @sk: socket auditing is being applied to
684 + * @error: error code for failure else 0
685 + *
686 + * Returns: %0 or sa->error else other errorcode on failure
687 + */
688 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
689 +                    int protocol, struct sock *sk, int error)
690 +{
691 +       int audit_type = AUDIT_APPARMOR_AUTO;
692 +       struct common_audit_data sa;
693 +       struct apparmor_audit_data aad = { };
694 +       struct lsm_network_audit net = { };
695 +       if (sk) {
696 +               sa.type = LSM_AUDIT_DATA_NET;
697 +       } else {
698 +               sa.type = LSM_AUDIT_DATA_NONE;
699 +       }
700 +       /* todo fill in socket addr info */
701 +       sa.aad = &aad;
702 +       sa.u.net = &net;
703 +       sa.aad->op = op,
704 +       sa.u.net->family = family;
705 +       sa.u.net->sk = sk;
706 +       sa.aad->net.type = type;
707 +       sa.aad->net.protocol = protocol;
708 +       sa.aad->error = error;
709 +
710 +       if (likely(!sa.aad->error)) {
711 +               u16 audit_mask = profile->net.audit[sa.u.net->family];
712 +               if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
713 +                          !(1 << sa.aad->net.type & audit_mask)))
714 +                       return 0;
715 +               audit_type = AUDIT_APPARMOR_AUDIT;
716 +       } else {
717 +               u16 quiet_mask = profile->net.quiet[sa.u.net->family];
718 +               u16 kill_mask = 0;
719 +               u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
720 +
721 +               if (denied & kill_mask)
722 +                       audit_type = AUDIT_APPARMOR_KILL;
723 +
724 +               if ((denied & quiet_mask) &&
725 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
726 +                   AUDIT_MODE(profile) != AUDIT_ALL)
727 +                       return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
728 +       }
729 +
730 +       return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
731 +}
732 +
733 +/**
734 + * aa_net_perm - very course network access check
735 + * @op: operation being checked
736 + * @profile: profile being enforced  (NOT NULL)
737 + * @family: network family
738 + * @type:   network type
739 + * @protocol: network protocol
740 + *
741 + * Returns: %0 else error if permission denied
742 + */
743 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
744 +               int protocol, struct sock *sk)
745 +{
746 +       u16 family_mask;
747 +       int error;
748 +
749 +       if ((family < 0) || (family >= AF_MAX))
750 +               return -EINVAL;
751 +
752 +       if ((type < 0) || (type >= SOCK_MAX))
753 +               return -EINVAL;
754 +
755 +       /* unix domain and netlink sockets are handled by ipc */
756 +       if (family == AF_UNIX || family == AF_NETLINK)
757 +               return 0;
758 +
759 +       family_mask = profile->net.allow[family];
760 +
761 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
762 +
763 +       return audit_net(profile, op, family, type, protocol, sk, error);
764 +}
765 +
766 +/**
767 + * aa_revalidate_sk - Revalidate access to a sock
768 + * @op: operation being checked
769 + * @sk: sock being revalidated  (NOT NULL)
770 + *
771 + * Returns: %0 else error if permission denied
772 + */
773 +int aa_revalidate_sk(int op, struct sock *sk)
774 +{
775 +       struct aa_profile *profile;
776 +       int error = 0;
777 +
778 +       /* aa_revalidate_sk should not be called from interrupt context
779 +        * don't mediate these calls as they are not task related
780 +        */
781 +       if (in_interrupt())
782 +               return 0;
783 +
784 +       profile = __aa_current_profile();
785 +       if (!unconfined(profile))
786 +               error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
787 +                                   sk->sk_protocol, sk);
788 +
789 +       return error;
790 +}
791 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
792 index cf5fd22..27c8161 100644
793 --- a/security/apparmor/policy.c
794 +++ b/security/apparmor/policy.c
795 @@ -745,6 +745,7 @@ static void free_profile(struct aa_profile *profile)
796  
797         aa_free_file_rules(&profile->file);
798         aa_free_cap_rules(&profile->caps);
799 +       aa_free_net_rules(&profile->net);
800         aa_free_rlimit_rules(&profile->rlimits);
801  
802         aa_free_sid(profile->sid);
803 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
804 index 329b1fd..1b90dfa 100644
805 --- a/security/apparmor/policy_unpack.c
806 +++ b/security/apparmor/policy_unpack.c
807 @@ -193,6 +193,19 @@ fail:
808         return 0;
809  }
810  
811 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
812 +{
813 +       if (unpack_nameX(e, AA_U16, name)) {
814 +               if (!inbounds(e, sizeof(u16)))
815 +                       return 0;
816 +               if (data)
817 +                       *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
818 +               e->pos += sizeof(u16);
819 +               return 1;
820 +       }
821 +       return 0;
822 +}
823 +
824  static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
825  {
826         if (unpack_nameX(e, AA_U32, name)) {
827 @@ -471,6 +484,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
828  {
829         struct aa_profile *profile = NULL;
830         const char *name = NULL;
831 +       size_t size = 0;
832         int i, error = -EPROTO;
833         kernel_cap_t tmpcap;
834         u32 tmp;
835 @@ -564,6 +578,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
836         if (!unpack_rlimits(e, profile))
837                 goto fail;
838  
839 +       size = unpack_array(e, "net_allowed_af");
840 +       if (size) {
841 +
842 +               for (i = 0; i < size; i++) {
843 +                       /* discard extraneous rules that this kernel will
844 +                        * never request
845 +                        */
846 +                       if (i >= AF_MAX) {
847 +                               u16 tmp;
848 +                               if (!unpack_u16(e, &tmp, NULL) ||
849 +                                   !unpack_u16(e, &tmp, NULL) ||
850 +                                   !unpack_u16(e, &tmp, NULL))
851 +                                       goto fail;
852 +                               continue;
853 +                       }
854 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
855 +                               goto fail;
856 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
857 +                               goto fail;
858 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
859 +                               goto fail;
860 +               }
861 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
862 +                       goto fail;
863 +       }
864 +       /*
865 +        * allow unix domain and netlink sockets they are handled
866 +        * by IPC
867 +        */
868 +       profile->net.allow[AF_UNIX] = 0xffff;
869 +       profile->net.allow[AF_NETLINK] = 0xffff;
870 +
871         if (unpack_nameX(e, AA_STRUCT, "policydb")) {
872                 /* generic policy dfa - optional and may be NULL */
873                 profile->policy.dfa = unpack_dfa(e);
874 -- 
875 1.7.7.6
876
877 From 888a3d71db1ffd3a19d9f621b07e60c4ab9e1c44 Mon Sep 17 00:00:00 2001
878 From: John Johansen <john.johansen@canonical.com>
879 Date: Wed, 16 May 2012 10:58:05 -0700
880 Subject: [PATCH] UBUNTU: SAUCE: apparmor: Add the ability to mediate mount
881
882 Add the ability for apparmor to do mediation of mount operations. Mount
883 rules require an updated apparmor_parser (2.8 series) for policy compilation.
884
885 The basic form of the rules are.
886
887   [audit] [deny] mount [conds]* [device] [ -> [conds] path],
888   [audit] [deny] remount [conds]* [path],
889   [audit] [deny] umount [conds]* [path],
890   [audit] [deny] pivotroot [oldroot=<value>] <path>
891
892   remount is just a short cut for mount options=remount
893
894   where [conds] can be
895     fstype=<expr>
896     options=<expr>
897
898 Example mount commands
899   mount,                # allow all mounts, but not umount or pivotroot
900
901   mount fstype=procfs,  # allow mounting procfs anywhere
902
903   mount options=(bind, ro) /foo -> /bar,  # readonly bind mount
904
905   mount /dev/sda -> /mnt,
906
907   mount /dev/sd** -> /mnt/**,
908
909   mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
910
911   umount,
912
913   umount /m*,
914
915 See the apparmor userspace for full documentation
916
917 Signed-off-by: John Johansen <john.johansen@canonical.com>
918 Acked-by: Kees Cook <kees@ubuntu.com>
919 ---
920  security/apparmor/Makefile           |    2 +-
921  security/apparmor/apparmorfs.c       |   13 +
922  security/apparmor/audit.c            |    4 +
923  security/apparmor/domain.c           |    2 +-
924  security/apparmor/include/apparmor.h |    3 +-
925  security/apparmor/include/audit.h    |   11 +
926  security/apparmor/include/domain.h   |    2 +
927  security/apparmor/include/mount.h    |   54 +++
928  security/apparmor/lsm.c              |   59 ++++
929  security/apparmor/mount.c            |  620 ++++++++++++++++++++++++++++++++++
930  10 files changed, 767 insertions(+), 3 deletions(-)
931  create mode 100644 security/apparmor/include/mount.h
932  create mode 100644 security/apparmor/mount.c
933
934 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
935 index 19daa85..63e0a4c 100644
936 --- a/security/apparmor/Makefile
937 +++ b/security/apparmor/Makefile
938 @@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
939  
940  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
941                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
942 -              resource.o sid.o file.o net.o
943 +              resource.o sid.o file.o net.o mount.o
944  
945  clean-files := capability_names.h rlim_names.h net_names.h
946  
947 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
948 index 114fb23..ee77ec9 100644
949 --- a/security/apparmor/apparmorfs.c
950 +++ b/security/apparmor/apparmorfs.c
951 @@ -426,10 +426,23 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
952         { }
953  };
954  
955 +static struct aa_fs_entry aa_fs_entry_mount[] = {
956 +       AA_FS_FILE_STRING("mask", "mount umount"),
957 +       { }
958 +};
959 +
960 +static struct aa_fs_entry aa_fs_entry_namespaces[] = {
961 +       AA_FS_FILE_BOOLEAN("profile",           1),
962 +       AA_FS_FILE_BOOLEAN("pivot_root",        1),
963 +       { }
964 +};
965 +
966  static struct aa_fs_entry aa_fs_entry_features[] = {
967         AA_FS_DIR("domain",                     aa_fs_entry_domain),
968         AA_FS_DIR("file",                       aa_fs_entry_file),
969         AA_FS_DIR("network",                    aa_fs_entry_network),
970 +       AA_FS_DIR("mount",                      aa_fs_entry_mount),
971 +       AA_FS_DIR("namespaces",                 aa_fs_entry_namespaces),
972         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
973         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
974         { }
975 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
976 index 3ae28db..e267963 100644
977 --- a/security/apparmor/audit.c
978 +++ b/security/apparmor/audit.c
979 @@ -44,6 +44,10 @@ const char *const op_table[] = {
980         "file_mmap",
981         "file_mprotect",
982  
983 +       "pivotroot",
984 +       "mount",
985 +       "umount",
986 +
987         "create",
988         "post_create",
989         "bind",
990 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
991 index b81ea10..afa8671 100644
992 --- a/security/apparmor/domain.c
993 +++ b/security/apparmor/domain.c
994 @@ -242,7 +242,7 @@ static const char *next_name(int xtype, const char *name)
995   *
996   * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
997   */
998 -static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
999 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
1000  {
1001         struct aa_profile *new_profile = NULL;
1002         struct aa_namespace *ns = profile->ns;
1003 diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
1004 index 40aedd9..e243d96 100644
1005 --- a/security/apparmor/include/apparmor.h
1006 +++ b/security/apparmor/include/apparmor.h
1007 @@ -29,8 +29,9 @@
1008  #define AA_CLASS_NET           4
1009  #define AA_CLASS_RLIMITS       5
1010  #define AA_CLASS_DOMAIN                6
1011 +#define AA_CLASS_MOUNT         7
1012  
1013 -#define AA_CLASS_LAST          AA_CLASS_DOMAIN
1014 +#define AA_CLASS_LAST          AA_CLASS_MOUNT
1015  
1016  /* Control parameters settable through module/boot flags */
1017  extern enum audit_mode aa_g_audit;
1018 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
1019 index 17734f9..66a738c 100644
1020 --- a/security/apparmor/include/audit.h
1021 +++ b/security/apparmor/include/audit.h
1022 @@ -73,6 +73,10 @@ enum aa_ops {
1023         OP_FMMAP,
1024         OP_FMPROT,
1025  
1026 +       OP_PIVOTROOT,
1027 +       OP_MOUNT,
1028 +       OP_UMOUNT,
1029 +
1030         OP_CREATE,
1031         OP_POST_CREATE,
1032         OP_BIND,
1033 @@ -122,6 +126,13 @@ struct apparmor_audit_data {
1034                         unsigned long max;
1035                 } rlim;
1036                 struct {
1037 +                       const char *src_name;
1038 +                       const char *type;
1039 +                       const char *trans;
1040 +                       const char *data;
1041 +                       unsigned long flags;
1042 +               } mnt;
1043 +               struct {
1044                         const char *target;
1045                         u32 request;
1046                         u32 denied;
1047 diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
1048 index de04464..a3f70c5 100644
1049 --- a/security/apparmor/include/domain.h
1050 +++ b/security/apparmor/include/domain.h
1051 @@ -23,6 +23,8 @@ struct aa_domain {
1052         char **table;
1053  };
1054  
1055 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
1056 +
1057  int apparmor_bprm_set_creds(struct linux_binprm *bprm);
1058  int apparmor_bprm_secureexec(struct linux_binprm *bprm);
1059  void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
1060 diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
1061 new file mode 100644
1062 index 0000000..bc17a53
1063 --- /dev/null
1064 +++ b/security/apparmor/include/mount.h
1065 @@ -0,0 +1,54 @@
1066 +/*
1067 + * AppArmor security module
1068 + *
1069 + * This file contains AppArmor file mediation function definitions.
1070 + *
1071 + * Copyright 2012 Canonical Ltd.
1072 + *
1073 + * This program is free software; you can redistribute it and/or
1074 + * modify it under the terms of the GNU General Public License as
1075 + * published by the Free Software Foundation, version 2 of the
1076 + * License.
1077 + */
1078 +
1079 +#ifndef __AA_MOUNT_H
1080 +#define __AA_MOUNT_H
1081 +
1082 +#include <linux/fs.h>
1083 +#include <linux/path.h>
1084 +
1085 +#include "domain.h"
1086 +#include "policy.h"
1087 +
1088 +/* mount perms */
1089 +#define AA_MAY_PIVOTROOT       0x01
1090 +#define AA_MAY_MOUNT           0x02
1091 +#define AA_MAY_UMOUNT          0x04
1092 +#define AA_AUDIT_DATA          0x40
1093 +#define AA_CONT_MATCH          0x40
1094 +
1095 +#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
1096 +
1097 +int aa_remount(struct aa_profile *profile, struct path *path,
1098 +              unsigned long flags, void *data);
1099 +
1100 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
1101 +                 const char *old_name, unsigned long flags);
1102 +
1103 +
1104 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
1105 +                        unsigned long flags);
1106 +
1107 +int aa_move_mount(struct aa_profile *profile, struct path *path,
1108 +                 const char *old_name);
1109 +
1110 +int aa_new_mount(struct aa_profile *profile, const char *dev_name,
1111 +                struct path *path, const char *type, unsigned long flags,
1112 +                void *data);
1113 +
1114 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
1115 +
1116 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
1117 +                 struct path *new_path);
1118 +
1119 +#endif /* __AA_MOUNT_H */
1120 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
1121 index f628734..65ff9e4 100644
1122 --- a/security/apparmor/lsm.c
1123 +++ b/security/apparmor/lsm.c
1124 @@ -36,6 +36,7 @@
1125  #include "include/path.h"
1126  #include "include/policy.h"
1127  #include "include/procattr.h"
1128 +#include "include/mount.h"
1129  
1130  /* Flag indicating whether initialization completed */
1131  int apparmor_initialized __initdata;
1132 @@ -504,6 +505,60 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
1133                            !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
1134  }
1135  
1136 +static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
1137 +                            unsigned long flags, void *data)
1138 +{
1139 +       struct aa_profile *profile;
1140 +       int error = 0;
1141 +
1142 +       /* Discard magic */
1143 +       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
1144 +               flags &= ~MS_MGC_MSK;
1145 +
1146 +       flags &= ~AA_MS_IGNORE_MASK;
1147 +
1148 +       profile = __aa_current_profile();
1149 +       if (!unconfined(profile)) {
1150 +               if (flags & MS_REMOUNT)
1151 +                       error = aa_remount(profile, path, flags, data);
1152 +               else if (flags & MS_BIND)
1153 +                       error = aa_bind_mount(profile, path, dev_name, flags);
1154 +               else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
1155 +                                 MS_UNBINDABLE))
1156 +                       error = aa_mount_change_type(profile, path, flags);
1157 +               else if (flags & MS_MOVE)
1158 +                       error = aa_move_mount(profile, path, dev_name);
1159 +               else
1160 +                       error = aa_new_mount(profile, dev_name, path, type,
1161 +                                            flags, data);
1162 +       }
1163 +       return error;
1164 +}
1165 +
1166 +static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
1167 +{
1168 +       struct aa_profile *profile;
1169 +       int error = 0;
1170 +
1171 +       profile = __aa_current_profile();
1172 +       if (!unconfined(profile))
1173 +               error = aa_umount(profile, mnt, flags);
1174 +
1175 +       return error;
1176 +}
1177 +
1178 +static int apparmor_sb_pivotroot(struct path *old_path, struct path *new_path)
1179 +{
1180 +       struct aa_profile *profile;
1181 +       int error = 0;
1182 +
1183 +       profile = __aa_current_profile();
1184 +       if (!unconfined(profile))
1185 +               error = aa_pivotroot(profile, old_path, new_path);
1186 +
1187 +       return error;
1188 +}
1189 +
1190  static int apparmor_getprocattr(struct task_struct *task, char *name,
1191                                 char **value)
1192  {
1193 @@ -721,6 +776,10 @@ static struct security_operations apparmor_ops = {
1194         .capget =                       apparmor_capget,
1195         .capable =                      apparmor_capable,
1196  
1197 +       .sb_mount =                     apparmor_sb_mount,
1198 +       .sb_umount =                    apparmor_sb_umount,
1199 +       .sb_pivotroot =                 apparmor_sb_pivotroot,
1200 +
1201         .path_link =                    apparmor_path_link,
1202         .path_unlink =                  apparmor_path_unlink,
1203         .path_symlink =                 apparmor_path_symlink,
1204 diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
1205 new file mode 100644
1206 index 0000000..478aa4d
1207 --- /dev/null
1208 +++ b/security/apparmor/mount.c
1209 @@ -0,0 +1,620 @@
1210 +/*
1211 + * AppArmor security module
1212 + *
1213 + * This file contains AppArmor mediation of files
1214 + *
1215 + * Copyright (C) 1998-2008 Novell/SUSE
1216 + * Copyright 2009-2012 Canonical Ltd.
1217 + *
1218 + * This program is free software; you can redistribute it and/or
1219 + * modify it under the terms of the GNU General Public License as
1220 + * published by the Free Software Foundation, version 2 of the
1221 + * License.
1222 + */
1223 +
1224 +#include <linux/fs.h>
1225 +#include <linux/mount.h>
1226 +#include <linux/namei.h>
1227 +
1228 +#include "include/apparmor.h"
1229 +#include "include/audit.h"
1230 +#include "include/context.h"
1231 +#include "include/domain.h"
1232 +#include "include/file.h"
1233 +#include "include/match.h"
1234 +#include "include/mount.h"
1235 +#include "include/path.h"
1236 +#include "include/policy.h"
1237 +
1238 +
1239 +static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
1240 +{
1241 +       if (flags & MS_RDONLY)
1242 +               audit_log_format(ab, "ro");
1243 +       else
1244 +               audit_log_format(ab, "rw");
1245 +       if (flags & MS_NOSUID)
1246 +               audit_log_format(ab, ", nosuid");
1247 +       if (flags & MS_NODEV)
1248 +               audit_log_format(ab, ", nodev");
1249 +       if (flags & MS_NOEXEC)
1250 +               audit_log_format(ab, ", noexec");
1251 +       if (flags & MS_SYNCHRONOUS)
1252 +               audit_log_format(ab, ", sync");
1253 +       if (flags & MS_REMOUNT)
1254 +               audit_log_format(ab, ", remount");
1255 +       if (flags & MS_MANDLOCK)
1256 +               audit_log_format(ab, ", mand");
1257 +       if (flags & MS_DIRSYNC)
1258 +               audit_log_format(ab, ", dirsync");
1259 +       if (flags & MS_NOATIME)
1260 +               audit_log_format(ab, ", noatime");
1261 +       if (flags & MS_NODIRATIME)
1262 +               audit_log_format(ab, ", nodiratime");
1263 +       if (flags & MS_BIND)
1264 +               audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
1265 +       if (flags & MS_MOVE)
1266 +               audit_log_format(ab, ", move");
1267 +       if (flags & MS_SILENT)
1268 +               audit_log_format(ab, ", silent");
1269 +       if (flags & MS_POSIXACL)
1270 +               audit_log_format(ab, ", acl");
1271 +       if (flags & MS_UNBINDABLE)
1272 +               audit_log_format(ab, flags & MS_REC ? ", runbindable" :
1273 +                                ", unbindable");
1274 +       if (flags & MS_PRIVATE)
1275 +               audit_log_format(ab, flags & MS_REC ? ", rprivate" :
1276 +                                ", private");
1277 +       if (flags & MS_SLAVE)
1278 +               audit_log_format(ab, flags & MS_REC ? ", rslave" :
1279 +                                ", slave");
1280 +       if (flags & MS_SHARED)
1281 +               audit_log_format(ab, flags & MS_REC ? ", rshared" :
1282 +                                ", shared");
1283 +       if (flags & MS_RELATIME)
1284 +               audit_log_format(ab, ", relatime");
1285 +       if (flags & MS_I_VERSION)
1286 +               audit_log_format(ab, ", iversion");
1287 +       if (flags & MS_STRICTATIME)
1288 +               audit_log_format(ab, ", strictatime");
1289 +       if (flags & MS_NOUSER)
1290 +               audit_log_format(ab, ", nouser");
1291 +}
1292 +
1293 +/**
1294 + * audit_cb - call back for mount specific audit fields
1295 + * @ab: audit_buffer  (NOT NULL)
1296 + * @va: audit struct to audit values of  (NOT NULL)
1297 + */
1298 +static void audit_cb(struct audit_buffer *ab, void *va)
1299 +{
1300 +       struct common_audit_data *sa = va;
1301 +
1302 +       if (sa->aad->mnt.type) {
1303 +               audit_log_format(ab, " fstype=");
1304 +               audit_log_untrustedstring(ab, sa->aad->mnt.type);
1305 +       }
1306 +       if (sa->aad->mnt.src_name) {
1307 +               audit_log_format(ab, " srcname=");
1308 +               audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
1309 +       }
1310 +       if (sa->aad->mnt.trans) {
1311 +               audit_log_format(ab, " trans=");
1312 +               audit_log_untrustedstring(ab, sa->aad->mnt.trans);
1313 +       }
1314 +       if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
1315 +               audit_log_format(ab, " flags=\"");
1316 +               audit_mnt_flags(ab, sa->aad->mnt.flags);
1317 +               audit_log_format(ab, "\"");
1318 +       }
1319 +       if (sa->aad->mnt.data) {
1320 +               audit_log_format(ab, " options=");
1321 +               audit_log_untrustedstring(ab, sa->aad->mnt.data);
1322 +       }
1323 +}
1324 +
1325 +/**
1326 + * audit_mount - handle the auditing of mount operations
1327 + * @profile: the profile being enforced  (NOT NULL)
1328 + * @gfp: allocation flags
1329 + * @op: operation being mediated (NOT NULL)
1330 + * @name: name of object being mediated (MAYBE NULL)
1331 + * @src_name: src_name of object being mediated (MAYBE_NULL)
1332 + * @type: type of filesystem (MAYBE_NULL)
1333 + * @trans: name of trans (MAYBE NULL)
1334 + * @flags: filesystem idependent mount flags
1335 + * @data: filesystem mount flags
1336 + * @request: permissions requested
1337 + * @perms: the permissions computed for the request (NOT NULL)
1338 + * @info: extra information message (MAYBE NULL)
1339 + * @error: 0 if operation allowed else failure error code
1340 + *
1341 + * Returns: %0 or error on failure
1342 + */
1343 +static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
1344 +                      const char *name, const char *src_name,
1345 +                      const char *type, const char *trans,
1346 +                      unsigned long flags, const void *data, u32 request,
1347 +                      struct file_perms *perms, const char *info, int error)
1348 +{
1349 +       int audit_type = AUDIT_APPARMOR_AUTO;
1350 +       struct common_audit_data sa = { };
1351 +       struct apparmor_audit_data aad = { };
1352 +
1353 +       if (likely(!error)) {
1354 +               u32 mask = perms->audit;
1355 +
1356 +               if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
1357 +                       mask = 0xffff;
1358 +
1359 +               /* mask off perms that are not being force audited */
1360 +               request &= mask;
1361 +
1362 +               if (likely(!request))
1363 +                       return 0;
1364 +               audit_type = AUDIT_APPARMOR_AUDIT;
1365 +       } else {
1366 +               /* only report permissions that were denied */
1367 +               request = request & ~perms->allow;
1368 +
1369 +               if (request & perms->kill)
1370 +                       audit_type = AUDIT_APPARMOR_KILL;
1371 +
1372 +               /* quiet known rejects, assumes quiet and kill do not overlap */
1373 +               if ((request & perms->quiet) &&
1374 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1375 +                   AUDIT_MODE(profile) != AUDIT_ALL)
1376 +                       request &= ~perms->quiet;
1377 +
1378 +               if (!request)
1379 +                       return COMPLAIN_MODE(profile) ?
1380 +                               complain_error(error) : error;
1381 +       }
1382 +
1383 +       sa.type = LSM_AUDIT_DATA_NONE;
1384 +       sa.aad = &aad;
1385 +       sa.aad->op = op;
1386 +       sa.aad->name = name;
1387 +       sa.aad->mnt.src_name = src_name;
1388 +       sa.aad->mnt.type = type;
1389 +       sa.aad->mnt.trans = trans;
1390 +       sa.aad->mnt.flags = flags;
1391 +       if (data && (perms->audit & AA_AUDIT_DATA))
1392 +               sa.aad->mnt.data = data;
1393 +       sa.aad->info = info;
1394 +       sa.aad->error = error;
1395 +
1396 +       return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
1397 +}
1398 +
1399 +/**
1400 + * match_mnt_flags - Do an ordered match on mount flags
1401 + * @dfa: dfa to match against
1402 + * @state: state to start in
1403 + * @flags: mount flags to match against
1404 + *
1405 + * Mount flags are encoded as an ordered match. This is done instead of
1406 + * checking against a simple bitmask, to allow for logical operations
1407 + * on the flags.
1408 + *
1409 + * Returns: next state after flags match
1410 + */
1411 +static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
1412 +                                   unsigned long flags)
1413 +{
1414 +       unsigned int i;
1415 +
1416 +       for (i = 0; i <= 31 ; ++i) {
1417 +               if ((1 << i) & flags)
1418 +                       state = aa_dfa_next(dfa, state, i + 1);
1419 +       }
1420 +
1421 +       return state;
1422 +}
1423 +
1424 +/**
1425 + * compute_mnt_perms - compute mount permission associated with @state
1426 + * @dfa: dfa to match against (NOT NULL)
1427 + * @state: state match finished in
1428 + *
1429 + * Returns: mount permissions
1430 + */
1431 +static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
1432 +                                          unsigned int state)
1433 +{
1434 +       struct file_perms perms;
1435 +
1436 +       perms.kill = 0;
1437 +       perms.allow = dfa_user_allow(dfa, state);
1438 +       perms.audit = dfa_user_audit(dfa, state);
1439 +       perms.quiet = dfa_user_quiet(dfa, state);
1440 +       perms.xindex = dfa_user_xindex(dfa, state);
1441 +
1442 +       return perms;
1443 +}
1444 +
1445 +static const char const *mnt_info_table[] = {
1446 +       "match succeeded",
1447 +       "failed mntpnt match",
1448 +       "failed srcname match",
1449 +       "failed type match",
1450 +       "failed flags match",
1451 +       "failed data match"
1452 +};
1453 +
1454 +/*
1455 + * Returns 0 on success else element that match failed in, this is the
1456 + * index into the mnt_info_table above
1457 + */
1458 +static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
1459 +                       const char *mntpnt, const char *devname,
1460 +                       const char *type, unsigned long flags,
1461 +                       void *data, bool binary, struct file_perms *perms)
1462 +{
1463 +       unsigned int state;
1464 +
1465 +       state = aa_dfa_match(dfa, start, mntpnt);
1466 +       state = aa_dfa_null_transition(dfa, state);
1467 +       if (!state)
1468 +               return 1;
1469 +
1470 +       if (devname)
1471 +               state = aa_dfa_match(dfa, state, devname);
1472 +       state = aa_dfa_null_transition(dfa, state);
1473 +       if (!state)
1474 +               return 2;
1475 +
1476 +       if (type)
1477 +               state = aa_dfa_match(dfa, state, type);
1478 +       state = aa_dfa_null_transition(dfa, state);
1479 +       if (!state)
1480 +               return 3;
1481 +
1482 +       state = match_mnt_flags(dfa, state, flags);
1483 +       if (!state)
1484 +               return 4;
1485 +       *perms = compute_mnt_perms(dfa, state);
1486 +       if (perms->allow & AA_MAY_MOUNT)
1487 +               return 0;
1488 +
1489 +       /* only match data if not binary and the DFA flags data is expected */
1490 +       if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
1491 +               state = aa_dfa_null_transition(dfa, state);
1492 +               if (!state)
1493 +                       return 4;
1494 +
1495 +               state = aa_dfa_match(dfa, state, data);
1496 +               if (!state)
1497 +                       return 5;
1498 +               *perms = compute_mnt_perms(dfa, state);
1499 +               if (perms->allow & AA_MAY_MOUNT)
1500 +                       return 0;
1501 +       }
1502 +
1503 +       /* failed at end of flags match */
1504 +       return 4;
1505 +}
1506 +
1507 +/**
1508 + * match_mnt - handle path matching for mount
1509 + * @profile: the confining profile
1510 + * @mntpnt: string for the mntpnt (NOT NULL)
1511 + * @devname: string for the devname/src_name (MAYBE NULL)
1512 + * @type: string for the dev type (MAYBE NULL)
1513 + * @flags: mount flags to match
1514 + * @data: fs mount data (MAYBE NULL)
1515 + * @binary: whether @data is binary
1516 + * @perms: Returns: permission found by the match
1517 + * @info: Returns: infomation string about the match for logging
1518 + *
1519 + * Returns: 0 on success else error
1520 + */
1521 +static int match_mnt(struct aa_profile *profile, const char *mntpnt,
1522 +                    const char *devname, const char *type,
1523 +                    unsigned long flags, void *data, bool binary,
1524 +                    struct file_perms *perms, const char **info)
1525 +{
1526 +       int pos;
1527 +
1528 +       if (!profile->policy.dfa)
1529 +               return -EACCES;
1530 +
1531 +       pos = do_match_mnt(profile->policy.dfa,
1532 +                          profile->policy.start[AA_CLASS_MOUNT],
1533 +                          mntpnt, devname, type, flags, data, binary, perms);
1534 +       if (pos) {
1535 +               *info = mnt_info_table[pos];
1536 +               return -EACCES;
1537 +       }
1538 +
1539 +       return 0;
1540 +}
1541 +
1542 +static int path_flags(struct aa_profile *profile, struct path *path)
1543 +{
1544 +       return profile->path_flags |
1545 +               S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
1546 +}
1547 +
1548 +int aa_remount(struct aa_profile *profile, struct path *path,
1549 +              unsigned long flags, void *data)
1550 +{
1551 +       struct file_perms perms = { };
1552 +       const char *name, *info = NULL;
1553 +       char *buffer = NULL;
1554 +       int binary, error;
1555 +
1556 +       binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
1557 +
1558 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1559 +                            &info);
1560 +       if (error)
1561 +               goto audit;
1562 +
1563 +       error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
1564 +                         &perms, &info);
1565 +
1566 +audit:
1567 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1568 +                           NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1569 +                           error);
1570 +       kfree(buffer);
1571 +
1572 +       return error;
1573 +}
1574 +
1575 +int aa_bind_mount(struct aa_profile *profile, struct path *path,
1576 +                 const char *dev_name, unsigned long flags)
1577 +{
1578 +       struct file_perms perms = { };
1579 +       char *buffer = NULL, *old_buffer = NULL;
1580 +       const char *name, *old_name = NULL, *info = NULL;
1581 +       struct path old_path;
1582 +       int error;
1583 +
1584 +       if (!dev_name || !*dev_name)
1585 +               return -EINVAL;
1586 +
1587 +       flags &= MS_REC | MS_BIND;
1588 +
1589 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1590 +                            &info);
1591 +       if (error)
1592 +               goto audit;
1593 +
1594 +       error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
1595 +       if (error)
1596 +               goto audit;
1597 +
1598 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
1599 +                            &old_buffer, &old_name, &info);
1600 +       path_put(&old_path);
1601 +       if (error)
1602 +               goto audit;
1603 +
1604 +       error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
1605 +                         &perms, &info);
1606 +
1607 +audit:
1608 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1609 +                           NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
1610 +                           info, error);
1611 +       kfree(buffer);
1612 +       kfree(old_buffer);
1613 +
1614 +       return error;
1615 +}
1616 +
1617 +int aa_mount_change_type(struct aa_profile *profile, struct path *path,
1618 +                        unsigned long flags)
1619 +{
1620 +       struct file_perms perms = { };
1621 +       char *buffer = NULL;
1622 +       const char *name, *info = NULL;
1623 +       int error;
1624 +
1625 +       /* These are the flags allowed by do_change_type() */
1626 +       flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
1627 +                 MS_UNBINDABLE);
1628 +
1629 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1630 +                            &info);
1631 +       if (error)
1632 +               goto audit;
1633 +
1634 +       error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
1635 +                         &info);
1636 +
1637 +audit:
1638 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
1639 +                           NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
1640 +                           error);
1641 +       kfree(buffer);
1642 +
1643 +       return error;
1644 +}
1645 +
1646 +int aa_move_mount(struct aa_profile *profile, struct path *path,
1647 +                 const char *orig_name)
1648 +{
1649 +       struct file_perms perms = { };
1650 +       char *buffer = NULL, *old_buffer = NULL;
1651 +       const char *name, *old_name = NULL, *info = NULL;
1652 +       struct path old_path;
1653 +       int error;
1654 +
1655 +       if (!orig_name || !*orig_name)
1656 +               return -EINVAL;
1657 +
1658 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1659 +                            &info);
1660 +       if (error)
1661 +               goto audit;
1662 +
1663 +       error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
1664 +       if (error)
1665 +               goto audit;
1666 +
1667 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
1668 +                            &old_buffer, &old_name, &info);
1669 +       path_put(&old_path);
1670 +       if (error)
1671 +               goto audit;
1672 +
1673 +       error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
1674 +                         &perms, &info);
1675 +
1676 +audit:
1677 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
1678 +                           NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
1679 +                           info, error);
1680 +       kfree(buffer);
1681 +       kfree(old_buffer);
1682 +
1683 +       return error;
1684 +}
1685 +
1686 +int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
1687 +                struct path *path, const char *type, unsigned long flags,
1688 +                void *data)
1689 +{
1690 +       struct file_perms perms = { };
1691 +       char *buffer = NULL, *dev_buffer = NULL;
1692 +       const char *name = NULL, *dev_name = NULL, *info = NULL;
1693 +       int binary = 1;
1694 +       int error;
1695 +
1696 +       dev_name = orig_dev_name;
1697 +       if (type) {
1698 +               int requires_dev;
1699 +               struct file_system_type *fstype = get_fs_type(type);
1700 +               if (!fstype)
1701 +                       return -ENODEV;
1702 +
1703 +               binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
1704 +               requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
1705 +               put_filesystem(fstype);
1706 +
1707 +               if (requires_dev) {
1708 +                       struct path dev_path;
1709 +
1710 +                       if (!dev_name || !*dev_name) {
1711 +                               error = -ENOENT;
1712 +                               goto out;
1713 +                       }
1714 +
1715 +                       error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
1716 +                       if (error)
1717 +                               goto audit;
1718 +
1719 +                       error = aa_path_name(&dev_path,
1720 +                                            path_flags(profile, &dev_path),
1721 +                                            &dev_buffer, &dev_name, &info);
1722 +                       path_put(&dev_path);
1723 +                       if (error)
1724 +                               goto audit;
1725 +               }
1726 +       }
1727 +
1728 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
1729 +                            &info);
1730 +       if (error)
1731 +               goto audit;
1732 +
1733 +       error = match_mnt(profile, name, dev_name, type, flags, data, binary,
1734 +                         &perms, &info);
1735 +
1736 +audit:
1737 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,  dev_name,
1738 +                           type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
1739 +                           error);
1740 +       kfree(buffer);
1741 +       kfree(dev_buffer);
1742 +
1743 +out:
1744 +       return error;
1745 +
1746 +}
1747 +
1748 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
1749 +{
1750 +       struct file_perms perms = { };
1751 +       char *buffer = NULL;
1752 +       const char *name, *info = NULL;
1753 +       int error;
1754 +
1755 +       struct path path = { mnt, mnt->mnt_root };
1756 +       error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
1757 +                            &info);
1758 +       if (error)
1759 +               goto audit;
1760 +
1761 +       if (!error && profile->policy.dfa) {
1762 +               unsigned int state;
1763 +               state = aa_dfa_match(profile->policy.dfa,
1764 +                                    profile->policy.start[AA_CLASS_MOUNT],
1765 +                                    name);
1766 +               perms = compute_mnt_perms(profile->policy.dfa, state);
1767 +       }
1768 +
1769 +       if (AA_MAY_UMOUNT & ~perms.allow)
1770 +               error = -EACCES;
1771 +
1772 +audit:
1773 +       error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
1774 +                           NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
1775 +       kfree(buffer);
1776 +
1777 +       return error;
1778 +}
1779 +
1780 +int aa_pivotroot(struct aa_profile *profile, struct path *old_path,
1781 +                 struct path *new_path)
1782 +{
1783 +       struct file_perms perms = { };
1784 +       struct aa_profile *target = NULL;
1785 +       char *old_buffer = NULL, *new_buffer = NULL;
1786 +       const char *old_name, *new_name = NULL, *info = NULL;
1787 +       int error;
1788 +
1789 +       error = aa_path_name(old_path, path_flags(profile, old_path),
1790 +                            &old_buffer, &old_name, &info);
1791 +       if (error)
1792 +               goto audit;
1793 +
1794 +       error = aa_path_name(new_path, path_flags(profile, new_path),
1795 +                            &new_buffer, &new_name, &info);
1796 +       if (error)
1797 +               goto audit;
1798 +
1799 +       if (profile->policy.dfa) {
1800 +               unsigned int state;
1801 +               state = aa_dfa_match(profile->policy.dfa,
1802 +                                    profile->policy.start[AA_CLASS_MOUNT],
1803 +                                    new_name);
1804 +               state = aa_dfa_null_transition(profile->policy.dfa, state);
1805 +               state = aa_dfa_match(profile->policy.dfa, state, old_name);
1806 +               perms = compute_mnt_perms(profile->policy.dfa, state);
1807 +       }
1808 +
1809 +       if (AA_MAY_PIVOTROOT & perms.allow) {
1810 +               if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
1811 +                       target = x_table_lookup(profile, perms.xindex);
1812 +                       if (!target)
1813 +                               error = -ENOENT;
1814 +                       else
1815 +                               error = aa_replace_current_profile(target);
1816 +               }
1817 +       } else
1818 +               error = -EACCES;
1819 +
1820 +audit:
1821 +       error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
1822 +                           old_name, NULL, target ? target->base.name : NULL,
1823 +                           0, NULL,  AA_MAY_PIVOTROOT, &perms, info, error);
1824 +       aa_put_profile(target);
1825 +       kfree(old_buffer);
1826 +       kfree(new_buffer);
1827 +
1828 +       return error;
1829 +}
1830 -- 
1831 1.7.7.6
1832
This page took 0.161845 seconds and 3 git commands to generate.