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