]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
- builds; imq updated; apparmor updated; zph dropped (unmaintained for few years)
[packages/kernel.git] / kernel-apparmor.patch
1 commit 5ea33f587f5f7324c40c5986286d0f38307923bb
2 Author: John Johansen <john.johansen@canonical.com>
3 Date:   Mon Apr 11 16:55:10 2016 -0700
4
5     apparmor: fix refcount bug in profile replacement
6     
7     Signed-off-by: John Johansen <john.johansen@canonical.com>
8     Acked-by: Seth Arnold <seth.arnold@canonical.com>
9
10 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
11 index 705c287..222052f 100644
12 --- a/security/apparmor/policy.c
13 +++ b/security/apparmor/policy.c
14 @@ -1189,12 +1189,12 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
15                                 aa_get_profile(newest);
16                                 aa_put_profile(parent);
17                                 rcu_assign_pointer(ent->new->parent, newest);
18 -                       } else
19 -                               aa_put_profile(newest);
20 +                       }
21                         /* aafs interface uses replacedby */
22                         rcu_assign_pointer(ent->new->replacedby->profile,
23                                            aa_get_profile(ent->new));
24                         __list_add_profile(&parent->base.profiles, ent->new);
25 +                       aa_put_profile(newest);
26                 } else {
27                         /* aafs interface uses replacedby */
28                         rcu_assign_pointer(ent->new->replacedby->profile,
29
30 commit f65b1c9b72442e6166332c04f332e4b4d4797887
31 Author: John Johansen <john.johansen@canonical.com>
32 Date:   Mon Apr 11 16:57:19 2016 -0700
33
34     apparmor: fix replacement bug that adds new child to old parent
35     
36     When set atomic replacement is used and the parent is updated before the
37     child, and the child did not exist in the old parent so there is no
38     direct replacement then the new child is incorrectly added to the old
39     parent. This results in the new parent not having the child(ren) that
40     it should and the old parent when being destroyed asserting the
41     following error.
42     
43     AppArmor: policy_destroy: internal error, policy '<profile/name>' still
44     contains profiles
45     
46     Signed-off-by: John Johansen <john.johansen@canonical.com>
47     Acked-by: Seth Arnold <seth.arnold@canonical.com>
48
49 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
50 index 222052f..c92a9f6 100644
51 --- a/security/apparmor/policy.c
52 +++ b/security/apparmor/policy.c
53 @@ -1193,7 +1193,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
54                         /* aafs interface uses replacedby */
55                         rcu_assign_pointer(ent->new->replacedby->profile,
56                                            aa_get_profile(ent->new));
57 -                       __list_add_profile(&parent->base.profiles, ent->new);
58 +                       __list_add_profile(&newest->base.profiles, ent->new);
59                         aa_put_profile(newest);
60                 } else {
61                         /* aafs interface uses replacedby */
62
63 commit b6669bef20c9d934bc6498e79fffa220f6226518
64 Author: John Johansen <john.johansen@canonical.com>
65 Date:   Sun Jun 8 11:20:54 2014 -0700
66
67     apparmor: fix uninitialized lsm_audit member
68     
69     BugLink: http://bugs.launchpad.net/bugs/1268727
70     
71     The task field in the lsm_audit struct needs to be initialized if
72     a change_hat fails, otherwise the following oops will occur
73     
74     BUG: unable to handle kernel paging request at 0000002fbead7d08
75     IP: [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
76     PGD 1e3f35067 PUD 0
77     Oops: 0002 [#1] SMP
78     Modules linked in: pppox crc_ccitt p8023 p8022 psnap llc ax25 btrfs raid6_pq xor xfs libcrc32c dm_multipath scsi_dh kvm_amd dcdbas kvm microcode amd64_edac_mod joydev edac_core psmouse edac_mce_amd serio_raw k10temp sp5100_tco i2c_piix4 ipmi_si ipmi_msghandler acpi_power_meter mac_hid lp parport hid_generic usbhid hid pata_acpi mpt2sas ahci raid_class pata_atiixp bnx2 libahci scsi_transport_sas [last unloaded: tipc]
79     CPU: 2 PID: 699 Comm: changehat_twice Tainted: GF          O 3.13.0-7-generic #25-Ubuntu
80     Hardware name: Dell Inc. PowerEdge R415/08WNM9, BIOS 1.8.6 12/06/2011
81     task: ffff8802135c6000 ti: ffff880212986000 task.ti: ffff880212986000
82     RIP: 0010:[<ffffffff8171153e>]  [<ffffffff8171153e>] _raw_spin_lock+0xe/0x50
83     RSP: 0018:ffff880212987b68  EFLAGS: 00010006
84     RAX: 0000000000020000 RBX: 0000002fbead7500 RCX: 0000000000000000
85     RDX: 0000000000000292 RSI: ffff880212987ba8 RDI: 0000002fbead7d08
86     RBP: ffff880212987b68 R08: 0000000000000246 R09: ffff880216e572a0
87     R10: ffffffff815fd677 R11: ffffea0008469580 R12: ffffffff8130966f
88     R13: ffff880212987ba8 R14: 0000002fbead7d08 R15: ffff8800d8c6b830
89     FS:  00002b5e6c84e7c0(0000) GS:ffff880216e40000(0000) knlGS:0000000055731700
90     CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
91     CR2: 0000002fbead7d08 CR3: 000000021270f000 CR4: 00000000000006e0
92     Stack:
93      ffff880212987b98 ffffffff81075f17 ffffffff8130966f 0000000000000009
94      0000000000000000 0000000000000000 ffff880212987bd0 ffffffff81075f7c
95      0000000000000292 ffff880212987c08 ffff8800d8c6b800 0000000000000026
96     Call Trace:
97      [<ffffffff81075f17>] __lock_task_sighand+0x47/0x80
98      [<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
99      [<ffffffff81075f7c>] do_send_sig_info+0x2c/0x80
100      [<ffffffff81075fee>] send_sig_info+0x1e/0x30
101      [<ffffffff8130242d>] aa_audit+0x13d/0x190
102      [<ffffffff8130c1dc>] aa_audit_file+0xbc/0x130
103      [<ffffffff8130966f>] ? apparmor_cred_prepare+0x2f/0x50
104      [<ffffffff81304cc2>] aa_change_hat+0x202/0x530
105      [<ffffffff81308fc6>] aa_setprocattr_changehat+0x116/0x1d0
106      [<ffffffff8130a11d>] apparmor_setprocattr+0x25d/0x300
107      [<ffffffff812cee56>] security_setprocattr+0x16/0x20
108      [<ffffffff8121fc87>] proc_pid_attr_write+0x107/0x130
109      [<ffffffff811b7604>] vfs_write+0xb4/0x1f0
110      [<ffffffff811b8039>] SyS_write+0x49/0xa0
111      [<ffffffff8171a1bf>] tracesys+0xe1/0xe6
112     
113     Signed-off-by: John Johansen <john.johansen@canonical.com>
114     Acked-by: Seth Arnold <seth.arnold@canonical.com>
115
116 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
117 index 89c7865..3a7f1da 100644
118 --- a/security/apparmor/audit.c
119 +++ b/security/apparmor/audit.c
120 @@ -200,7 +200,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
121  
122         if (sa->aad->type == AUDIT_APPARMOR_KILL)
123                 (void)send_sig_info(SIGKILL, NULL,
124 -                                   sa->u.tsk ?  sa->u.tsk : current);
125 +                       sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
126 +                                   sa->u.tsk : current);
127  
128         if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
129                 return complain_error(sa->aad->error);
130 diff --git a/security/apparmor/file.c b/security/apparmor/file.c
131 index d186674..4d2af4b 100644
132 --- a/security/apparmor/file.c
133 +++ b/security/apparmor/file.c
134 @@ -110,7 +110,8 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
135         int type = AUDIT_APPARMOR_AUTO;
136         struct common_audit_data sa;
137         struct apparmor_audit_data aad = {0,};
138 -       sa.type = LSM_AUDIT_DATA_NONE;
139 +       sa.type = LSM_AUDIT_DATA_TASK;
140 +       sa.u.tsk = NULL;
141         sa.aad = &aad;
142         aad.op = op,
143         aad.fs.request = request;
144
145 commit aeab4cbfb86d0faeeb709e8201672e0662aa2c6f
146 Author: John Johansen <john.johansen@canonical.com>
147 Date:   Fri Jul 25 04:02:03 2014 -0700
148
149     apparmor: exec should not be returning ENOENT when it denies
150     
151     The current behavior is confusing as it causes exec failures to report
152     the executable is missing instead of identifying that apparmor
153     caused the failure.
154     
155     Signed-off-by: John Johansen <john.johansen@canonical.com>
156     Acked-by: Seth Arnold <seth.arnold@canonical.com>
157
158 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
159 index dc0027b..67a7418 100644
160 --- a/security/apparmor/domain.c
161 +++ b/security/apparmor/domain.c
162 @@ -433,7 +433,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
163                                 new_profile = aa_get_newest_profile(ns->unconfined);
164                                 info = "ux fallback";
165                         } else {
166 -                               error = -ENOENT;
167 +                               error = -EACCES;
168                                 info = "profile not found";
169                                 /* remove MAY_EXEC to audit as failure */
170                                 perms.allow &= ~MAY_EXEC;
171
172 commit 752e4263021d90cf23c262f2fd3ebfd6dbccd455
173 Author: John Johansen <john.johansen@canonical.com>
174 Date:   Fri Jul 25 04:01:56 2014 -0700
175
176     apparmor: fix update the mtime of the profile file on replacement
177     
178     Signed-off-by: John Johansen <john.johansen@canonical.com>
179     Acked-by: Seth Arnold <seth.arnold@canonical.com>
180
181 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
182 index ad4fa49..45a6199 100644
183 --- a/security/apparmor/apparmorfs.c
184 +++ b/security/apparmor/apparmorfs.c
185 @@ -379,6 +379,8 @@ void __aa_fs_profile_migrate_dents(struct aa_profile *old,
186  
187         for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
188                 new->dents[i] = old->dents[i];
189 +               if (new->dents[i])
190 +                       new->dents[i]->d_inode->i_mtime = CURRENT_TIME;
191                 old->dents[i] = NULL;
192         }
193  }
194
195 commit 0c67233b18406dc7a8629faf8f9452feace6fb13
196 Author: John Johansen <john.johansen@canonical.com>
197 Date:   Fri Jul 25 04:02:08 2014 -0700
198
199     apparmor: fix disconnected bind mnts reconnection
200     
201     Bind mounts can fail to be properly reconnected when PATH_CONNECT is
202     specified. Ensure that when PATH_CONNECT is specified the path has
203     a root.
204     
205     BugLink: http://bugs.launchpad.net/bugs/1319984
206     
207     Signed-off-by: John Johansen <john.johansen@canonical.com>
208     Acked-by: Seth Arnold <seth.arnold@canonical.com>
209
210 diff --git a/security/apparmor/path.c b/security/apparmor/path.c
211 index edddc02..f261678 100644
212 --- a/security/apparmor/path.c
213 +++ b/security/apparmor/path.c
214 @@ -141,7 +141,10 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen,
215                         error = -EACCES;
216                         if (*res == '/')
217                                 *name = res + 1;
218 -               }
219 +               } else if (*res != '/')
220 +                       /* CONNECT_PATH with missing root */
221 +                       error = prepend(name, *name - buf, "/", 1);
222 +
223         }
224  
225  out:
226
227 commit 30c2b759b4f456e97e859ca550666c8abe84ff3c
228 Author: John Johansen <john.johansen@canonical.com>
229 Date:   Fri Jul 25 04:02:10 2014 -0700
230
231     apparmor: internal paths should be treated as disconnected
232     
233     Internal mounts are not mounted anywhere and as such should be treated
234     as disconnected paths.
235     
236     Signed-off-by: John Johansen <john.johansen@canonical.com>
237     Acked-by: Seth Arnold <seth.arnold@canonical.com>
238
239 diff --git a/security/apparmor/path.c b/security/apparmor/path.c
240 index f261678..a8fc7d0 100644
241 --- a/security/apparmor/path.c
242 +++ b/security/apparmor/path.c
243 @@ -25,7 +25,6 @@
244  #include "include/path.h"
245  #include "include/policy.h"
246  
247 -
248  /* modified from dcache.c */
249  static int prepend(char **buffer, int buflen, const char *str, int namelen)
250  {
251 @@ -39,6 +38,38 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen)
252  
253  #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
254  
255 +/* If the path is not connected to the expected root,
256 + * check if it is a sysctl and handle specially else remove any
257 + * leading / that __d_path may have returned.
258 + * Unless
259 + *     specifically directed to connect the path,
260 + * OR
261 + *     if in a chroot and doing chroot relative paths and the path
262 + *     resolves to the namespace root (would be connected outside
263 + *     of chroot) and specifically directed to connect paths to
264 + *     namespace root.
265 + */
266 +static int disconnect(const struct path *path, char *buf, char **name,
267 +                     int flags)
268 +{
269 +       int error = 0;
270 +
271 +       if (!(flags & PATH_CONNECT_PATH) &&
272 +           !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
273 +             our_mnt(path->mnt))) {
274 +               /* disconnected path, don't return pathname starting
275 +                * with '/'
276 +                */
277 +               error = -EACCES;
278 +               if (**name == '/')
279 +                       *name = *name + 1;
280 +       } else if (**name != '/')
281 +               /* CONNECT_PATH with missing root */
282 +               error = prepend(name, *name - buf, "/", 1);
283 +
284 +       return error;
285 +}
286 +
287  /**
288   * d_namespace_path - lookup a name associated with a given path
289   * @path: path to lookup  (NOT NULL)
290 @@ -74,7 +105,8 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen,
291                          * control instead of hard coded /proc
292                          */
293                         return prepend(name, *name - buf, "/proc", 5);
294 -               }
295 +               } else
296 +                       return disconnect(path, buf, name, flags);
297                 return 0;
298         }
299  
300 @@ -120,32 +152,8 @@ static int d_namespace_path(const struct path *path, char *buf, int buflen,
301                         goto out;
302         }
303  
304 -       /* If the path is not connected to the expected root,
305 -        * check if it is a sysctl and handle specially else remove any
306 -        * leading / that __d_path may have returned.
307 -        * Unless
308 -        *     specifically directed to connect the path,
309 -        * OR
310 -        *     if in a chroot and doing chroot relative paths and the path
311 -        *     resolves to the namespace root (would be connected outside
312 -        *     of chroot) and specifically directed to connect paths to
313 -        *     namespace root.
314 -        */
315 -       if (!connected) {
316 -               if (!(flags & PATH_CONNECT_PATH) &&
317 -                          !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
318 -                            our_mnt(path->mnt))) {
319 -                       /* disconnected path, don't return pathname starting
320 -                        * with '/'
321 -                        */
322 -                       error = -EACCES;
323 -                       if (*res == '/')
324 -                               *name = res + 1;
325 -               } else if (*res != '/')
326 -                       /* CONNECT_PATH with missing root */
327 -                       error = prepend(name, *name - buf, "/", 1);
328 -
329 -       }
330 +       if (!connected)
331 +               error = disconnect(path, buf, name, flags);
332  
333  out:
334         return error;
335
336 commit 35f89b597a40c870f93a068bc92a7ef4f9b16a66
337 Author: John Johansen <john.johansen@canonical.com>
338 Date:   Sat Apr 16 13:59:02 2016 -0700
339
340     apparmor: fix put() parent ref after updating the active ref
341     
342     Signed-off-by: John Johansen <john.johansen@canonical.com>
343     Acked-by: Seth Arnold <seth.arnold@canonical.com>
344
345 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
346 index c92a9f6..455c9f8 100644
347 --- a/security/apparmor/policy.c
348 +++ b/security/apparmor/policy.c
349 @@ -1187,8 +1187,8 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
350                         /* parent replaced in this atomic set? */
351                         if (newest != parent) {
352                                 aa_get_profile(newest);
353 -                               aa_put_profile(parent);
354                                 rcu_assign_pointer(ent->new->parent, newest);
355 +                               aa_put_profile(parent);
356                         }
357                         /* aafs interface uses replacedby */
358                         rcu_assign_pointer(ent->new->replacedby->profile,
359
360 commit 7b1ec6a04ca57fabe250f1102f2803dea7fbd03b
361 Author: John Johansen <john.johansen@canonical.com>
362 Date:   Sat Apr 16 14:16:50 2016 -0700
363
364     apparmor: fix log failures for all profiles in a set
365     
366     currently only the profile that is causing the failure is logged. This
367     makes it more confusing than necessary about which profiles loaded
368     and which didn't. So make sure to log success and failure messages for
369     all profiles in the set being loaded.
370     
371     Signed-off-by: John Johansen <john.johansen@canonical.com>
372     Acked-by: Seth Arnold <seth.arnold@canonical.com>
373
374 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
375 index 455c9f8..db31bc5 100644
376 --- a/security/apparmor/policy.c
377 +++ b/security/apparmor/policy.c
378 @@ -1067,7 +1067,7 @@ static int __lookup_replace(struct aa_namespace *ns, const char *hname,
379   */
380  ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
381  {
382 -       const char *ns_name, *name = NULL, *info = NULL;
383 +       const char *ns_name, *info = NULL;
384         struct aa_namespace *ns = NULL;
385         struct aa_load_ent *ent, *tmp;
386         int op = OP_PROF_REPL;
387 @@ -1082,18 +1082,15 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
388         /* released below */
389         ns = aa_prepare_namespace(ns_name);
390         if (!ns) {
391 -               info = "failed to prepare namespace";
392 -               error = -ENOMEM;
393 -               name = ns_name;
394 -               goto fail;
395 +               error = audit_policy(op, GFP_KERNEL, ns_name,
396 +                                    "failed to prepare namespace", -ENOMEM);
397 +               goto free;
398         }
399  
400         mutex_lock(&ns->lock);
401         /* setup parent and ns info */
402         list_for_each_entry(ent, &lh, list) {
403                 struct aa_policy *policy;
404 -
405 -               name = ent->new->base.hname;
406                 error = __lookup_replace(ns, ent->new->base.hname, noreplace,
407                                          &ent->old, &info);
408                 if (error)
409 @@ -1121,7 +1118,6 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
410                         if (!p) {
411                                 error = -ENOENT;
412                                 info = "parent does not exist";
413 -                               name = ent->new->base.hname;
414                                 goto fail_lock;
415                         }
416                         rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
417 @@ -1214,9 +1210,22 @@ out:
418  
419  fail_lock:
420         mutex_unlock(&ns->lock);
421 -fail:
422 -       error = audit_policy(op, GFP_KERNEL, name, info, error);
423  
424 +       /* audit cause of failure */
425 +       op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
426 +       audit_policy(op, GFP_KERNEL, ent->new->base.hname, info, error);
427 +       /* audit status that rest of profiles in the atomic set failed too */
428 +       info = "valid profile in failed atomic policy load";
429 +       list_for_each_entry(tmp, &lh, list) {
430 +               if (tmp == ent) {
431 +                       info = "unchecked profile in failed atomic policy load";
432 +                       /* skip entry that caused failure */
433 +                       continue;
434 +               }
435 +               op = (!ent->old) ? OP_PROF_LOAD : OP_PROF_REPL;
436 +               audit_policy(op, GFP_KERNEL, tmp->new->base.hname, info, error);
437 +       }
438 +free:
439         list_for_each_entry_safe(ent, tmp, &lh, list) {
440                 list_del_init(&ent->list);
441                 aa_load_ent_free(ent);
442
443 commit 4c475747a31b0637f0d47cb9bddaf2c6efb02854
444 Author: John Johansen <john.johansen@canonical.com>
445 Date:   Sat Apr 16 14:19:38 2016 -0700
446
447     apparmor: fix audit full profile hname on successful load
448     
449     Currently logging of a successful profile load only logs the basename
450     of the profile. This can result in confusion when a child profile has
451     the same name as the another profile in the set. Logging the hname
452     will ensure there is no confusion.
453     
454     Signed-off-by: John Johansen <john.johansen@canonical.com>
455     Acked-by: Seth Arnold <seth.arnold@canonical.com>
456
457 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
458 index db31bc5..ca402d0 100644
459 --- a/security/apparmor/policy.c
460 +++ b/security/apparmor/policy.c
461 @@ -1159,7 +1159,7 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
462                 list_del_init(&ent->list);
463                 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
464  
465 -               audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
466 +               audit_policy(op, GFP_ATOMIC, ent->new->base.hname, NULL, error);
467  
468                 if (ent->old) {
469                         __replace_profile(ent->old, ent->new, 1);
470
471 commit 430741dd766291d2e618b04e918ee6da844c230a
472 Author: John Johansen <john.johansen@canonical.com>
473 Date:   Wed Apr 20 14:18:18 2016 -0700
474
475     apparmor: ensure the target profile name is always audited
476     
477     The target profile name was not being correctly audited in a few
478     cases because the target variable was not being set and gotos
479     passed the code to set it at apply:
480     
481     Since it is always based on new_profile just drop the target var
482     and conditionally report based on new_profile.
483     
484     Signed-off-by: John Johansen <john.johansen@canonical.com>
485     Acked-by: Seth Arnold <seth.arnold@canonical.com>
486
487 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
488 index 67a7418..fc3036b 100644
489 --- a/security/apparmor/domain.c
490 +++ b/security/apparmor/domain.c
491 @@ -346,7 +346,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
492                 file_inode(bprm->file)->i_uid,
493                 file_inode(bprm->file)->i_mode
494         };
495 -       const char *name = NULL, *target = NULL, *info = NULL;
496 +       const char *name = NULL, *info = NULL;
497         int error = 0;
498  
499         if (bprm->cred_prepared)
500 @@ -399,6 +399,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
501         if (cxt->onexec) {
502                 struct file_perms cp;
503                 info = "change_profile onexec";
504 +               new_profile = aa_get_newest_profile(cxt->onexec);
505                 if (!(perms.allow & AA_MAY_ONEXEC))
506                         goto audit;
507  
508 @@ -413,7 +414,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
509  
510                 if (!(cp.allow & AA_MAY_ONEXEC))
511                         goto audit;
512 -               new_profile = aa_get_newest_profile(cxt->onexec);
513                 goto apply;
514         }
515  
516 @@ -445,10 +445,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
517                 if (!new_profile) {
518                         error = -ENOMEM;
519                         info = "could not create null profile";
520 -               } else {
521 +               } else
522                         error = -EACCES;
523 -                       target = new_profile->base.hname;
524 -               }
525                 perms.xindex |= AA_X_UNSAFE;
526         } else
527                 /* fail exec */
528 @@ -459,7 +457,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
529          * fail the exec.
530          */
531         if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
532 -               aa_put_profile(new_profile);
533                 error = -EPERM;
534                 goto cleanup;
535         }
536 @@ -474,10 +471,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
537  
538         if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
539                 error = may_change_ptraced_domain(new_profile);
540 -               if (error) {
541 -                       aa_put_profile(new_profile);
542 +               if (error)
543                         goto audit;
544 -               }
545         }
546  
547         /* Determine if secure exec is needed.
548 @@ -498,7 +493,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
549                 bprm->unsafe |= AA_SECURE_X_NEEDED;
550         }
551  apply:
552 -       target = new_profile->base.hname;
553         /* when transitioning profiles clear unsafe personality bits */
554         bprm->per_clear |= PER_CLEAR_ON_SETID;
555  
556 @@ -506,15 +500,19 @@ x_clear:
557         aa_put_profile(cxt->profile);
558         /* transfer new profile reference will be released when cxt is freed */
559         cxt->profile = new_profile;
560 +       new_profile = NULL;
561  
562         /* clear out all temporary/transitional state from the context */
563         aa_clear_task_cxt_trans(cxt);
564  
565  audit:
566         error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
567 -                             name, target, cond.uid, info, error);
568 +                             name,
569 +                             new_profile ? new_profile->base.hname : NULL,
570 +                             cond.uid, info, error);
571  
572  cleanup:
573 +       aa_put_profile(new_profile);
574         aa_put_profile(profile);
575         kfree(buffer);
576  
577
578 commit 06763d057300b3d5bbe1894acfe236cf193bab78
579 Author: John Johansen <john.johansen@canonical.com>
580 Date:   Thu Mar 17 12:02:54 2016 -0700
581
582     apparmor: check that xindex is in trans_table bounds
583     
584     Signed-off-by: John Johansen <john.johansen@canonical.com>
585     Acked-by: Seth Arnold <seth.arnold@canonical.com>
586
587 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
588 index a689f10..c841b12 100644
589 --- a/security/apparmor/policy_unpack.c
590 +++ b/security/apparmor/policy_unpack.c
591 @@ -676,7 +676,7 @@ static bool verify_xindex(int xindex, int table_size)
592         int index, xtype;
593         xtype = xindex & AA_X_TYPE_MASK;
594         index = xindex & AA_X_INDEX_MASK;
595 -       if (xtype == AA_X_TABLE && index > table_size)
596 +       if (xtype == AA_X_TABLE && index >= table_size)
597                 return 0;
598         return 1;
599  }
600
601 commit 9ad29b2e7820895339f90eb71b411d0134cf1ce9
602 Author: John Johansen <john.johansen@canonical.com>
603 Date:   Wed Nov 18 11:41:05 2015 -0800
604
605     apparmor: fix ref count leak when profile sha1 hash is read
606     
607     Signed-off-by: John Johansen <john.johansen@canonical.com>
608     Acked-by: Seth Arnold <seth.arnold@canonical.com>
609
610 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
611 index 45a6199..0d8dd71 100644
612 --- a/security/apparmor/apparmorfs.c
613 +++ b/security/apparmor/apparmorfs.c
614 @@ -331,6 +331,7 @@ static int aa_fs_seq_hash_show(struct seq_file *seq, void *v)
615                         seq_printf(seq, "%.2x", profile->hash[i]);
616                 seq_puts(seq, "\n");
617         }
618 +       aa_put_profile(profile);
619  
620         return 0;
621  }
622
623 commit e13f968d154ba9d6a2c4f82f33d3312a63430b54
624 Author: John Johansen <john.johansen@canonical.com>
625 Date:   Wed Dec 16 18:09:10 2015 -0800
626
627     apparmor: fix refcount race when finding a child profile
628     
629     When finding a child profile via an rcu critical section, the profile
630     may be put and scheduled for deletion after the child is found but
631     before its refcount is incremented.
632     
633     Protect against this by repeating the lookup if the profiles refcount
634     is 0 and is one its way to deletion.
635     
636     Signed-off-by: John Johansen <john.johansen@canonical.com>
637     Acked-by: Seth Arnold <seth.arnold@canonical.com>
638
639 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
640 index ca402d0..7807125 100644
641 --- a/security/apparmor/policy.c
642 +++ b/security/apparmor/policy.c
643 @@ -766,7 +766,9 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
644         struct aa_profile *profile;
645  
646         rcu_read_lock();
647 -       profile = aa_get_profile(__find_child(&parent->base.profiles, name));
648 +       do {
649 +               profile = __find_child(&parent->base.profiles, name);
650 +       } while (profile && !aa_get_profile_not0(profile));
651         rcu_read_unlock();
652  
653         /* refcount released by caller */
654
655 commit 5833ccff1227fbc8f1bab64351f6747a6c71bdeb
656 Author: Geliang Tang <geliangtang@163.com>
657 Date:   Mon Nov 16 21:46:33 2015 +0800
658
659     apparmor: use list_next_entry instead of list_entry_next
660     
661     list_next_entry has been defined in list.h, so I replace list_entry_next
662     with it.
663     
664     Signed-off-by: Geliang Tang <geliangtang@163.com>
665     Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
666     Signed-off-by: John Johansen <john.johansen@canonical.com>
667
668 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
669 index 0d8dd71..729e595 100644
670 --- a/security/apparmor/apparmorfs.c
671 +++ b/security/apparmor/apparmorfs.c
672 @@ -553,8 +553,6 @@ fail2:
673  }
674  
675  
676 -#define list_entry_next(pos, member) \
677 -       list_entry(pos->member.next, typeof(*pos), member)
678  #define list_entry_is_head(pos, head, member) (&pos->member == (head))
679  
680  /**
681 @@ -585,7 +583,7 @@ static struct aa_namespace *__next_namespace(struct aa_namespace *root,
682         parent = ns->parent;
683         while (ns != root) {
684                 mutex_unlock(&ns->lock);
685 -               next = list_entry_next(ns, base.list);
686 +               next = list_next_entry(ns, base.list);
687                 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
688                         mutex_lock(&next->lock);
689                         return next;
690 @@ -639,7 +637,7 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
691         parent = rcu_dereference_protected(p->parent,
692                                            mutex_is_locked(&p->ns->lock));
693         while (parent) {
694 -               p = list_entry_next(p, base.list);
695 +               p = list_next_entry(p, base.list);
696                 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
697                         return p;
698                 p = parent;
699 @@ -648,7 +646,7 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
700         }
701  
702         /* is next another profile in the namespace */
703 -       p = list_entry_next(p, base.list);
704 +       p = list_next_entry(p, base.list);
705         if (!list_entry_is_head(p, &ns->base.profiles, base.list))
706                 return p;
707  
708
709 commit 645801f1ddd183109c011e5ecee23ed3fdcae244
710 Author: Jeff Mahoney <jeffm@suse.com>
711 Date:   Fri Nov 6 15:17:30 2015 -0500
712
713     apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task
714     
715     While using AppArmor, SYS_CAP_RESOURCE is insufficient to call prlimit
716     on another task. The only other example of a AppArmor mediating access to
717     another, already running, task (ignoring fork+exec) is ptrace.
718     
719     The AppArmor model for ptrace is that one of the following must be true:
720     1) The tracer is unconfined
721     2) The tracer is in complain mode
722     3) The tracer and tracee are confined by the same profile
723     4) The tracer is confined but has SYS_CAP_PTRACE
724     
725     1), 2, and 3) are already true for setrlimit.
726     
727     We can match the ptrace model just by allowing CAP_SYS_RESOURCE.
728     
729     We still test the values of the rlimit since it can always be overridden
730     using a value that means unlimited for a particular resource.
731     
732     Signed-off-by: Jeff Mahoney <jeffm@suse.com>
733     Signed-off-by: John Johansen <john.johansen@canonical.com>
734
735 diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
736 index 748bf0c..67a6072 100644
737 --- a/security/apparmor/resource.c
738 +++ b/security/apparmor/resource.c
739 @@ -101,9 +101,11 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task,
740         /* TODO: extend resource control to handle other (non current)
741          * profiles.  AppArmor rules currently have the implicit assumption
742          * that the task is setting the resource of a task confined with
743 -        * the same profile.
744 +        * the same profile or that the task setting the resource of another
745 +        * task has CAP_SYS_RESOURCE.
746          */
747 -       if (profile != task_profile ||
748 +       if ((profile != task_profile &&
749 +            aa_capable(profile, CAP_SYS_RESOURCE, 1)) ||
750             (profile->rlimits.mask & (1 << resource) &&
751              new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max))
752                 error = -EACCES;
753
754 commit 2be4aed1f3332d87273eb593944332054f3cffac
755 Author: John Johansen <john.johansen@canonical.com>
756 Date:   Thu Jun 2 02:37:02 2016 -0700
757
758     apparmor: add missing id bounds check on dfa verification
759     
760     Signed-off-by: John Johansen <john.johansen@canonical.com>
761
762 diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
763 index 001c43a..a1c04fe 100644
764 --- a/security/apparmor/include/match.h
765 +++ b/security/apparmor/include/match.h
766 @@ -62,6 +62,7 @@ struct table_set_header {
767  #define YYTD_ID_ACCEPT2 6
768  #define YYTD_ID_NXT    7
769  #define YYTD_ID_TSIZE  8
770 +#define YYTD_ID_MAX    8
771  
772  #define YYTD_DATA8     1
773  #define YYTD_DATA16    2
774 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
775 index 727eb42..f9f57c6 100644
776 --- a/security/apparmor/match.c
777 +++ b/security/apparmor/match.c
778 @@ -47,6 +47,8 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
779          * it every time we use td_id as an index
780          */
781         th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
782 +       if (th.td_id > YYTD_ID_MAX)
783 +               goto out;
784         th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
785         th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
786         blob += sizeof(struct table_header);
787
788 commit c7f87d3c3363b1a0c4724e627e5c8e640a883c89
789 Author: John Johansen <john.johansen@canonical.com>
790 Date:   Wed Jun 15 09:57:55 2016 +0300
791
792     apparmor: don't check for vmalloc_addr if kvzalloc() failed
793     
794     Signed-off-by: John Johansen <john.johansen@canonical.com>
795
796 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
797 index f9f57c6..32b72eb 100644
798 --- a/security/apparmor/match.c
799 +++ b/security/apparmor/match.c
800 @@ -75,14 +75,14 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
801                                      u32, be32_to_cpu);
802                 else
803                         goto fail;
804 +               /* if table was vmalloced make sure the page tables are synced
805 +                * before it is used, as it goes live to all cpus.
806 +                */
807 +               if (is_vmalloc_addr(table))
808 +                       vm_unmap_aliases();
809         }
810  
811  out:
812 -       /* if table was vmalloced make sure the page tables are synced
813 -        * before it is used, as it goes live to all cpus.
814 -        */
815 -       if (is_vmalloc_addr(table))
816 -               vm_unmap_aliases();
817         return table;
818  fail:
819         kvfree(table);
820
821 commit 0f7e61013dd1e67ebb54d58eee11ab009ceb5ef3
822 Author: John Johansen <john.johansen@canonical.com>
823 Date:   Wed Jun 15 10:00:55 2016 +0300
824
825     apparmor: fix oops in profile_unpack() when policy_db is not present
826     
827     BugLink: http://bugs.launchpad.net/bugs/1592547
828     
829     If unpack_dfa() returns NULL due to the dfa not being present,
830     profile_unpack() is not checking if the dfa is not present (NULL).
831     
832     Signed-off-by: John Johansen <john.johansen@canonical.com>
833
834 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
835 index c841b12..dac2121 100644
836 --- a/security/apparmor/policy_unpack.c
837 +++ b/security/apparmor/policy_unpack.c
838 @@ -583,6 +583,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
839                         error = PTR_ERR(profile->policy.dfa);
840                         profile->policy.dfa = NULL;
841                         goto fail;
842 +               } else if (!profile->policy.dfa) {
843 +                       error = -EPROTO;
844 +                       goto fail;
845                 }
846                 if (!unpack_u32(e, &profile->policy.start[0], "start"))
847                         /* default start state */
848
849 commit de4ca46ec035283928e8fa40797897cefcf6ec3e
850 Author: John Johansen <john.johansen@canonical.com>
851 Date:   Wed Jun 22 18:01:08 2016 -0700
852
853     apparmor: fix module parameters can be changed after policy is locked
854     
855     the policy_lock parameter is a one way switch that prevents policy
856     from being further modified. Unfortunately some of the module parameters
857     can effectively modify policy by turning off enforcement.
858     
859     split policy_admin_capable into a view check and a full admin check,
860     and update the admin check to test the policy_lock parameter.
861     
862     Signed-off-by: John Johansen <john.johansen@canonical.com>
863
864 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
865 index c28b0f2..52275f0 100644
866 --- a/security/apparmor/include/policy.h
867 +++ b/security/apparmor/include/policy.h
868 @@ -403,6 +403,8 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
869         return profile->audit;
870  }
871  
872 +bool policy_view_capable(void);
873 +bool policy_admin_capable(void);
874  bool aa_may_manage_policy(int op);
875  
876  #endif /* __AA_POLICY_H */
877 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
878 index 7798e16..e83eefb 100644
879 --- a/security/apparmor/lsm.c
880 +++ b/security/apparmor/lsm.c
881 @@ -728,51 +728,49 @@ __setup("apparmor=", apparmor_enabled_setup);
882  /* set global flag turning off the ability to load policy */
883  static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp)
884  {
885 -       if (!capable(CAP_MAC_ADMIN))
886 +       if (!policy_admin_capable())
887                 return -EPERM;
888 -       if (aa_g_lock_policy)
889 -               return -EACCES;
890         return param_set_bool(val, kp);
891  }
892  
893  static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp)
894  {
895 -       if (!capable(CAP_MAC_ADMIN))
896 +       if (!policy_view_capable())
897                 return -EPERM;
898         return param_get_bool(buffer, kp);
899  }
900  
901  static int param_set_aabool(const char *val, const struct kernel_param *kp)
902  {
903 -       if (!capable(CAP_MAC_ADMIN))
904 +       if (!policy_admin_capable())
905                 return -EPERM;
906         return param_set_bool(val, kp);
907  }
908  
909  static int param_get_aabool(char *buffer, const struct kernel_param *kp)
910  {
911 -       if (!capable(CAP_MAC_ADMIN))
912 +       if (!policy_view_capable())
913                 return -EPERM;
914         return param_get_bool(buffer, kp);
915  }
916  
917  static int param_set_aauint(const char *val, const struct kernel_param *kp)
918  {
919 -       if (!capable(CAP_MAC_ADMIN))
920 +       if (!policy_admin_capable())
921                 return -EPERM;
922         return param_set_uint(val, kp);
923  }
924  
925  static int param_get_aauint(char *buffer, const struct kernel_param *kp)
926  {
927 -       if (!capable(CAP_MAC_ADMIN))
928 +       if (!policy_view_capable())
929                 return -EPERM;
930         return param_get_uint(buffer, kp);
931  }
932  
933  static int param_get_audit(char *buffer, struct kernel_param *kp)
934  {
935 -       if (!capable(CAP_MAC_ADMIN))
936 +       if (!policy_view_capable())
937                 return -EPERM;
938  
939         if (!apparmor_enabled)
940 @@ -784,7 +782,7 @@ static int param_get_audit(char *buffer, struct kernel_param *kp)
941  static int param_set_audit(const char *val, struct kernel_param *kp)
942  {
943         int i;
944 -       if (!capable(CAP_MAC_ADMIN))
945 +       if (!policy_admin_capable())
946                 return -EPERM;
947  
948         if (!apparmor_enabled)
949 @@ -805,7 +803,7 @@ static int param_set_audit(const char *val, struct kernel_param *kp)
950  
951  static int param_get_mode(char *buffer, struct kernel_param *kp)
952  {
953 -       if (!capable(CAP_MAC_ADMIN))
954 +       if (!policy_admin_capable())
955                 return -EPERM;
956  
957         if (!apparmor_enabled)
958 @@ -817,7 +815,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
959  static int param_set_mode(const char *val, struct kernel_param *kp)
960  {
961         int i;
962 -       if (!capable(CAP_MAC_ADMIN))
963 +       if (!policy_admin_capable())
964                 return -EPERM;
965  
966         if (!apparmor_enabled)
967 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
968 index 7807125..179e68d 100644
969 --- a/security/apparmor/policy.c
970 +++ b/security/apparmor/policy.c
971 @@ -918,6 +918,22 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
972                         &sa, NULL);
973  }
974  
975 +bool policy_view_capable(void)
976 +{
977 +       struct user_namespace *user_ns = current_user_ns();
978 +       bool response = false;
979 +
980 +       if (ns_capable(user_ns, CAP_MAC_ADMIN))
981 +               response = true;
982 +
983 +       return response;
984 +}
985 +
986 +bool policy_admin_capable(void)
987 +{
988 +       return policy_view_capable() && !aa_g_lock_policy;
989 +}
990 +
991  /**
992   * aa_may_manage_policy - can the current task manage policy
993   * @op: the policy manipulation operation being done
994 @@ -932,7 +948,7 @@ bool aa_may_manage_policy(int op)
995                 return 0;
996         }
997  
998 -       if (!capable(CAP_MAC_ADMIN)) {
999 +       if (!policy_admin_capable()) {
1000                 audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
1001                 return 0;
1002         }
1003
1004 commit 46c339f46b83e4cf8098f599cd182e65e9d054fc
1005 Author: Heinrich Schuchardt <xypron.glpk@gmx.de>
1006 Date:   Fri Jun 10 23:34:26 2016 +0200
1007
1008     apparmor: do not expose kernel stack
1009     
1010     Do not copy uninitalized fields th.td_hilen, th.td_data.
1011     
1012     Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
1013     Signed-off-by: John Johansen <john.johansen@canonical.com>
1014
1015 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
1016 index 32b72eb..3f900fc 100644
1017 --- a/security/apparmor/match.c
1018 +++ b/security/apparmor/match.c
1019 @@ -63,7 +63,9 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
1020  
1021         table = kvzalloc(tsize);
1022         if (table) {
1023 -               *table = th;
1024 +               table->td_id = th.td_id;
1025 +               table->td_flags = th.td_flags;
1026 +               table->td_lolen = th.td_lolen;
1027                 if (th.td_flags == YYTD_DATA8)
1028                         UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
1029                                      u8, byte_to_byte);
1030
1031 commit 7e65e8142b2ea4891581173d6e92fc337b02ff8b
1032 Author: John Johansen <john.johansen@canonical.com>
1033 Date:   Sat Jul 9 23:46:33 2016 -0700
1034
1035     apparmor: fix arg_size computation for when setprocattr is null terminated
1036     
1037     Signed-off-by: John Johansen <john.johansen@canonical.com>
1038
1039 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
1040 index e83eefb..ba8207b 100644
1041 --- a/security/apparmor/lsm.c
1042 +++ b/security/apparmor/lsm.c
1043 @@ -529,7 +529,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
1044         if (!*args)
1045                 goto out;
1046  
1047 -       arg_size = size - (args - (char *) value);
1048 +       arg_size = size - (args - (largs ? largs : (char *) value));
1049         if (strcmp(name, "current") == 0) {
1050                 if (strcmp(command, "changehat") == 0) {
1051                         error = aa_setprocattr_changehat(args, arg_size,
1052
1053 commit b661b13237991be6b5cdf0849f137c5ec58217bf
1054 Author: John Johansen <john.johansen@canonical.com>
1055 Date:   Mon Oct 4 15:03:36 2010 -0700
1056
1057     UBUNTU: SAUCE: AppArmor: basic networking rules
1058     
1059     Base support for network mediation.
1060     
1061     Signed-off-by: John Johansen <john.johansen@canonical.com>
1062
1063 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
1064 index 9cdec70..d5b291e 100644
1065 --- a/security/apparmor/.gitignore
1066 +++ b/security/apparmor/.gitignore
1067 @@ -1,5 +1,6 @@
1068  #
1069  # Generated include files
1070  #
1071 +net_names.h
1072  capability_names.h
1073  rlim_names.h
1074 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
1075 index d693df8..5dbb72f 100644
1076 --- a/security/apparmor/Makefile
1077 +++ b/security/apparmor/Makefile
1078 @@ -4,10 +4,10 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
1079  
1080  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
1081                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
1082 -              resource.o sid.o file.o
1083 +              resource.o sid.o file.o net.o
1084  apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
1085  
1086 -clean-files := capability_names.h rlim_names.h
1087 +clean-files := capability_names.h rlim_names.h net_names.h
1088  
1089  
1090  # Build a lower case string table of capability names
1091 @@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
1092             -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
1093              tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
1094  
1095 +# Build a lower case string table of address family names
1096 +# Transform lines from
1097 +#    define AF_LOCAL   1       /* POSIX name for AF_UNIX       */
1098 +#    #define AF_INET           2       /* Internet IP Protocol         */
1099 +# to
1100 +#    [1] = "local",
1101 +#    [2] = "inet",
1102 +#
1103 +# and build the securityfs entries for the mapping.
1104 +# Transforms lines from
1105 +#    #define AF_INET           2       /* Internet IP Protocol         */
1106 +# to
1107 +#    #define AA_FS_AF_MASK "local inet"
1108 +quiet_cmd_make-af = GEN     $@
1109 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
1110 +       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
1111 +        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
1112 +       echo "};" >> $@ ;\
1113 +       echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
1114 +       sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
1115 +        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
1116 +
1117 +# Build a lower case string table of sock type names
1118 +# Transform lines from
1119 +#    SOCK_STREAM       = 1,
1120 +# to
1121 +#    [1] = "stream",
1122 +quiet_cmd_make-sock = GEN     $@
1123 +cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
1124 +       sed $^ >>$@ -r -n \
1125 +       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
1126 +       echo "};" >> $@
1127  
1128  # Build a lower case string table of rlimit names.
1129  # Transforms lines from
1130 @@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
1131             tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
1132  
1133  $(obj)/capability.o : $(obj)/capability_names.h
1134 +$(obj)/net.o : $(obj)/net_names.h
1135  $(obj)/resource.o : $(obj)/rlim_names.h
1136  $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
1137                             $(src)/Makefile
1138 @@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
1139  $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
1140                       $(src)/Makefile
1141         $(call cmd,make-rlim)
1142 +$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
1143 +                    $(srctree)/include/linux/net.h \
1144 +                    $(src)/Makefile
1145 +       $(call cmd,make-af)
1146 +       $(call cmd,make-sock)
1147 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
1148 index 729e595..181d961 100644
1149 --- a/security/apparmor/apparmorfs.c
1150 +++ b/security/apparmor/apparmorfs.c
1151 @@ -807,6 +807,7 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
1152         AA_FS_DIR("policy",                     aa_fs_entry_policy),
1153         AA_FS_DIR("domain",                     aa_fs_entry_domain),
1154         AA_FS_DIR("file",                       aa_fs_entry_file),
1155 +       AA_FS_DIR("network",                    aa_fs_entry_network),
1156         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
1157         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
1158         AA_FS_DIR("caps",                       aa_fs_entry_caps),
1159 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
1160 index ba3dfd1..5d3c419 100644
1161 --- a/security/apparmor/include/audit.h
1162 +++ b/security/apparmor/include/audit.h
1163 @@ -125,6 +125,10 @@ struct apparmor_audit_data {
1164                         u32 denied;
1165                         kuid_t ouid;
1166                 } fs;
1167 +               struct {
1168 +                       int type, protocol;
1169 +                       struct sock *sk;
1170 +               } net;
1171         };
1172  };
1173  
1174 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
1175 new file mode 100644
1176 index 0000000..cb8a121
1177 --- /dev/null
1178 +++ b/security/apparmor/include/net.h
1179 @@ -0,0 +1,44 @@
1180 +/*
1181 + * AppArmor security module
1182 + *
1183 + * This file contains AppArmor network mediation definitions.
1184 + *
1185 + * Copyright (C) 1998-2008 Novell/SUSE
1186 + * Copyright 2009-2012 Canonical Ltd.
1187 + *
1188 + * This program is free software; you can redistribute it and/or
1189 + * modify it under the terms of the GNU General Public License as
1190 + * published by the Free Software Foundation, version 2 of the
1191 + * License.
1192 + */
1193 +
1194 +#ifndef __AA_NET_H
1195 +#define __AA_NET_H
1196 +
1197 +#include <net/sock.h>
1198 +
1199 +#include "apparmorfs.h"
1200 +
1201 +/* struct aa_net - network confinement data
1202 + * @allowed: basic network families permissions
1203 + * @audit_network: which network permissions to force audit
1204 + * @quiet_network: which network permissions to quiet rejects
1205 + */
1206 +struct aa_net {
1207 +       u16 allow[AF_MAX];
1208 +       u16 audit[AF_MAX];
1209 +       u16 quiet[AF_MAX];
1210 +};
1211 +
1212 +extern struct aa_fs_entry aa_fs_entry_network[];
1213 +
1214 +extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
1215 +                      int type, int protocol, struct sock *sk);
1216 +extern int aa_revalidate_sk(int op, struct sock *sk);
1217 +
1218 +static inline void aa_free_net_rules(struct aa_net *new)
1219 +{
1220 +       /* NOP */
1221 +}
1222 +
1223 +#endif /* __AA_NET_H */
1224 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
1225 index 52275f0..4fc4dac 100644
1226 --- a/security/apparmor/include/policy.h
1227 +++ b/security/apparmor/include/policy.h
1228 @@ -27,6 +27,7 @@
1229  #include "capability.h"
1230  #include "domain.h"
1231  #include "file.h"
1232 +#include "net.h"
1233  #include "resource.h"
1234  
1235  extern const char *const aa_profile_mode_names[];
1236 @@ -176,6 +177,7 @@ struct aa_replacedby {
1237   * @policy: general match rules governing policy
1238   * @file: The set of rules governing basic file access and domain transitions
1239   * @caps: capabilities for the profile
1240 + * @net: network controls for the profile
1241   * @rlimits: rlimits for the profile
1242   *
1243   * @dents: dentries for the profiles file entries in apparmorfs
1244 @@ -217,6 +219,7 @@ struct aa_profile {
1245         struct aa_policydb policy;
1246         struct aa_file_rules file;
1247         struct aa_caps caps;
1248 +       struct aa_net net;
1249         struct aa_rlimit rlimits;
1250  
1251         unsigned char *hash;
1252 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
1253 index ba8207b..88d3b0a 100644
1254 --- a/security/apparmor/lsm.c
1255 +++ b/security/apparmor/lsm.c
1256 @@ -32,6 +32,7 @@
1257  #include "include/context.h"
1258  #include "include/file.h"
1259  #include "include/ipc.h"
1260 +#include "include/net.h"
1261  #include "include/path.h"
1262  #include "include/policy.h"
1263  #include "include/procattr.h"
1264 @@ -584,6 +585,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
1265         return error;
1266  }
1267  
1268 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
1269 +{
1270 +       struct aa_profile *profile;
1271 +       int error = 0;
1272 +
1273 +       if (kern)
1274 +               return 0;
1275 +
1276 +       profile = __aa_current_profile();
1277 +       if (!unconfined(profile))
1278 +               error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
1279 +                                   NULL);
1280 +       return error;
1281 +}
1282 +
1283 +static int apparmor_socket_bind(struct socket *sock,
1284 +                               struct sockaddr *address, int addrlen)
1285 +{
1286 +       struct sock *sk = sock->sk;
1287 +
1288 +       return aa_revalidate_sk(OP_BIND, sk);
1289 +}
1290 +
1291 +static int apparmor_socket_connect(struct socket *sock,
1292 +                                  struct sockaddr *address, int addrlen)
1293 +{
1294 +       struct sock *sk = sock->sk;
1295 +
1296 +       return aa_revalidate_sk(OP_CONNECT, sk);
1297 +}
1298 +
1299 +static int apparmor_socket_listen(struct socket *sock, int backlog)
1300 +{
1301 +       struct sock *sk = sock->sk;
1302 +
1303 +       return aa_revalidate_sk(OP_LISTEN, sk);
1304 +}
1305 +
1306 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
1307 +{
1308 +       struct sock *sk = sock->sk;
1309 +
1310 +       return aa_revalidate_sk(OP_ACCEPT, sk);
1311 +}
1312 +
1313 +static int apparmor_socket_sendmsg(struct socket *sock,
1314 +                                  struct msghdr *msg, int size)
1315 +{
1316 +       struct sock *sk = sock->sk;
1317 +
1318 +       return aa_revalidate_sk(OP_SENDMSG, sk);
1319 +}
1320 +
1321 +static int apparmor_socket_recvmsg(struct socket *sock,
1322 +                                  struct msghdr *msg, int size, int flags)
1323 +{
1324 +       struct sock *sk = sock->sk;
1325 +
1326 +       return aa_revalidate_sk(OP_RECVMSG, sk);
1327 +}
1328 +
1329 +static int apparmor_socket_getsockname(struct socket *sock)
1330 +{
1331 +       struct sock *sk = sock->sk;
1332 +
1333 +       return aa_revalidate_sk(OP_GETSOCKNAME, sk);
1334 +}
1335 +
1336 +static int apparmor_socket_getpeername(struct socket *sock)
1337 +{
1338 +       struct sock *sk = sock->sk;
1339 +
1340 +       return aa_revalidate_sk(OP_GETPEERNAME, sk);
1341 +}
1342 +
1343 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
1344 +                                     int optname)
1345 +{
1346 +       struct sock *sk = sock->sk;
1347 +
1348 +       return aa_revalidate_sk(OP_GETSOCKOPT, sk);
1349 +}
1350 +
1351 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
1352 +                                     int optname)
1353 +{
1354 +       struct sock *sk = sock->sk;
1355 +
1356 +       return aa_revalidate_sk(OP_SETSOCKOPT, sk);
1357 +}
1358 +
1359 +static int apparmor_socket_shutdown(struct socket *sock, int how)
1360 +{
1361 +       struct sock *sk = sock->sk;
1362 +
1363 +       return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
1364 +}
1365 +
1366  static struct security_hook_list apparmor_hooks[] = {
1367         LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
1368         LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
1369 @@ -613,6 +712,19 @@ static struct security_hook_list apparmor_hooks[] = {
1370         LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
1371         LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
1372  
1373 +       LSM_HOOK_INIT(socket_create, apparmor_socket_create),
1374 +       LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
1375 +       LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
1376 +       LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
1377 +       LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
1378 +       LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
1379 +       LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
1380 +       LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
1381 +       LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
1382 +       LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
1383 +       LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
1384 +       LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
1385 +
1386         LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
1387         LSM_HOOK_INIT(cred_free, apparmor_cred_free),
1388         LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
1389 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
1390 new file mode 100644
1391 index 0000000..003dd18
1392 --- /dev/null
1393 +++ b/security/apparmor/net.c
1394 @@ -0,0 +1,162 @@
1395 +/*
1396 + * AppArmor security module
1397 + *
1398 + * This file contains AppArmor network mediation
1399 + *
1400 + * Copyright (C) 1998-2008 Novell/SUSE
1401 + * Copyright 2009-2012 Canonical Ltd.
1402 + *
1403 + * This program is free software; you can redistribute it and/or
1404 + * modify it under the terms of the GNU General Public License as
1405 + * published by the Free Software Foundation, version 2 of the
1406 + * License.
1407 + */
1408 +
1409 +#include "include/apparmor.h"
1410 +#include "include/audit.h"
1411 +#include "include/context.h"
1412 +#include "include/net.h"
1413 +#include "include/policy.h"
1414 +
1415 +#include "net_names.h"
1416 +
1417 +struct aa_fs_entry aa_fs_entry_network[] = {
1418 +       AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
1419 +       { }
1420 +};
1421 +
1422 +/* audit callback for net specific fields */
1423 +static void audit_cb(struct audit_buffer *ab, void *va)
1424 +{
1425 +       struct common_audit_data *sa = va;
1426 +
1427 +       audit_log_format(ab, " family=");
1428 +       if (address_family_names[sa->u.net->family]) {
1429 +               audit_log_string(ab, address_family_names[sa->u.net->family]);
1430 +       } else {
1431 +               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
1432 +       }
1433 +       audit_log_format(ab, " sock_type=");
1434 +       if (sock_type_names[sa->aad->net.type]) {
1435 +               audit_log_string(ab, sock_type_names[sa->aad->net.type]);
1436 +       } else {
1437 +               audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
1438 +       }
1439 +       audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
1440 +}
1441 +
1442 +/**
1443 + * audit_net - audit network access
1444 + * @profile: profile being enforced  (NOT NULL)
1445 + * @op: operation being checked
1446 + * @family: network family
1447 + * @type:   network type
1448 + * @protocol: network protocol
1449 + * @sk: socket auditing is being applied to
1450 + * @error: error code for failure else 0
1451 + *
1452 + * Returns: %0 or sa->error else other errorcode on failure
1453 + */
1454 +static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
1455 +                    int protocol, struct sock *sk, int error)
1456 +{
1457 +       int audit_type = AUDIT_APPARMOR_AUTO;
1458 +       struct common_audit_data sa;
1459 +       struct apparmor_audit_data aad = { };
1460 +       struct lsm_network_audit net = { };
1461 +       if (sk) {
1462 +               sa.type = LSM_AUDIT_DATA_NET;
1463 +       } else {
1464 +               sa.type = LSM_AUDIT_DATA_NONE;
1465 +       }
1466 +       /* todo fill in socket addr info */
1467 +       sa.aad = &aad;
1468 +       sa.u.net = &net;
1469 +       sa.aad->op = op,
1470 +       sa.u.net->family = family;
1471 +       sa.u.net->sk = sk;
1472 +       sa.aad->net.type = type;
1473 +       sa.aad->net.protocol = protocol;
1474 +       sa.aad->error = error;
1475 +
1476 +       if (likely(!sa.aad->error)) {
1477 +               u16 audit_mask = profile->net.audit[sa.u.net->family];
1478 +               if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
1479 +                          !(1 << sa.aad->net.type & audit_mask)))
1480 +                       return 0;
1481 +               audit_type = AUDIT_APPARMOR_AUDIT;
1482 +       } else {
1483 +               u16 quiet_mask = profile->net.quiet[sa.u.net->family];
1484 +               u16 kill_mask = 0;
1485 +               u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
1486 +
1487 +               if (denied & kill_mask)
1488 +                       audit_type = AUDIT_APPARMOR_KILL;
1489 +
1490 +               if ((denied & quiet_mask) &&
1491 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1492 +                   AUDIT_MODE(profile) != AUDIT_ALL)
1493 +                       return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
1494 +       }
1495 +
1496 +       return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
1497 +}
1498 +
1499 +/**
1500 + * aa_net_perm - very course network access check
1501 + * @op: operation being checked
1502 + * @profile: profile being enforced  (NOT NULL)
1503 + * @family: network family
1504 + * @type:   network type
1505 + * @protocol: network protocol
1506 + *
1507 + * Returns: %0 else error if permission denied
1508 + */
1509 +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
1510 +               int protocol, struct sock *sk)
1511 +{
1512 +       u16 family_mask;
1513 +       int error;
1514 +
1515 +       if ((family < 0) || (family >= AF_MAX))
1516 +               return -EINVAL;
1517 +
1518 +       if ((type < 0) || (type >= SOCK_MAX))
1519 +               return -EINVAL;
1520 +
1521 +       /* unix domain and netlink sockets are handled by ipc */
1522 +       if (family == AF_UNIX || family == AF_NETLINK)
1523 +               return 0;
1524 +
1525 +       family_mask = profile->net.allow[family];
1526 +
1527 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
1528 +
1529 +       return audit_net(profile, op, family, type, protocol, sk, error);
1530 +}
1531 +
1532 +/**
1533 + * aa_revalidate_sk - Revalidate access to a sock
1534 + * @op: operation being checked
1535 + * @sk: sock being revalidated  (NOT NULL)
1536 + *
1537 + * Returns: %0 else error if permission denied
1538 + */
1539 +int aa_revalidate_sk(int op, struct sock *sk)
1540 +{
1541 +       struct aa_profile *profile;
1542 +       int error = 0;
1543 +
1544 +       /* aa_revalidate_sk should not be called from interrupt context
1545 +        * don't mediate these calls as they are not task related
1546 +        */
1547 +       if (in_interrupt())
1548 +               return 0;
1549 +
1550 +       profile = __aa_current_profile();
1551 +       if (!unconfined(profile))
1552 +               error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
1553 +                                   sk->sk_protocol, sk);
1554 +
1555 +       return error;
1556 +}
1557 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
1558 index 179e68d..f1a8541 100644
1559 --- a/security/apparmor/policy.c
1560 +++ b/security/apparmor/policy.c
1561 @@ -603,6 +603,7 @@ void aa_free_profile(struct aa_profile *profile)
1562  
1563         aa_free_file_rules(&profile->file);
1564         aa_free_cap_rules(&profile->caps);
1565 +       aa_free_net_rules(&profile->net);
1566         aa_free_rlimit_rules(&profile->rlimits);
1567  
1568         kzfree(profile->dirname);
1569 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
1570 index dac2121..0107bc4 100644
1571 --- a/security/apparmor/policy_unpack.c
1572 +++ b/security/apparmor/policy_unpack.c
1573 @@ -193,6 +193,19 @@ fail:
1574         return 0;
1575  }
1576  
1577 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
1578 +{
1579 +       if (unpack_nameX(e, AA_U16, name)) {
1580 +               if (!inbounds(e, sizeof(u16)))
1581 +                       return 0;
1582 +               if (data)
1583 +                       *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
1584 +               e->pos += sizeof(u16);
1585 +               return 1;
1586 +       }
1587 +       return 0;
1588 +}
1589 +
1590  static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
1591  {
1592         if (unpack_nameX(e, AA_U32, name)) {
1593 @@ -476,6 +489,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
1594  {
1595         struct aa_profile *profile = NULL;
1596         const char *name = NULL;
1597 +       size_t size = 0;
1598         int i, error = -EPROTO;
1599         kernel_cap_t tmpcap;
1600         u32 tmp;
1601 @@ -576,6 +590,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
1602         if (!unpack_rlimits(e, profile))
1603                 goto fail;
1604  
1605 +       size = unpack_array(e, "net_allowed_af");
1606 +       if (size) {
1607 +
1608 +               for (i = 0; i < size; i++) {
1609 +                       /* discard extraneous rules that this kernel will
1610 +                        * never request
1611 +                        */
1612 +                       if (i >= AF_MAX) {
1613 +                               u16 tmp;
1614 +                               if (!unpack_u16(e, &tmp, NULL) ||
1615 +                                   !unpack_u16(e, &tmp, NULL) ||
1616 +                                   !unpack_u16(e, &tmp, NULL))
1617 +                                       goto fail;
1618 +                               continue;
1619 +                       }
1620 +                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
1621 +                               goto fail;
1622 +                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
1623 +                               goto fail;
1624 +                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
1625 +                               goto fail;
1626 +               }
1627 +               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
1628 +                       goto fail;
1629 +       }
1630 +       /*
1631 +        * allow unix domain and netlink sockets they are handled
1632 +        * by IPC
1633 +        */
1634 +       profile->net.allow[AF_UNIX] = 0xffff;
1635 +       profile->net.allow[AF_NETLINK] = 0xffff;
1636 +
1637         if (unpack_nameX(e, AA_STRUCT, "policydb")) {
1638                 /* generic policy dfa - optional and may be NULL */
1639                 profile->policy.dfa = unpack_dfa(e);
1640
1641 commit 64c5e24470a219c79c2870c63f18f6bd55648b1b
1642 Author: John Johansen <john.johansen@canonical.com>
1643 Date:   Fri Jun 29 17:34:00 2012 -0700
1644
1645     apparmor: Fix quieting of audit messages for network mediation
1646     
1647     If a profile specified a quieting of network denials for a given rule by
1648     either the quiet or deny rule qualifiers, the resultant quiet mask for
1649     denied requests was applied incorrectly, resulting in two potential bugs.
1650     1. The misapplied quiet mask would prevent denials from being correctly
1651        tested against the kill mask/mode. Thus network access requests that
1652        should have resulted in the application being killed did not.
1653     
1654     2. The actual quieting of the denied network request was not being applied.
1655        This would result in network rejections always being logged even when
1656        they had been specifically marked as quieted.
1657     
1658     Signed-off-by: John Johansen <john.johansen@canonical.com>
1659
1660 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
1661 index 003dd18..6e6e5c9 100644
1662 --- a/security/apparmor/net.c
1663 +++ b/security/apparmor/net.c
1664 @@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
1665         } else {
1666                 u16 quiet_mask = profile->net.quiet[sa.u.net->family];
1667                 u16 kill_mask = 0;
1668 -               u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
1669 +               u16 denied = (1 << sa.aad->net.type);
1670  
1671                 if (denied & kill_mask)
1672                         audit_type = AUDIT_APPARMOR_KILL;
1673
1674 commit f7cef61751a2382fb4ea26c18736d7552ffdb24a
1675 Author: John Johansen <john.johansen@canonical.com>
1676 Date:   Wed May 16 10:58:05 2012 -0700
1677
1678     UBUNTU: SAUCE: apparmor: Add the ability to mediate mount
1679     
1680     Add the ability for apparmor to do mediation of mount operations. Mount
1681     rules require an updated apparmor_parser (2.8 series) for policy compilation.
1682     
1683     The basic form of the rules are.
1684     
1685       [audit] [deny] mount [conds]* [device] [ -> [conds] path],
1686       [audit] [deny] remount [conds]* [path],
1687       [audit] [deny] umount [conds]* [path],
1688       [audit] [deny] pivotroot [oldroot=<value>] <path>
1689     
1690       remount is just a short cut for mount options=remount
1691     
1692       where [conds] can be
1693         fstype=<expr>
1694         options=<expr>
1695     
1696     Example mount commands
1697       mount,                # allow all mounts, but not umount or pivotroot
1698     
1699       mount fstype=procfs,  # allow mounting procfs anywhere
1700     
1701       mount options=(bind, ro) /foo -> /bar,  # readonly bind mount
1702     
1703       mount /dev/sda -> /mnt,
1704     
1705       mount /dev/sd** -> /mnt/**,
1706     
1707       mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
1708     
1709       umount,
1710     
1711       umount /m*,
1712     
1713     See the apparmor userspace for full documentation
1714     
1715     Signed-off-by: John Johansen <john.johansen@canonical.com>
1716     Acked-by: Kees Cook <kees@ubuntu.com>
1717
1718 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
1719 index 5dbb72f..89b3445 100644
1720 --- a/security/apparmor/Makefile
1721 +++ b/security/apparmor/Makefile
1722 @@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
1723  
1724  apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
1725                path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
1726 -              resource.o sid.o file.o net.o
1727 +              resource.o sid.o file.o net.o mount.o
1728  apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
1729  
1730  clean-files := capability_names.h rlim_names.h net_names.h
1731 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
1732 index 181d961..5fb67f6 100644
1733 --- a/security/apparmor/apparmorfs.c
1734 +++ b/security/apparmor/apparmorfs.c
1735 @@ -800,7 +800,18 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
1736  
1737  static struct aa_fs_entry aa_fs_entry_policy[] = {
1738         AA_FS_FILE_BOOLEAN("set_load",          1),
1739 -       {}
1740 +       { }
1741 +};
1742 +
1743 +static struct aa_fs_entry aa_fs_entry_mount[] = {
1744 +       AA_FS_FILE_STRING("mask", "mount umount"),
1745 +       { }
1746 +};
1747 +
1748 +static struct aa_fs_entry aa_fs_entry_namespaces[] = {
1749 +       AA_FS_FILE_BOOLEAN("profile",           1),
1750 +       AA_FS_FILE_BOOLEAN("pivot_root",        1),
1751 +       { }
1752  };
1753  
1754  static struct aa_fs_entry aa_fs_entry_features[] = {
1755 @@ -808,6 +819,8 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
1756         AA_FS_DIR("domain",                     aa_fs_entry_domain),
1757         AA_FS_DIR("file",                       aa_fs_entry_file),
1758         AA_FS_DIR("network",                    aa_fs_entry_network),
1759 +       AA_FS_DIR("mount",                      aa_fs_entry_mount),
1760 +       AA_FS_DIR("namespaces",                 aa_fs_entry_namespaces),
1761         AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
1762         AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
1763         AA_FS_DIR("caps",                       aa_fs_entry_caps),
1764 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
1765 index 3a7f1da..c2a8b8a 100644
1766 --- a/security/apparmor/audit.c
1767 +++ b/security/apparmor/audit.c
1768 @@ -44,6 +44,10 @@ const char *const op_table[] = {
1769         "file_mmap",
1770         "file_mprotect",
1771  
1772 +       "pivotroot",
1773 +       "mount",
1774 +       "umount",
1775 +
1776         "create",
1777         "post_create",
1778         "bind",
1779 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
1780 index fc3036b..f2a83b4 100644
1781 --- a/security/apparmor/domain.c
1782 +++ b/security/apparmor/domain.c
1783 @@ -236,7 +236,7 @@ static const char *next_name(int xtype, const char *name)
1784   *
1785   * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
1786   */
1787 -static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
1788 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
1789  {
1790         struct aa_profile *new_profile = NULL;
1791         struct aa_namespace *ns = profile->ns;
1792 diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
1793 index e4ea626..ce6ff6a 100644
1794 --- a/security/apparmor/include/apparmor.h
1795 +++ b/security/apparmor/include/apparmor.h
1796 @@ -30,8 +30,9 @@
1797  #define AA_CLASS_NET           4
1798  #define AA_CLASS_RLIMITS       5
1799  #define AA_CLASS_DOMAIN                6
1800 +#define AA_CLASS_MOUNT         7
1801  
1802 -#define AA_CLASS_LAST          AA_CLASS_DOMAIN
1803 +#define AA_CLASS_LAST          AA_CLASS_MOUNT
1804  
1805  /* Control parameters settable through module/boot flags */
1806  extern enum audit_mode aa_g_audit;
1807 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
1808 index 5d3c419..b9f1d57 100644
1809 --- a/security/apparmor/include/audit.h
1810 +++ b/security/apparmor/include/audit.h
1811 @@ -72,6 +72,10 @@ enum aa_ops {
1812         OP_FMMAP,
1813         OP_FMPROT,
1814  
1815 +       OP_PIVOTROOT,
1816 +       OP_MOUNT,
1817 +       OP_UMOUNT,
1818 +
1819         OP_CREATE,
1820         OP_POST_CREATE,
1821         OP_BIND,
1822 @@ -120,6 +124,13 @@ struct apparmor_audit_data {
1823                         unsigned long max;
1824                 } rlim;
1825                 struct {
1826 +                       const char *src_name;
1827 +                       const char *type;
1828 +                       const char *trans;
1829 +                       const char *data;
1830 +                       unsigned long flags;
1831 +               } mnt;
1832 +               struct {
1833                         const char *target;
1834                         u32 request;
1835                         u32 denied;
1836 diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
1837 index de04464..a3f70c5 100644
1838 --- a/security/apparmor/include/domain.h
1839 +++ b/security/apparmor/include/domain.h
1840 @@ -23,6 +23,8 @@ struct aa_domain {
1841         char **table;
1842  };
1843  
1844 +struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
1845 +
1846  int apparmor_bprm_set_creds(struct linux_binprm *bprm);
1847  int apparmor_bprm_secureexec(struct linux_binprm *bprm);
1848  void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
1849 diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
1850 new file mode 100644
1851 index 0000000..a43b1d6
1852 --- /dev/null
1853 +++ b/security/apparmor/include/mount.h
1854 @@ -0,0 +1,54 @@
1855 +/*
1856 + * AppArmor security module
1857 + *
1858 + * This file contains AppArmor file mediation function definitions.
1859 + *
1860 + * Copyright 2012 Canonical Ltd.
1861 + *
1862 + * This program is free software; you can redistribute it and/or
1863 + * modify it under the terms of the GNU General Public License as
1864 + * published by the Free Software Foundation, version 2 of the
1865 + * License.
1866 + */
1867 +
1868 +#ifndef __AA_MOUNT_H
1869 +#define __AA_MOUNT_H
1870 +
1871 +#include <linux/fs.h>
1872 +#include <linux/path.h>
1873 +
1874 +#include "domain.h"
1875 +#include "policy.h"
1876 +
1877 +/* mount perms */
1878 +#define AA_MAY_PIVOTROOT       0x01
1879 +#define AA_MAY_MOUNT           0x02
1880 +#define AA_MAY_UMOUNT          0x04
1881 +#define AA_AUDIT_DATA          0x40
1882 +#define AA_CONT_MATCH          0x40
1883 +
1884 +#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
1885 +
1886 +int aa_remount(struct aa_profile *profile, const struct path *path,
1887 +              unsigned long flags, void *data);
1888 +
1889 +int aa_bind_mount(struct aa_profile *profile, const struct path *path,
1890 +                 const char *old_name, unsigned long flags);
1891 +
1892 +
1893 +int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
1894 +                        unsigned long flags);
1895 +
1896 +int aa_move_mount(struct aa_profile *profile, const struct path *path,
1897 +                 const char *old_name);
1898 +
1899 +int aa_new_mount(struct aa_profile *profile, const char *dev_name,
1900 +                const struct path *path, const char *type, unsigned long flags,
1901 +                void *data);
1902 +
1903 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
1904 +
1905 +int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
1906 +                const struct path *new_path);
1907 +
1908 +#endif /* __AA_MOUNT_H */
1909 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
1910 index 88d3b0a..432cbd3 100644
1911 --- a/security/apparmor/lsm.c
1912 +++ b/security/apparmor/lsm.c
1913 @@ -36,6 +36,7 @@
1914  #include "include/path.h"
1915  #include "include/policy.h"
1916  #include "include/procattr.h"
1917 +#include "include/mount.h"
1918  
1919  /* Flag indicating whether initialization completed */
1920  int apparmor_initialized __initdata;
1921 @@ -469,6 +470,61 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
1922                            !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
1923  }
1924  
1925 +static int apparmor_sb_mount(const char *dev_name, const struct path *path,
1926 +                            const char *type, unsigned long flags, void *data)
1927 +{
1928 +       struct aa_profile *profile;
1929 +       int error = 0;
1930 +
1931 +       /* Discard magic */
1932 +       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
1933 +               flags &= ~MS_MGC_MSK;
1934 +
1935 +       flags &= ~AA_MS_IGNORE_MASK;
1936 +
1937 +       profile = __aa_current_profile();
1938 +       if (!unconfined(profile)) {
1939 +               if (flags & MS_REMOUNT)
1940 +                       error = aa_remount(profile, path, flags, data);
1941 +               else if (flags & MS_BIND)
1942 +                       error = aa_bind_mount(profile, path, dev_name, flags);
1943 +               else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
1944 +                                 MS_UNBINDABLE))
1945 +                       error = aa_mount_change_type(profile, path, flags);
1946 +               else if (flags & MS_MOVE)
1947 +                       error = aa_move_mount(profile, path, dev_name);
1948 +               else
1949 +                       error = aa_new_mount(profile, dev_name, path, type,
1950 +                                            flags, data);
1951 +       }
1952 +       return error;
1953 +}
1954 +
1955 +static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
1956 +{
1957 +       struct aa_profile *profile;
1958 +       int error = 0;
1959 +
1960 +       profile = __aa_current_profile();
1961 +       if (!unconfined(profile))
1962 +               error = aa_umount(profile, mnt, flags);
1963 +
1964 +       return error;
1965 +}
1966 +
1967 +static int apparmor_sb_pivotroot(const struct path *old_path,
1968 +                                const struct path *new_path)
1969 +{
1970 +       struct aa_profile *profile;
1971 +       int error = 0;
1972 +
1973 +       profile = __aa_current_profile();
1974 +       if (!unconfined(profile))
1975 +               error = aa_pivotroot(profile, old_path, new_path);
1976 +
1977 +       return error;
1978 +}
1979 +
1980  static int apparmor_getprocattr(struct task_struct *task, char *name,
1981                                 char **value)
1982  {
1983 @@ -689,6 +745,10 @@ static struct security_hook_list apparmor_hooks[] = {
1984         LSM_HOOK_INIT(capget, apparmor_capget),
1985         LSM_HOOK_INIT(capable, apparmor_capable),
1986  
1987 +       LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
1988 +       LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
1989 +       LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
1990 +       
1991         LSM_HOOK_INIT(path_link, apparmor_path_link),
1992         LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
1993         LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
1994 diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
1995 new file mode 100644
1996 index 0000000..9cf9170
1997 --- /dev/null
1998 +++ b/security/apparmor/mount.c
1999 @@ -0,0 +1,620 @@
2000 +/*
2001 + * AppArmor security module
2002 + *
2003 + * This file contains AppArmor mediation of files
2004 + *
2005 + * Copyright (C) 1998-2008 Novell/SUSE
2006 + * Copyright 2009-2012 Canonical Ltd.
2007 + *
2008 + * This program is free software; you can redistribute it and/or
2009 + * modify it under the terms of the GNU General Public License as
2010 + * published by the Free Software Foundation, version 2 of the
2011 + * License.
2012 + */
2013 +
2014 +#include <linux/fs.h>
2015 +#include <linux/mount.h>
2016 +#include <linux/namei.h>
2017 +
2018 +#include "include/apparmor.h"
2019 +#include "include/audit.h"
2020 +#include "include/context.h"
2021 +#include "include/domain.h"
2022 +#include "include/file.h"
2023 +#include "include/match.h"
2024 +#include "include/mount.h"
2025 +#include "include/path.h"
2026 +#include "include/policy.h"
2027 +
2028 +
2029 +static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
2030 +{
2031 +       if (flags & MS_RDONLY)
2032 +               audit_log_format(ab, "ro");
2033 +       else
2034 +               audit_log_format(ab, "rw");
2035 +       if (flags & MS_NOSUID)
2036 +               audit_log_format(ab, ", nosuid");
2037 +       if (flags & MS_NODEV)
2038 +               audit_log_format(ab, ", nodev");
2039 +       if (flags & MS_NOEXEC)
2040 +               audit_log_format(ab, ", noexec");
2041 +       if (flags & MS_SYNCHRONOUS)
2042 +               audit_log_format(ab, ", sync");
2043 +       if (flags & MS_REMOUNT)
2044 +               audit_log_format(ab, ", remount");
2045 +       if (flags & MS_MANDLOCK)
2046 +               audit_log_format(ab, ", mand");
2047 +       if (flags & MS_DIRSYNC)
2048 +               audit_log_format(ab, ", dirsync");
2049 +       if (flags & MS_NOATIME)
2050 +               audit_log_format(ab, ", noatime");
2051 +       if (flags & MS_NODIRATIME)
2052 +               audit_log_format(ab, ", nodiratime");
2053 +       if (flags & MS_BIND)
2054 +               audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
2055 +       if (flags & MS_MOVE)
2056 +               audit_log_format(ab, ", move");
2057 +       if (flags & MS_SILENT)
2058 +               audit_log_format(ab, ", silent");
2059 +       if (flags & MS_POSIXACL)
2060 +               audit_log_format(ab, ", acl");
2061 +       if (flags & MS_UNBINDABLE)
2062 +               audit_log_format(ab, flags & MS_REC ? ", runbindable" :
2063 +                                ", unbindable");
2064 +       if (flags & MS_PRIVATE)
2065 +               audit_log_format(ab, flags & MS_REC ? ", rprivate" :
2066 +                                ", private");
2067 +       if (flags & MS_SLAVE)
2068 +               audit_log_format(ab, flags & MS_REC ? ", rslave" :
2069 +                                ", slave");
2070 +       if (flags & MS_SHARED)
2071 +               audit_log_format(ab, flags & MS_REC ? ", rshared" :
2072 +                                ", shared");
2073 +       if (flags & MS_RELATIME)
2074 +               audit_log_format(ab, ", relatime");
2075 +       if (flags & MS_I_VERSION)
2076 +               audit_log_format(ab, ", iversion");
2077 +       if (flags & MS_STRICTATIME)
2078 +               audit_log_format(ab, ", strictatime");
2079 +       if (flags & MS_NOUSER)
2080 +               audit_log_format(ab, ", nouser");
2081 +}
2082 +
2083 +/**
2084 + * audit_cb - call back for mount specific audit fields
2085 + * @ab: audit_buffer  (NOT NULL)
2086 + * @va: audit struct to audit values of  (NOT NULL)
2087 + */
2088 +static void audit_cb(struct audit_buffer *ab, void *va)
2089 +{
2090 +       struct common_audit_data *sa = va;
2091 +
2092 +       if (sa->aad->mnt.type) {
2093 +               audit_log_format(ab, " fstype=");
2094 +               audit_log_untrustedstring(ab, sa->aad->mnt.type);
2095 +       }
2096 +       if (sa->aad->mnt.src_name) {
2097 +               audit_log_format(ab, " srcname=");
2098 +               audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
2099 +       }
2100 +       if (sa->aad->mnt.trans) {
2101 +               audit_log_format(ab, " trans=");
2102 +               audit_log_untrustedstring(ab, sa->aad->mnt.trans);
2103 +       }
2104 +       if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
2105 +               audit_log_format(ab, " flags=\"");
2106 +               audit_mnt_flags(ab, sa->aad->mnt.flags);
2107 +               audit_log_format(ab, "\"");
2108 +       }
2109 +       if (sa->aad->mnt.data) {
2110 +               audit_log_format(ab, " options=");
2111 +               audit_log_untrustedstring(ab, sa->aad->mnt.data);
2112 +       }
2113 +}
2114 +
2115 +/**
2116 + * audit_mount - handle the auditing of mount operations
2117 + * @profile: the profile being enforced  (NOT NULL)
2118 + * @gfp: allocation flags
2119 + * @op: operation being mediated (NOT NULL)
2120 + * @name: name of object being mediated (MAYBE NULL)
2121 + * @src_name: src_name of object being mediated (MAYBE_NULL)
2122 + * @type: type of filesystem (MAYBE_NULL)
2123 + * @trans: name of trans (MAYBE NULL)
2124 + * @flags: filesystem idependent mount flags
2125 + * @data: filesystem mount flags
2126 + * @request: permissions requested
2127 + * @perms: the permissions computed for the request (NOT NULL)
2128 + * @info: extra information message (MAYBE NULL)
2129 + * @error: 0 if operation allowed else failure error code
2130 + *
2131 + * Returns: %0 or error on failure
2132 + */
2133 +static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
2134 +                      const char *name, const char *src_name,
2135 +                      const char *type, const char *trans,
2136 +                      unsigned long flags, const void *data, u32 request,
2137 +                      struct file_perms *perms, const char *info, int error)
2138 +{
2139 +       int audit_type = AUDIT_APPARMOR_AUTO;
2140 +       struct common_audit_data sa = { };
2141 +       struct apparmor_audit_data aad = { };
2142 +
2143 +       if (likely(!error)) {
2144 +               u32 mask = perms->audit;
2145 +
2146 +               if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
2147 +                       mask = 0xffff;
2148 +
2149 +               /* mask off perms that are not being force audited */
2150 +               request &= mask;
2151 +
2152 +               if (likely(!request))
2153 +                       return 0;
2154 +               audit_type = AUDIT_APPARMOR_AUDIT;
2155 +       } else {
2156 +               /* only report permissions that were denied */
2157 +               request = request & ~perms->allow;
2158 +
2159 +               if (request & perms->kill)
2160 +                       audit_type = AUDIT_APPARMOR_KILL;
2161 +
2162 +               /* quiet known rejects, assumes quiet and kill do not overlap */
2163 +               if ((request & perms->quiet) &&
2164 +                   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
2165 +                   AUDIT_MODE(profile) != AUDIT_ALL)
2166 +                       request &= ~perms->quiet;
2167 +
2168 +               if (!request)
2169 +                       return COMPLAIN_MODE(profile) ?
2170 +                               complain_error(error) : error;
2171 +       }
2172 +
2173 +       sa.type = LSM_AUDIT_DATA_NONE;
2174 +       sa.aad = &aad;
2175 +       sa.aad->op = op;
2176 +       sa.aad->name = name;
2177 +       sa.aad->mnt.src_name = src_name;
2178 +       sa.aad->mnt.type = type;
2179 +       sa.aad->mnt.trans = trans;
2180 +       sa.aad->mnt.flags = flags;
2181 +       if (data && (perms->audit & AA_AUDIT_DATA))
2182 +               sa.aad->mnt.data = data;
2183 +       sa.aad->info = info;
2184 +       sa.aad->error = error;
2185 +
2186 +       return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
2187 +}
2188 +
2189 +/**
2190 + * match_mnt_flags - Do an ordered match on mount flags
2191 + * @dfa: dfa to match against
2192 + * @state: state to start in
2193 + * @flags: mount flags to match against
2194 + *
2195 + * Mount flags are encoded as an ordered match. This is done instead of
2196 + * checking against a simple bitmask, to allow for logical operations
2197 + * on the flags.
2198 + *
2199 + * Returns: next state after flags match
2200 + */
2201 +static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
2202 +                                   unsigned long flags)
2203 +{
2204 +       unsigned int i;
2205 +
2206 +       for (i = 0; i <= 31 ; ++i) {
2207 +               if ((1 << i) & flags)
2208 +                       state = aa_dfa_next(dfa, state, i + 1);
2209 +       }
2210 +
2211 +       return state;
2212 +}
2213 +
2214 +/**
2215 + * compute_mnt_perms - compute mount permission associated with @state
2216 + * @dfa: dfa to match against (NOT NULL)
2217 + * @state: state match finished in
2218 + *
2219 + * Returns: mount permissions
2220 + */
2221 +static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
2222 +                                          unsigned int state)
2223 +{
2224 +       struct file_perms perms;
2225 +
2226 +       perms.kill = 0;
2227 +       perms.allow = dfa_user_allow(dfa, state);
2228 +       perms.audit = dfa_user_audit(dfa, state);
2229 +       perms.quiet = dfa_user_quiet(dfa, state);
2230 +       perms.xindex = dfa_user_xindex(dfa, state);
2231 +
2232 +       return perms;
2233 +}
2234 +
2235 +static const char const *mnt_info_table[] = {
2236 +       "match succeeded",
2237 +       "failed mntpnt match",
2238 +       "failed srcname match",
2239 +       "failed type match",
2240 +       "failed flags match",
2241 +       "failed data match"
2242 +};
2243 +
2244 +/*
2245 + * Returns 0 on success else element that match failed in, this is the
2246 + * index into the mnt_info_table above
2247 + */
2248 +static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
2249 +                       const char *mntpnt, const char *devname,
2250 +                       const char *type, unsigned long flags,
2251 +                       void *data, bool binary, struct file_perms *perms)
2252 +{
2253 +       unsigned int state;
2254 +
2255 +       state = aa_dfa_match(dfa, start, mntpnt);
2256 +       state = aa_dfa_null_transition(dfa, state);
2257 +       if (!state)
2258 +               return 1;
2259 +
2260 +       if (devname)
2261 +               state = aa_dfa_match(dfa, state, devname);
2262 +       state = aa_dfa_null_transition(dfa, state);
2263 +       if (!state)
2264 +               return 2;
2265 +
2266 +       if (type)
2267 +               state = aa_dfa_match(dfa, state, type);
2268 +       state = aa_dfa_null_transition(dfa, state);
2269 +       if (!state)
2270 +               return 3;
2271 +
2272 +       state = match_mnt_flags(dfa, state, flags);
2273 +       if (!state)
2274 +               return 4;
2275 +       *perms = compute_mnt_perms(dfa, state);
2276 +       if (perms->allow & AA_MAY_MOUNT)
2277 +               return 0;
2278 +
2279 +       /* only match data if not binary and the DFA flags data is expected */
2280 +       if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
2281 +               state = aa_dfa_null_transition(dfa, state);
2282 +               if (!state)
2283 +                       return 4;
2284 +
2285 +               state = aa_dfa_match(dfa, state, data);
2286 +               if (!state)
2287 +                       return 5;
2288 +               *perms = compute_mnt_perms(dfa, state);
2289 +               if (perms->allow & AA_MAY_MOUNT)
2290 +                       return 0;
2291 +       }
2292 +
2293 +       /* failed at end of flags match */
2294 +       return 4;
2295 +}
2296 +
2297 +/**
2298 + * match_mnt - handle path matching for mount
2299 + * @profile: the confining profile
2300 + * @mntpnt: string for the mntpnt (NOT NULL)
2301 + * @devname: string for the devname/src_name (MAYBE NULL)
2302 + * @type: string for the dev type (MAYBE NULL)
2303 + * @flags: mount flags to match
2304 + * @data: fs mount data (MAYBE NULL)
2305 + * @binary: whether @data is binary
2306 + * @perms: Returns: permission found by the match
2307 + * @info: Returns: infomation string about the match for logging
2308 + *
2309 + * Returns: 0 on success else error
2310 + */
2311 +static int match_mnt(struct aa_profile *profile, const char *mntpnt,
2312 +                    const char *devname, const char *type,
2313 +                    unsigned long flags, void *data, bool binary,
2314 +                    struct file_perms *perms, const char **info)
2315 +{
2316 +       int pos;
2317 +
2318 +       if (!profile->policy.dfa)
2319 +               return -EACCES;
2320 +
2321 +       pos = do_match_mnt(profile->policy.dfa,
2322 +                          profile->policy.start[AA_CLASS_MOUNT],
2323 +                          mntpnt, devname, type, flags, data, binary, perms);
2324 +       if (pos) {
2325 +               *info = mnt_info_table[pos];
2326 +               return -EACCES;
2327 +       }
2328 +
2329 +       return 0;
2330 +}
2331 +
2332 +static int path_flags(struct aa_profile *profile, const struct path *path)
2333 +{
2334 +       return profile->path_flags |
2335 +               S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
2336 +}
2337 +
2338 +int aa_remount(struct aa_profile *profile, const struct path *path,
2339 +              unsigned long flags, void *data)
2340 +{
2341 +       struct file_perms perms = { };
2342 +       const char *name, *info = NULL;
2343 +       char *buffer = NULL;
2344 +       int binary, error;
2345 +
2346 +       binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
2347 +
2348 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
2349 +                            &info);
2350 +       if (error)
2351 +               goto audit;
2352 +
2353 +       error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
2354 +                         &perms, &info);
2355 +
2356 +audit:
2357 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
2358 +                           NULL, flags, data, AA_MAY_MOUNT, &perms, info,
2359 +                           error);
2360 +       kfree(buffer);
2361 +
2362 +       return error;
2363 +}
2364 +
2365 +int aa_bind_mount(struct aa_profile *profile, const struct path *path,
2366 +                 const char *dev_name, unsigned long flags)
2367 +{
2368 +       struct file_perms perms = { };
2369 +       char *buffer = NULL, *old_buffer = NULL;
2370 +       const char *name, *old_name = NULL, *info = NULL;
2371 +       struct path old_path;
2372 +       int error;
2373 +
2374 +       if (!dev_name || !*dev_name)
2375 +               return -EINVAL;
2376 +
2377 +       flags &= MS_REC | MS_BIND;
2378 +
2379 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
2380 +                            &info);
2381 +       if (error)
2382 +               goto audit;
2383 +
2384 +       error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
2385 +       if (error)
2386 +               goto audit;
2387 +
2388 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
2389 +                            &old_buffer, &old_name, &info);
2390 +       path_put(&old_path);
2391 +       if (error)
2392 +               goto audit;
2393 +
2394 +       error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
2395 +                         &perms, &info);
2396 +
2397 +audit:
2398 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
2399 +                           NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
2400 +                           info, error);
2401 +       kfree(buffer);
2402 +       kfree(old_buffer);
2403 +
2404 +       return error;
2405 +}
2406 +
2407 +int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
2408 +                        unsigned long flags)
2409 +{
2410 +       struct file_perms perms = { };
2411 +       char *buffer = NULL;
2412 +       const char *name, *info = NULL;
2413 +       int error;
2414 +
2415 +       /* These are the flags allowed by do_change_type() */
2416 +       flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
2417 +                 MS_UNBINDABLE);
2418 +
2419 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
2420 +                            &info);
2421 +       if (error)
2422 +               goto audit;
2423 +
2424 +       error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
2425 +                         &info);
2426 +
2427 +audit:
2428 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
2429 +                           NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
2430 +                           error);
2431 +       kfree(buffer);
2432 +
2433 +       return error;
2434 +}
2435 +
2436 +int aa_move_mount(struct aa_profile *profile, const struct path *path,
2437 +                 const char *orig_name)
2438 +{
2439 +       struct file_perms perms = { };
2440 +       char *buffer = NULL, *old_buffer = NULL;
2441 +       const char *name, *old_name = NULL, *info = NULL;
2442 +       struct path old_path;
2443 +       int error;
2444 +
2445 +       if (!orig_name || !*orig_name)
2446 +               return -EINVAL;
2447 +
2448 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
2449 +                            &info);
2450 +       if (error)
2451 +               goto audit;
2452 +
2453 +       error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
2454 +       if (error)
2455 +               goto audit;
2456 +
2457 +       error = aa_path_name(&old_path, path_flags(profile, &old_path),
2458 +                            &old_buffer, &old_name, &info);
2459 +       path_put(&old_path);
2460 +       if (error)
2461 +               goto audit;
2462 +
2463 +       error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
2464 +                         &perms, &info);
2465 +
2466 +audit:
2467 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
2468 +                           NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
2469 +                           info, error);
2470 +       kfree(buffer);
2471 +       kfree(old_buffer);
2472 +
2473 +       return error;
2474 +}
2475 +
2476 +int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
2477 +                const struct path *path, const char *type, unsigned long flags,
2478 +                void *data)
2479 +{
2480 +       struct file_perms perms = { };
2481 +       char *buffer = NULL, *dev_buffer = NULL;
2482 +       const char *name = NULL, *dev_name = NULL, *info = NULL;
2483 +       int binary = 1;
2484 +       int error;
2485 +
2486 +       dev_name = orig_dev_name;
2487 +       if (type) {
2488 +               int requires_dev;
2489 +               struct file_system_type *fstype = get_fs_type(type);
2490 +               if (!fstype)
2491 +                       return -ENODEV;
2492 +
2493 +               binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
2494 +               requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
2495 +               put_filesystem(fstype);
2496 +
2497 +               if (requires_dev) {
2498 +                       struct path dev_path;
2499 +
2500 +                       if (!dev_name || !*dev_name) {
2501 +                               error = -ENOENT;
2502 +                               goto out;
2503 +                       }
2504 +
2505 +                       error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
2506 +                       if (error)
2507 +                               goto audit;
2508 +
2509 +                       error = aa_path_name(&dev_path,
2510 +                                            path_flags(profile, &dev_path),
2511 +                                            &dev_buffer, &dev_name, &info);
2512 +                       path_put(&dev_path);
2513 +                       if (error)
2514 +                               goto audit;
2515 +               }
2516 +       }
2517 +
2518 +       error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
2519 +                            &info);
2520 +       if (error)
2521 +               goto audit;
2522 +
2523 +       error = match_mnt(profile, name, dev_name, type, flags, data, binary,
2524 +                         &perms, &info);
2525 +
2526 +audit:
2527 +       error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,  dev_name,
2528 +                           type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
2529 +                           error);
2530 +       kfree(buffer);
2531 +       kfree(dev_buffer);
2532 +
2533 +out:
2534 +       return error;
2535 +
2536 +}
2537 +
2538 +int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
2539 +{
2540 +       struct file_perms perms = { };
2541 +       char *buffer = NULL;
2542 +       const char *name, *info = NULL;
2543 +       int error;
2544 +
2545 +       struct path path = { mnt, mnt->mnt_root };
2546 +       error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
2547 +                            &info);
2548 +       if (error)
2549 +               goto audit;
2550 +
2551 +       if (!error && profile->policy.dfa) {
2552 +               unsigned int state;
2553 +               state = aa_dfa_match(profile->policy.dfa,
2554 +                                    profile->policy.start[AA_CLASS_MOUNT],
2555 +                                    name);
2556 +               perms = compute_mnt_perms(profile->policy.dfa, state);
2557 +       }
2558 +
2559 +       if (AA_MAY_UMOUNT & ~perms.allow)
2560 +               error = -EACCES;
2561 +
2562 +audit:
2563 +       error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
2564 +                           NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
2565 +       kfree(buffer);
2566 +
2567 +       return error;
2568 +}
2569 +
2570 +int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
2571 +                const struct path *new_path)
2572 +{
2573 +       struct file_perms perms = { };
2574 +       struct aa_profile *target = NULL;
2575 +       char *old_buffer = NULL, *new_buffer = NULL;
2576 +       const char *old_name, *new_name = NULL, *info = NULL;
2577 +       int error;
2578 +
2579 +       error = aa_path_name(old_path, path_flags(profile, old_path),
2580 +                            &old_buffer, &old_name, &info);
2581 +       if (error)
2582 +               goto audit;
2583 +
2584 +       error = aa_path_name(new_path, path_flags(profile, new_path),
2585 +                            &new_buffer, &new_name, &info);
2586 +       if (error)
2587 +               goto audit;
2588 +
2589 +       if (profile->policy.dfa) {
2590 +               unsigned int state;
2591 +               state = aa_dfa_match(profile->policy.dfa,
2592 +                                    profile->policy.start[AA_CLASS_MOUNT],
2593 +                                    new_name);
2594 +               state = aa_dfa_null_transition(profile->policy.dfa, state);
2595 +               state = aa_dfa_match(profile->policy.dfa, state, old_name);
2596 +               perms = compute_mnt_perms(profile->policy.dfa, state);
2597 +       }
2598 +
2599 +       if (AA_MAY_PIVOTROOT & perms.allow) {
2600 +               if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
2601 +                       target = x_table_lookup(profile, perms.xindex);
2602 +                       if (!target)
2603 +                               error = -ENOENT;
2604 +                       else
2605 +                               error = aa_replace_current_profile(target);
2606 +               }
2607 +       } else
2608 +               error = -EACCES;
2609 +
2610 +audit:
2611 +       error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
2612 +                           old_name, NULL, target ? target->base.name : NULL,
2613 +                           0, NULL,  AA_MAY_PIVOTROOT, &perms, info, error);
2614 +       aa_put_profile(target);
2615 +       kfree(old_buffer);
2616 +       kfree(new_buffer);
2617 +
2618 +       return error;
2619 +}
This page took 0.256323 seconds and 4 git commands to generate.