1 // SPDX-License-Identifier: GPL-2.0-only
3 * AppArmor security module
5 * This file contains AppArmor mediation of files
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2017 Canonical Ltd.
12 #include <linux/mount.h>
13 #include <linux/namei.h>
14 #include <uapi/linux/mount.h>
16 #include "include/apparmor.h"
17 #include "include/audit.h"
18 #include "include/cred.h"
19 #include "include/domain.h"
20 #include "include/file.h"
21 #include "include/match.h"
22 #include "include/mount.h"
23 #include "include/path.h"
24 #include "include/policy.h"
27 static void audit_mnt_flags(struct audit_buffer
*ab
, unsigned long flags
)
29 if (flags
& MS_RDONLY
)
30 audit_log_format(ab
, "ro");
32 audit_log_format(ab
, "rw");
33 if (flags
& MS_NOSUID
)
34 audit_log_format(ab
, ", nosuid");
36 audit_log_format(ab
, ", nodev");
37 if (flags
& MS_NOEXEC
)
38 audit_log_format(ab
, ", noexec");
39 if (flags
& MS_SYNCHRONOUS
)
40 audit_log_format(ab
, ", sync");
41 if (flags
& MS_REMOUNT
)
42 audit_log_format(ab
, ", remount");
43 if (flags
& MS_MANDLOCK
)
44 audit_log_format(ab
, ", mand");
45 if (flags
& MS_DIRSYNC
)
46 audit_log_format(ab
, ", dirsync");
47 if (flags
& MS_NOATIME
)
48 audit_log_format(ab
, ", noatime");
49 if (flags
& MS_NODIRATIME
)
50 audit_log_format(ab
, ", nodiratime");
52 audit_log_format(ab
, flags
& MS_REC
? ", rbind" : ", bind");
54 audit_log_format(ab
, ", move");
55 if (flags
& MS_SILENT
)
56 audit_log_format(ab
, ", silent");
57 if (flags
& MS_POSIXACL
)
58 audit_log_format(ab
, ", acl");
59 if (flags
& MS_UNBINDABLE
)
60 audit_log_format(ab
, flags
& MS_REC
? ", runbindable" :
62 if (flags
& MS_PRIVATE
)
63 audit_log_format(ab
, flags
& MS_REC
? ", rprivate" :
66 audit_log_format(ab
, flags
& MS_REC
? ", rslave" :
68 if (flags
& MS_SHARED
)
69 audit_log_format(ab
, flags
& MS_REC
? ", rshared" :
71 if (flags
& MS_RELATIME
)
72 audit_log_format(ab
, ", relatime");
73 if (flags
& MS_I_VERSION
)
74 audit_log_format(ab
, ", iversion");
75 if (flags
& MS_STRICTATIME
)
76 audit_log_format(ab
, ", strictatime");
77 if (flags
& MS_NOUSER
)
78 audit_log_format(ab
, ", nouser");
82 * audit_cb - call back for mount specific audit fields
83 * @ab: audit_buffer (NOT NULL)
84 * @va: audit struct to audit values of (NOT NULL)
86 static void audit_cb(struct audit_buffer
*ab
, void *va
)
88 struct common_audit_data
*sa
= va
;
90 if (aad(sa
)->mnt
.type
) {
91 audit_log_format(ab
, " fstype=");
92 audit_log_untrustedstring(ab
, aad(sa
)->mnt
.type
);
94 if (aad(sa
)->mnt
.src_name
) {
95 audit_log_format(ab
, " srcname=");
96 audit_log_untrustedstring(ab
, aad(sa
)->mnt
.src_name
);
98 if (aad(sa
)->mnt
.trans
) {
99 audit_log_format(ab
, " trans=");
100 audit_log_untrustedstring(ab
, aad(sa
)->mnt
.trans
);
102 if (aad(sa
)->mnt
.flags
) {
103 audit_log_format(ab
, " flags=\"");
104 audit_mnt_flags(ab
, aad(sa
)->mnt
.flags
);
105 audit_log_format(ab
, "\"");
107 if (aad(sa
)->mnt
.data
) {
108 audit_log_format(ab
, " options=");
109 audit_log_untrustedstring(ab
, aad(sa
)->mnt
.data
);
114 * audit_mount - handle the auditing of mount operations
115 * @profile: the profile being enforced (NOT NULL)
116 * @op: operation being mediated (NOT NULL)
117 * @name: name of object being mediated (MAYBE NULL)
118 * @src_name: src_name of object being mediated (MAYBE_NULL)
119 * @type: type of filesystem (MAYBE_NULL)
120 * @trans: name of trans (MAYBE NULL)
121 * @flags: filesystem independent mount flags
122 * @data: filesystem mount flags
123 * @request: permissions requested
124 * @perms: the permissions computed for the request (NOT NULL)
125 * @info: extra information message (MAYBE NULL)
126 * @error: 0 if operation allowed else failure error code
128 * Returns: %0 or error on failure
130 static int audit_mount(struct aa_profile
*profile
, const char *op
,
131 const char *name
, const char *src_name
,
132 const char *type
, const char *trans
,
133 unsigned long flags
, const void *data
, u32 request
,
134 struct aa_perms
*perms
, const char *info
, int error
)
136 int audit_type
= AUDIT_APPARMOR_AUTO
;
137 DEFINE_AUDIT_DATA(sa
, LSM_AUDIT_DATA_NONE
, op
);
139 if (likely(!error
)) {
140 u32 mask
= perms
->audit
;
142 if (unlikely(AUDIT_MODE(profile
) == AUDIT_ALL
))
145 /* mask off perms that are not being force audited */
148 if (likely(!request
))
150 audit_type
= AUDIT_APPARMOR_AUDIT
;
152 /* only report permissions that were denied */
153 request
= request
& ~perms
->allow
;
155 if (request
& perms
->kill
)
156 audit_type
= AUDIT_APPARMOR_KILL
;
158 /* quiet known rejects, assumes quiet and kill do not overlap */
159 if ((request
& perms
->quiet
) &&
160 AUDIT_MODE(profile
) != AUDIT_NOQUIET
&&
161 AUDIT_MODE(profile
) != AUDIT_ALL
)
162 request
&= ~perms
->quiet
;
168 aad(&sa
)->name
= name
;
169 aad(&sa
)->mnt
.src_name
= src_name
;
170 aad(&sa
)->mnt
.type
= type
;
171 aad(&sa
)->mnt
.trans
= trans
;
172 aad(&sa
)->mnt
.flags
= flags
;
173 if (data
&& (perms
->audit
& AA_AUDIT_DATA
))
174 aad(&sa
)->mnt
.data
= data
;
175 aad(&sa
)->info
= info
;
176 aad(&sa
)->error
= error
;
178 return aa_audit(audit_type
, profile
, &sa
, audit_cb
);
182 * match_mnt_flags - Do an ordered match on mount flags
183 * @dfa: dfa to match against
184 * @state: state to start in
185 * @flags: mount flags to match against
187 * Mount flags are encoded as an ordered match. This is done instead of
188 * checking against a simple bitmask, to allow for logical operations
191 * Returns: next state after flags match
193 static unsigned int match_mnt_flags(struct aa_dfa
*dfa
, unsigned int state
,
198 for (i
= 0; i
<= 31 ; ++i
) {
199 if ((1 << i
) & flags
)
200 state
= aa_dfa_next(dfa
, state
, i
+ 1);
207 * compute_mnt_perms - compute mount permission associated with @state
208 * @dfa: dfa to match against (NOT NULL)
209 * @state: state match finished in
211 * Returns: mount permissions
213 static struct aa_perms
compute_mnt_perms(struct aa_dfa
*dfa
,
216 struct aa_perms perms
= {
217 .allow
= dfa_user_allow(dfa
, state
),
218 .audit
= dfa_user_audit(dfa
, state
),
219 .quiet
= dfa_user_quiet(dfa
, state
),
220 .xindex
= dfa_user_xindex(dfa
, state
),
226 static const char * const mnt_info_table
[] = {
228 "failed mntpnt match",
229 "failed srcname match",
231 "failed flags match",
236 * Returns 0 on success else element that match failed in, this is the
237 * index into the mnt_info_table above
239 static int do_match_mnt(struct aa_dfa
*dfa
, unsigned int start
,
240 const char *mntpnt
, const char *devname
,
241 const char *type
, unsigned long flags
,
242 void *data
, bool binary
, struct aa_perms
*perms
)
249 state
= aa_dfa_match(dfa
, start
, mntpnt
);
250 state
= aa_dfa_null_transition(dfa
, state
);
255 state
= aa_dfa_match(dfa
, state
, devname
);
256 state
= aa_dfa_null_transition(dfa
, state
);
261 state
= aa_dfa_match(dfa
, state
, type
);
262 state
= aa_dfa_null_transition(dfa
, state
);
266 state
= match_mnt_flags(dfa
, state
, flags
);
269 *perms
= compute_mnt_perms(dfa
, state
);
270 if (perms
->allow
& AA_MAY_MOUNT
)
273 /* only match data if not binary and the DFA flags data is expected */
274 if (data
&& !binary
&& (perms
->allow
& AA_MNT_CONT_MATCH
)) {
275 state
= aa_dfa_null_transition(dfa
, state
);
279 state
= aa_dfa_match(dfa
, state
, data
);
282 *perms
= compute_mnt_perms(dfa
, state
);
283 if (perms
->allow
& AA_MAY_MOUNT
)
287 /* failed at end of flags match */
292 static int path_flags(struct aa_profile
*profile
, const struct path
*path
)
297 return profile
->path_flags
|
298 (S_ISDIR(path
->dentry
->d_inode
->i_mode
) ? PATH_IS_DIR
: 0);
302 * match_mnt_path_str - handle path matching for mount
303 * @profile: the confining profile
304 * @mntpath: for the mntpnt (NOT NULL)
305 * @buffer: buffer to be used to lookup mntpath
306 * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
307 * @type: string for the dev type (MAYBE NULL)
308 * @flags: mount flags to match
309 * @data: fs mount data (MAYBE NULL)
310 * @binary: whether @data is binary
311 * @devinfo: error str if (IS_ERR(@devname))
313 * Returns: 0 on success else error
315 static int match_mnt_path_str(struct aa_profile
*profile
,
316 const struct path
*mntpath
, char *buffer
,
317 const char *devname
, const char *type
,
318 unsigned long flags
, void *data
, bool binary
,
321 struct aa_perms perms
= { };
322 const char *mntpnt
= NULL
, *info
= NULL
;
329 if (!PROFILE_MEDIATES(profile
, AA_CLASS_MOUNT
))
332 error
= aa_path_name(mntpath
, path_flags(profile
, mntpath
), buffer
,
333 &mntpnt
, &info
, profile
->disconnected
);
336 if (IS_ERR(devname
)) {
337 error
= PTR_ERR(devname
);
344 pos
= do_match_mnt(profile
->policy
.dfa
,
345 profile
->policy
.start
[AA_CLASS_MOUNT
],
346 mntpnt
, devname
, type
, flags
, data
, binary
, &perms
);
348 info
= mnt_info_table
[pos
];
354 return audit_mount(profile
, OP_MOUNT
, mntpnt
, devname
, type
, NULL
,
355 flags
, data
, AA_MAY_MOUNT
, &perms
, info
, error
);
359 * match_mnt - handle path matching for mount
360 * @profile: the confining profile
361 * @mntpath: for the mntpnt (NOT NULL)
362 * @buffer: buffer to be used to lookup mntpath
363 * @devpath: path devname/src_name (MAYBE NULL)
364 * @devbuffer: buffer to be used to lookup devname/src_name
365 * @type: string for the dev type (MAYBE NULL)
366 * @flags: mount flags to match
367 * @data: fs mount data (MAYBE NULL)
368 * @binary: whether @data is binary
370 * Returns: 0 on success else error
372 static int match_mnt(struct aa_profile
*profile
, const struct path
*path
,
373 char *buffer
, struct path
*devpath
, char *devbuffer
,
374 const char *type
, unsigned long flags
, void *data
,
377 const char *devname
= NULL
, *info
= NULL
;
381 AA_BUG(devpath
&& !devbuffer
);
383 if (!PROFILE_MEDIATES(profile
, AA_CLASS_MOUNT
))
387 error
= aa_path_name(devpath
, path_flags(profile
, devpath
),
388 devbuffer
, &devname
, &info
,
389 profile
->disconnected
);
391 devname
= ERR_PTR(error
);
394 return match_mnt_path_str(profile
, path
, buffer
, devname
, type
, flags
,
398 int aa_remount(struct aa_label
*label
, const struct path
*path
,
399 unsigned long flags
, void *data
)
401 struct aa_profile
*profile
;
409 binary
= path
->dentry
->d_sb
->s_type
->fs_flags
& FS_BINARY_MOUNTDATA
;
411 buffer
= aa_get_buffer(false);
414 error
= fn_for_each_confined(label
, profile
,
415 match_mnt(profile
, path
, buffer
, NULL
, NULL
, NULL
,
416 flags
, data
, binary
));
417 aa_put_buffer(buffer
);
422 int aa_bind_mount(struct aa_label
*label
, const struct path
*path
,
423 const char *dev_name
, unsigned long flags
)
425 struct aa_profile
*profile
;
426 char *buffer
= NULL
, *old_buffer
= NULL
;
427 struct path old_path
;
433 if (!dev_name
|| !*dev_name
)
436 flags
&= MS_REC
| MS_BIND
;
438 error
= kern_path(dev_name
, LOOKUP_FOLLOW
|LOOKUP_AUTOMOUNT
, &old_path
);
442 buffer
= aa_get_buffer(false);
443 old_buffer
= aa_get_buffer(false);
445 if (!buffer
|| !old_buffer
)
448 error
= fn_for_each_confined(label
, profile
,
449 match_mnt(profile
, path
, buffer
, &old_path
, old_buffer
,
450 NULL
, flags
, NULL
, false));
452 aa_put_buffer(buffer
);
453 aa_put_buffer(old_buffer
);
459 int aa_mount_change_type(struct aa_label
*label
, const struct path
*path
,
462 struct aa_profile
*profile
;
469 /* These are the flags allowed by do_change_type() */
470 flags
&= (MS_REC
| MS_SILENT
| MS_SHARED
| MS_PRIVATE
| MS_SLAVE
|
473 buffer
= aa_get_buffer(false);
476 error
= fn_for_each_confined(label
, profile
,
477 match_mnt(profile
, path
, buffer
, NULL
, NULL
, NULL
,
478 flags
, NULL
, false));
479 aa_put_buffer(buffer
);
484 int aa_move_mount(struct aa_label
*label
, const struct path
*path
,
485 const char *orig_name
)
487 struct aa_profile
*profile
;
488 char *buffer
= NULL
, *old_buffer
= NULL
;
489 struct path old_path
;
495 if (!orig_name
|| !*orig_name
)
498 error
= kern_path(orig_name
, LOOKUP_FOLLOW
, &old_path
);
502 buffer
= aa_get_buffer(false);
503 old_buffer
= aa_get_buffer(false);
505 if (!buffer
|| !old_buffer
)
507 error
= fn_for_each_confined(label
, profile
,
508 match_mnt(profile
, path
, buffer
, &old_path
, old_buffer
,
509 NULL
, MS_MOVE
, NULL
, false));
511 aa_put_buffer(buffer
);
512 aa_put_buffer(old_buffer
);
518 int aa_new_mount(struct aa_label
*label
, const char *dev_name
,
519 const struct path
*path
, const char *type
, unsigned long flags
,
522 struct aa_profile
*profile
;
523 char *buffer
= NULL
, *dev_buffer
= NULL
;
526 int requires_dev
= 0;
527 struct path tmp_path
, *dev_path
= NULL
;
533 struct file_system_type
*fstype
;
535 fstype
= get_fs_type(type
);
538 binary
= fstype
->fs_flags
& FS_BINARY_MOUNTDATA
;
539 requires_dev
= fstype
->fs_flags
& FS_REQUIRES_DEV
;
540 put_filesystem(fstype
);
543 if (!dev_name
|| !*dev_name
)
546 error
= kern_path(dev_name
, LOOKUP_FOLLOW
, &tmp_path
);
549 dev_path
= &tmp_path
;
553 buffer
= aa_get_buffer(false);
559 dev_buffer
= aa_get_buffer(false);
564 error
= fn_for_each_confined(label
, profile
,
565 match_mnt(profile
, path
, buffer
, dev_path
, dev_buffer
,
566 type
, flags
, data
, binary
));
568 error
= fn_for_each_confined(label
, profile
,
569 match_mnt_path_str(profile
, path
, buffer
, dev_name
,
570 type
, flags
, data
, binary
, NULL
));
574 aa_put_buffer(buffer
);
575 aa_put_buffer(dev_buffer
);
582 static int profile_umount(struct aa_profile
*profile
, struct path
*path
,
585 struct aa_perms perms
= { };
586 const char *name
= NULL
, *info
= NULL
;
593 if (!PROFILE_MEDIATES(profile
, AA_CLASS_MOUNT
))
596 error
= aa_path_name(path
, path_flags(profile
, path
), buffer
, &name
,
597 &info
, profile
->disconnected
);
601 state
= aa_dfa_match(profile
->policy
.dfa
,
602 profile
->policy
.start
[AA_CLASS_MOUNT
],
604 perms
= compute_mnt_perms(profile
->policy
.dfa
, state
);
605 if (AA_MAY_UMOUNT
& ~perms
.allow
)
609 return audit_mount(profile
, OP_UMOUNT
, name
, NULL
, NULL
, NULL
, 0, NULL
,
610 AA_MAY_UMOUNT
, &perms
, info
, error
);
613 int aa_umount(struct aa_label
*label
, struct vfsmount
*mnt
, int flags
)
615 struct aa_profile
*profile
;
618 struct path path
= { .mnt
= mnt
, .dentry
= mnt
->mnt_root
};
623 buffer
= aa_get_buffer(false);
627 error
= fn_for_each_confined(label
, profile
,
628 profile_umount(profile
, &path
, buffer
));
629 aa_put_buffer(buffer
);
634 /* helper fn for transition on pivotroot
636 * Returns: label for transition or ERR_PTR. Does not return NULL
638 static struct aa_label
*build_pivotroot(struct aa_profile
*profile
,
639 const struct path
*new_path
,
641 const struct path
*old_path
,
644 const char *old_name
, *new_name
= NULL
, *info
= NULL
;
645 const char *trans_name
= NULL
;
646 struct aa_perms perms
= { };
654 if (profile_unconfined(profile
) ||
655 !PROFILE_MEDIATES(profile
, AA_CLASS_MOUNT
))
656 return aa_get_newest_label(&profile
->label
);
658 error
= aa_path_name(old_path
, path_flags(profile
, old_path
),
659 old_buffer
, &old_name
, &info
,
660 profile
->disconnected
);
663 error
= aa_path_name(new_path
, path_flags(profile
, new_path
),
664 new_buffer
, &new_name
, &info
,
665 profile
->disconnected
);
670 state
= aa_dfa_match(profile
->policy
.dfa
,
671 profile
->policy
.start
[AA_CLASS_MOUNT
],
673 state
= aa_dfa_null_transition(profile
->policy
.dfa
, state
);
674 state
= aa_dfa_match(profile
->policy
.dfa
, state
, old_name
);
675 perms
= compute_mnt_perms(profile
->policy
.dfa
, state
);
677 if (AA_MAY_PIVOTROOT
& perms
.allow
)
681 error
= audit_mount(profile
, OP_PIVOTROOT
, new_name
, old_name
,
682 NULL
, trans_name
, 0, NULL
, AA_MAY_PIVOTROOT
,
683 &perms
, info
, error
);
685 return ERR_PTR(error
);
687 return aa_get_newest_label(&profile
->label
);
690 int aa_pivotroot(struct aa_label
*label
, const struct path
*old_path
,
691 const struct path
*new_path
)
693 struct aa_profile
*profile
;
694 struct aa_label
*target
= NULL
;
695 char *old_buffer
= NULL
, *new_buffer
= NULL
, *info
= NULL
;
702 old_buffer
= aa_get_buffer(false);
703 new_buffer
= aa_get_buffer(false);
705 if (!old_buffer
|| !new_buffer
)
707 target
= fn_label_build(label
, profile
, GFP_KERNEL
,
708 build_pivotroot(profile
, new_path
, new_buffer
,
709 old_path
, old_buffer
));
711 info
= "label build failed";
714 } else if (!IS_ERR(target
)) {
715 error
= aa_replace_current_label(target
);
717 /* TODO: audit target */
718 aa_put_label(target
);
722 /* already audited error */
723 error
= PTR_ERR(target
);
725 aa_put_buffer(old_buffer
);
726 aa_put_buffer(new_buffer
);
731 /* TODO: add back in auditing of new_name and old_name */
732 error
= fn_for_each(label
, profile
,
733 audit_mount(profile
, OP_PIVOTROOT
, NULL
/*new_name */,
736 0, NULL
, AA_MAY_PIVOTROOT
, &nullperms
, info
,