]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - security/apparmor/mount.c
Revert "UBUNTU: SAUCE: apparmor: fix sleep in critical section"
[mirror_ubuntu-zesty-kernel.git] / security / apparmor / mount.c
1 /*
2 * AppArmor security module
3 *
4 * This file contains AppArmor mediation of files
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2012 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15 #include <linux/fs.h>
16 #include <linux/mount.h>
17 #include <linux/namei.h>
18
19 #include "include/apparmor.h"
20 #include "include/audit.h"
21 #include "include/context.h"
22 #include "include/domain.h"
23 #include "include/file.h"
24 #include "include/match.h"
25 #include "include/mount.h"
26 #include "include/path.h"
27 #include "include/policy.h"
28
29
30 static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
31 {
32 if (flags & MS_RDONLY)
33 audit_log_format(ab, "ro");
34 else
35 audit_log_format(ab, "rw");
36 if (flags & MS_NOSUID)
37 audit_log_format(ab, ", nosuid");
38 if (flags & MS_NODEV)
39 audit_log_format(ab, ", nodev");
40 if (flags & MS_NOEXEC)
41 audit_log_format(ab, ", noexec");
42 if (flags & MS_SYNCHRONOUS)
43 audit_log_format(ab, ", sync");
44 if (flags & MS_REMOUNT)
45 audit_log_format(ab, ", remount");
46 if (flags & MS_MANDLOCK)
47 audit_log_format(ab, ", mand");
48 if (flags & MS_DIRSYNC)
49 audit_log_format(ab, ", dirsync");
50 if (flags & MS_NOATIME)
51 audit_log_format(ab, ", noatime");
52 if (flags & MS_NODIRATIME)
53 audit_log_format(ab, ", nodiratime");
54 if (flags & MS_BIND)
55 audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
56 if (flags & MS_MOVE)
57 audit_log_format(ab, ", move");
58 if (flags & MS_SILENT)
59 audit_log_format(ab, ", silent");
60 if (flags & MS_POSIXACL)
61 audit_log_format(ab, ", acl");
62 if (flags & MS_UNBINDABLE)
63 audit_log_format(ab, flags & MS_REC ? ", runbindable" :
64 ", unbindable");
65 if (flags & MS_PRIVATE)
66 audit_log_format(ab, flags & MS_REC ? ", rprivate" :
67 ", private");
68 if (flags & MS_SLAVE)
69 audit_log_format(ab, flags & MS_REC ? ", rslave" :
70 ", slave");
71 if (flags & MS_SHARED)
72 audit_log_format(ab, flags & MS_REC ? ", rshared" :
73 ", shared");
74 if (flags & MS_RELATIME)
75 audit_log_format(ab, ", relatime");
76 if (flags & MS_I_VERSION)
77 audit_log_format(ab, ", iversion");
78 if (flags & MS_STRICTATIME)
79 audit_log_format(ab, ", strictatime");
80 if (flags & MS_NOUSER)
81 audit_log_format(ab, ", nouser");
82 }
83
84 /**
85 * audit_cb - call back for mount specific audit fields
86 * @ab: audit_buffer (NOT NULL)
87 * @va: audit struct to audit values of (NOT NULL)
88 */
89 static void audit_cb(struct audit_buffer *ab, void *va)
90 {
91 struct common_audit_data *sa = va;
92
93 if (aad(sa)->mnt.type) {
94 audit_log_format(ab, " fstype=");
95 audit_log_untrustedstring(ab, aad(sa)->mnt.type);
96 }
97 if (aad(sa)->mnt.src_name) {
98 audit_log_format(ab, " srcname=");
99 audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
100 }
101 if (aad(sa)->mnt.trans) {
102 audit_log_format(ab, " trans=");
103 audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
104 }
105 if (aad(sa)->mnt.flags) {
106 audit_log_format(ab, " flags=\"");
107 audit_mnt_flags(ab, aad(sa)->mnt.flags);
108 audit_log_format(ab, "\"");
109 }
110 if (aad(sa)->mnt.data) {
111 audit_log_format(ab, " options=");
112 audit_log_untrustedstring(ab, aad(sa)->mnt.data);
113 }
114 }
115
116 /**
117 * audit_mount - handle the auditing of mount operations
118 * @profile: the profile being enforced (NOT NULL)
119 * @op: operation being mediated (NOT NULL)
120 * @name: name of object being mediated (MAYBE NULL)
121 * @src_name: src_name of object being mediated (MAYBE_NULL)
122 * @type: type of filesystem (MAYBE_NULL)
123 * @trans: name of trans (MAYBE NULL)
124 * @flags: filesystem idependent mount flags
125 * @data: filesystem mount flags
126 * @request: permissions requested
127 * @perms: the permissions computed for the request (NOT NULL)
128 * @info: extra information message (MAYBE NULL)
129 * @error: 0 if operation allowed else failure error code
130 *
131 * Returns: %0 or error on failure
132 */
133 static int audit_mount(struct aa_profile *profile, const char *op, const char *name,
134 const char *src_name, const char *type,
135 const char *trans, unsigned long flags,
136 const void *data, u32 request, struct aa_perms *perms,
137 const char *info, int error)
138 {
139 int audit_type = AUDIT_APPARMOR_AUTO;
140 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
141
142 if (likely(!error)) {
143 u32 mask = perms->audit;
144
145 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
146 mask = 0xffff;
147
148 /* mask off perms that are not being force audited */
149 request &= mask;
150
151 if (likely(!request))
152 return 0;
153 audit_type = AUDIT_APPARMOR_AUDIT;
154 } else {
155 /* only report permissions that were denied */
156 request = request & ~perms->allow;
157
158 if (request & perms->kill)
159 audit_type = AUDIT_APPARMOR_KILL;
160
161 /* quiet known rejects, assumes quiet and kill do not overlap */
162 if ((request & perms->quiet) &&
163 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
164 AUDIT_MODE(profile) != AUDIT_ALL)
165 request &= ~perms->quiet;
166
167 if (!request)
168 return error;
169 }
170
171 aad(&sa)->name = name;
172 aad(&sa)->mnt.src_name = src_name;
173 aad(&sa)->mnt.type = type;
174 aad(&sa)->mnt.trans = trans;
175 aad(&sa)->mnt.flags = flags;
176 if (data && (perms->audit & AA_AUDIT_DATA))
177 aad(&sa)->mnt.data = data;
178 aad(&sa)->info = info;
179 aad(&sa)->error = error;
180
181 return aa_audit(audit_type, profile, &sa, audit_cb);
182 }
183
184 /**
185 * match_mnt_flags - Do an ordered match on mount flags
186 * @dfa: dfa to match against
187 * @state: state to start in
188 * @flags: mount flags to match against
189 *
190 * Mount flags are encoded as an ordered match. This is done instead of
191 * checking against a simple bitmask, to allow for logical operations
192 * on the flags.
193 *
194 * Returns: next state after flags match
195 */
196 static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
197 unsigned long flags)
198 {
199 unsigned int i;
200
201 for (i = 0; i <= 31 ; ++i) {
202 if ((1 << i) & flags)
203 state = aa_dfa_next(dfa, state, i + 1);
204 }
205
206 return state;
207 }
208
209 /**
210 * compute_mnt_perms - compute mount permission associated with @state
211 * @dfa: dfa to match against (NOT NULL)
212 * @state: state match finished in
213 *
214 * Returns: mount permissions
215 */
216 static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
217 unsigned int state)
218 {
219 struct aa_perms perms;
220
221 perms.kill = 0;
222 perms.allow = dfa_user_allow(dfa, state);
223 perms.audit = dfa_user_audit(dfa, state);
224 perms.quiet = dfa_user_quiet(dfa, state);
225 perms.xindex = dfa_user_xindex(dfa, state);
226
227 return perms;
228 }
229
230 static const char *mnt_info_table[] = {
231 "match succeeded",
232 "failed mntpnt match",
233 "failed srcname match",
234 "failed type match",
235 "failed flags match",
236 "failed data match"
237 };
238
239 /*
240 * Returns 0 on success else element that match failed in, this is the
241 * index into the mnt_info_table above
242 */
243 static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
244 const char *mntpnt, const char *devname,
245 const char *type, unsigned long flags,
246 void *data, bool binary, struct aa_perms *perms)
247 {
248 unsigned int state;
249
250 AA_BUG(!dfa);
251 AA_BUG(!perms);
252
253 state = aa_dfa_match(dfa, start, mntpnt);
254 state = aa_dfa_null_transition(dfa, state);
255 if (!state)
256 return 1;
257
258 if (devname)
259 state = aa_dfa_match(dfa, state, devname);
260 state = aa_dfa_null_transition(dfa, state);
261 if (!state)
262 return 2;
263
264 if (type)
265 state = aa_dfa_match(dfa, state, type);
266 state = aa_dfa_null_transition(dfa, state);
267 if (!state)
268 return 3;
269
270 state = match_mnt_flags(dfa, state, flags);
271 if (!state)
272 return 4;
273 *perms = compute_mnt_perms(dfa, state);
274 if (perms->allow & AA_MAY_MOUNT)
275 return 0;
276
277 /* only match data if not binary and the DFA flags data is expected */
278 if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
279 state = aa_dfa_null_transition(dfa, state);
280 if (!state)
281 return 4;
282
283 state = aa_dfa_match(dfa, state, data);
284 if (!state)
285 return 5;
286 *perms = compute_mnt_perms(dfa, state);
287 if (perms->allow & AA_MAY_MOUNT)
288 return 0;
289 }
290
291 /* failed at end of flags match */
292 return 4;
293 }
294
295 /**
296 * match_mnt - handle path matching for mount
297 * @profile: the confining profile
298 * @mntpnt: string for the mntpnt (NOT NULL)
299 * @devname: string for the devname/src_name (MAYBE NULL)
300 * @type: string for the dev type (MAYBE NULL)
301 * @flags: mount flags to match
302 * @data: fs mount data (MAYBE NULL)
303 * @binary: whether @data is binary
304 * @perms: Returns: permission found by the match
305 * @info: Returns: infomation string about the match for logging
306 *
307 * Returns: 0 on success else error
308 */
309 static int match_mnt(struct aa_profile *profile, const char *mntpnt,
310 const char *devname, const char *type,
311 unsigned long flags, void *data, bool binary)
312 {
313 struct aa_perms perms = { };
314 const char *info = NULL;
315 int pos, error = -EACCES;
316
317 AA_BUG(!profile);
318
319 pos = do_match_mnt(profile->policy.dfa,
320 profile->policy.start[AA_CLASS_MOUNT],
321 mntpnt, devname, type, flags, data, binary, &perms);
322 if (pos) {
323 info = mnt_info_table[pos];
324 goto audit;
325 }
326 error = 0;
327
328 audit:
329 return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
330 flags, data, AA_MAY_MOUNT, &perms, info, error);
331 }
332
333 static int path_flags(struct aa_profile *profile, struct path *path)
334 {
335 AA_BUG(!profile);
336 AA_BUG(!path);
337
338 return profile->path_flags |
339 (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
340 }
341
342 int aa_remount(struct aa_label *label, struct path *path, unsigned long flags,
343 void *data)
344 {
345 struct aa_profile *profile;
346 const char *name, *info = NULL;
347 char *buffer = NULL;
348 bool binary;
349 int error;
350
351 AA_BUG(!label);
352 AA_BUG(!path);
353
354 binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
355
356 get_buffers(buffer);
357 error = aa_path_name(path, path_flags(labels_profile(label), path),
358 buffer, &name, &info,
359 labels_profile(label)->disconnected);
360 if (error) {
361 error = audit_mount(labels_profile(label), OP_MOUNT, name, NULL,
362 NULL, NULL, flags, data, AA_MAY_MOUNT,
363 &nullperms, info, error);
364 goto out;
365 }
366
367 error = fn_for_each_confined(label, profile,
368 match_mnt(profile, name, NULL, NULL, flags, data,
369 binary));
370
371 out:
372 put_buffers(buffer);
373
374 return error;
375 }
376
377 int aa_bind_mount(struct aa_label *label, struct path *path,
378 const char *dev_name, unsigned long flags)
379 {
380 struct aa_profile *profile;
381 char *buffer = NULL, *old_buffer = NULL;
382 const char *name, *old_name = NULL, *info = NULL;
383 struct path old_path;
384 int error;
385
386 AA_BUG(!label);
387 AA_BUG(!path);
388
389 if (!dev_name || !*dev_name)
390 return -EINVAL;
391
392 flags &= MS_REC | MS_BIND;
393
394 error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
395 if (error)
396 return error;
397
398 get_buffers(buffer, old_buffer);
399 error = aa_path_name(path, path_flags(labels_profile(label), path), buffer, &name,
400 &info, labels_profile(label)->disconnected);
401 if (error)
402 goto error;
403
404 error = aa_path_name(&old_path, path_flags(labels_profile(label),
405 &old_path),
406 old_buffer, &old_name, &info,
407 labels_profile(label)->disconnected);
408 path_put(&old_path);
409 if (error)
410 goto error;
411
412 error = fn_for_each_confined(label, profile,
413 match_mnt(profile, name, old_name, NULL, flags, NULL,
414 false));
415
416 out:
417 put_buffers(buffer, old_buffer);
418
419 return error;
420
421 error:
422 error = fn_for_each(label, profile,
423 audit_mount(profile, OP_MOUNT, name, old_name, NULL,
424 NULL, flags, NULL, AA_MAY_MOUNT, &nullperms,
425 info, error));
426 goto out;
427 }
428
429 int aa_mount_change_type(struct aa_label *label, struct path *path,
430 unsigned long flags)
431 {
432 struct aa_profile *profile;
433 char *buffer = NULL;
434 const char *name, *info = NULL;
435 int error;
436
437 AA_BUG(!label);
438 AA_BUG(!path);
439
440 /* These are the flags allowed by do_change_type() */
441 flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
442 MS_UNBINDABLE);
443
444 get_buffers(buffer);
445 error = aa_path_name(path, path_flags(labels_profile(label), path),
446 buffer, &name, &info,
447 labels_profile(label)->disconnected);
448 if (error) {
449 error = fn_for_each(label, profile,
450 audit_mount(profile, OP_MOUNT, name, NULL,
451 NULL, NULL, flags, NULL,
452 AA_MAY_MOUNT, &nullperms, info,
453 error));
454 goto out;
455 }
456
457 error = fn_for_each_confined(label, profile,
458 match_mnt(profile, name, NULL, NULL, flags, NULL,
459 false));
460
461 out:
462 put_buffers(buffer);
463
464 return error;
465 }
466
467 int aa_move_mount(struct aa_label *label, struct path *path,
468 const char *orig_name)
469 {
470 struct aa_profile *profile;
471 char *buffer = NULL, *old_buffer = NULL;
472 const char *name, *old_name = NULL, *info = NULL;
473 struct path old_path;
474 int error;
475
476 AA_BUG(!label);
477 AA_BUG(!path);
478
479 if (!orig_name || !*orig_name)
480 return -EINVAL;
481
482 error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
483 if (error)
484 return error;
485
486 get_buffers(buffer, old_buffer);
487 error = aa_path_name(path, path_flags(labels_profile(label), path),
488 buffer, &name, &info,
489 labels_profile(label)->disconnected);
490 if (error)
491 goto error;
492
493 error = aa_path_name(&old_path, path_flags(labels_profile(label),
494 &old_path),
495 old_buffer, &old_name, &info,
496 labels_profile(label)->disconnected);
497 path_put(&old_path);
498 if (error)
499 goto error;
500
501 error = fn_for_each_confined(label, profile,
502 match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL,
503 false));
504
505 out:
506 put_buffers(buffer, old_buffer);
507
508 return error;
509
510 error:
511 error = fn_for_each(label, profile,
512 audit_mount(profile, OP_MOUNT, name, old_name, NULL,
513 NULL, MS_MOVE, NULL, AA_MAY_MOUNT,
514 &nullperms, info, error));
515 goto out;
516 }
517
518 int aa_new_mount(struct aa_label *label, const char *orig_dev_name,
519 struct path *path, const char *type, unsigned long flags,
520 void *data)
521 {
522 struct aa_profile *profile;
523 char *buffer = NULL, *dev_buffer = NULL;
524 const char *name = NULL, *dev_name = NULL, *info = NULL;
525 bool binary = true;
526 int error;
527 int requires_dev = 0;
528 struct path dev_path;
529
530 AA_BUG(!label);
531 AA_BUG(!path);
532
533 dev_name = orig_dev_name;
534 if (type) {
535 struct file_system_type *fstype;
536 fstype = get_fs_type(type);
537 if (!fstype)
538 return -ENODEV;
539 binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
540 requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
541 put_filesystem(fstype);
542
543 if (requires_dev) {
544 if (!dev_name || !*dev_name)
545 return -ENOENT;
546
547 error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
548 if (error)
549 return error;
550 }
551 }
552
553 get_buffers(buffer, dev_buffer);
554 if (type && requires_dev) {
555 error = aa_path_name(&dev_path,
556 path_flags(labels_profile(label),
557 &dev_path),
558 dev_buffer, &dev_name, &info,
559 labels_profile(label)->disconnected);
560 path_put(&dev_path);
561 if (error)
562 goto error;
563 }
564
565 error = aa_path_name(path, path_flags(labels_profile(label), path),
566 buffer, &name, &info,
567 labels_profile(label)->disconnected);
568 if (error)
569 goto error;
570
571 error = fn_for_each_confined(label, profile,
572 match_mnt(profile, name, dev_name, type, flags, data,
573 binary));
574
575 cleanup:
576 put_buffers(buffer, dev_buffer);
577
578 return error;
579
580 error:
581 error = fn_for_each(label, profile,
582 audit_mount(labels_profile(label), OP_MOUNT, name,
583 dev_name, type, NULL, flags, data,
584 AA_MAY_MOUNT, &nullperms, info, error));
585 goto cleanup;
586 }
587
588 static int profile_umount(struct aa_profile *profile, const char *name)
589 {
590 struct aa_perms perms = { };
591 const char *info = NULL;
592 unsigned int state;
593 int e = 0;
594
595 AA_BUG(!profile);
596 AA_BUG(!name);
597
598 state = aa_dfa_match(profile->policy.dfa,
599 profile->policy.start[AA_CLASS_MOUNT],
600 name);
601 perms = compute_mnt_perms(profile->policy.dfa, state);
602 if (AA_MAY_UMOUNT & ~perms.allow)
603 e = -EACCES;
604
605 return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
606 AA_MAY_UMOUNT, &perms, info, e);
607 }
608
609 int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
610 {
611 struct aa_profile *profile;
612 char *buffer = NULL;
613 const char *name, *info = NULL;
614 int error;
615 struct path path = { mnt, mnt->mnt_root };
616
617 AA_BUG(!label);
618 AA_BUG(!mnt);
619
620 get_buffers(buffer);
621 error = aa_path_name(&path, path_flags(labels_profile(label), &path),
622 buffer, &name, &info,
623 labels_profile(label)->disconnected);
624 if (error) {
625 error = fn_for_each(label, profile,
626 audit_mount(profile, OP_UMOUNT, name, NULL,
627 NULL, NULL, 0, NULL, AA_MAY_UMOUNT,
628 &nullperms, info, error));
629 goto out;
630 }
631
632 error = fn_for_each_confined(label, profile,
633 profile_umount(profile, name));
634
635 out:
636 put_buffers(buffer);
637
638 return error;
639 }
640
641 static int profile_pivotroot(struct aa_profile *profile, const char *new_name,
642 const char *old_name, struct aa_label **trans)
643 {
644 struct aa_label *target = NULL;
645 const char *trans_name = NULL;
646 struct aa_perms perms = { };
647 const char *info = NULL;
648 unsigned int state;
649 int error = -EACCES;
650
651 AA_BUG(!profile);
652 AA_BUG(!new_name);
653 AA_BUG(!old_name);
654 AA_BUG(!trans);
655
656 /* TODO: actual domain transition computation for multiple
657 * profiles
658 */
659 state = aa_dfa_match(profile->policy.dfa,
660 profile->policy.start[AA_CLASS_MOUNT],
661 new_name);
662 state = aa_dfa_null_transition(profile->policy.dfa, state);
663 state = aa_dfa_match(profile->policy.dfa, state, old_name);
664 perms = compute_mnt_perms(profile->policy.dfa, state);
665
666 if (AA_MAY_PIVOTROOT & perms.allow) {
667 if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
668 target = x_table_lookup(profile, perms.xindex,
669 &trans_name);
670 if (!target)
671 error = -ENOENT;
672 else
673 *trans = target;
674 } else
675 error = 0;
676 }
677
678 error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
679 NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
680 &perms, info, error);
681 if (!*trans)
682 aa_put_label(target);
683
684 return error;
685 }
686
687 int aa_pivotroot(struct aa_label *label, struct path *old_path,
688 struct path *new_path)
689 {
690 struct aa_profile *profile;
691 struct aa_label *target = NULL;
692 char *old_buffer = NULL, *new_buffer = NULL;
693 const char *old_name, *new_name = NULL, *info = NULL;
694 int error;
695
696 AA_BUG(!label);
697 AA_BUG(!old_path);
698 AA_BUG(!new_path);
699
700 get_buffers(old_buffer, new_buffer);
701 error = aa_path_name(old_path, path_flags(labels_profile(label),
702 old_path),
703 old_buffer, &old_name, &info,
704 labels_profile(label)->disconnected);
705 if (error)
706 goto error;
707 error = aa_path_name(new_path, path_flags(labels_profile(label),
708 new_path),
709 new_buffer, &new_name, &info,
710 labels_profile(label)->disconnected);
711 if (error)
712 goto error;
713 error = fn_for_each(label, profile,
714 profile_pivotroot(profile, new_name, old_name,
715 &target));
716 out:
717 put_buffers(old_buffer, new_buffer);
718
719 if (target)
720 error = aa_replace_current_label(target);
721
722 return error;
723
724 error:
725 error = fn_for_each(label, profile,
726 audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
727 NULL, NULL,
728 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
729 error));
730 goto out;
731 }