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-2010 Canonical Ltd.
11 #include <linux/tty.h>
12 #include <linux/fdtable.h>
13 #include <linux/file.h>
15 #include "include/apparmor.h"
16 #include "include/audit.h"
17 #include "include/cred.h"
18 #include "include/file.h"
19 #include "include/match.h"
20 #include "include/net.h"
21 #include "include/path.h"
22 #include "include/policy.h"
23 #include "include/label.h"
25 static u32
map_mask_to_chr_mask(u32 mask
)
27 u32 m
= mask
& PERMS_CHRS_MASK
;
29 if (mask
& AA_MAY_GETATTR
)
31 if (mask
& (AA_MAY_SETATTR
| AA_MAY_CHMOD
| AA_MAY_CHOWN
))
38 * file_audit_cb - call back for file specific audit fields
39 * @ab: audit_buffer (NOT NULL)
40 * @va: audit struct to audit values of (NOT NULL)
42 static void file_audit_cb(struct audit_buffer
*ab
, void *va
)
44 struct common_audit_data
*sa
= va
;
45 kuid_t fsuid
= current_fsuid();
48 if (aad(sa
)->request
& AA_AUDIT_FILE_MASK
) {
49 aa_perm_mask_to_str(str
, sizeof(str
), aa_file_perm_chrs
,
50 map_mask_to_chr_mask(aad(sa
)->request
));
51 audit_log_format(ab
, " requested_mask=\"%s\"", str
);
53 if (aad(sa
)->denied
& AA_AUDIT_FILE_MASK
) {
54 aa_perm_mask_to_str(str
, sizeof(str
), aa_file_perm_chrs
,
55 map_mask_to_chr_mask(aad(sa
)->denied
));
56 audit_log_format(ab
, " denied_mask=\"%s\"", str
);
58 if (aad(sa
)->request
& AA_AUDIT_FILE_MASK
) {
59 audit_log_format(ab
, " fsuid=%d",
60 from_kuid(&init_user_ns
, fsuid
));
61 audit_log_format(ab
, " ouid=%d",
62 from_kuid(&init_user_ns
, aad(sa
)->fs
.ouid
));
66 audit_log_format(ab
, " target=");
67 aa_label_xaudit(ab
, labels_ns(aad(sa
)->label
), aad(sa
)->peer
,
68 FLAG_VIEW_SUBNS
, GFP_KERNEL
);
69 } else if (aad(sa
)->fs
.target
) {
70 audit_log_format(ab
, " target=");
71 audit_log_untrustedstring(ab
, aad(sa
)->fs
.target
);
76 * aa_audit_file - handle the auditing of file operations
77 * @profile: the profile being enforced (NOT NULL)
78 * @perms: the permissions computed for the request (NOT NULL)
79 * @op: operation being mediated
80 * @request: permissions requested
81 * @name: name of object being mediated (MAYBE NULL)
82 * @target: name of target (MAYBE NULL)
83 * @tlabel: target label (MAY BE NULL)
85 * @info: extra information message (MAYBE NULL)
86 * @error: 0 if operation allowed else failure error code
88 * Returns: %0 or error on failure
90 int aa_audit_file(struct aa_profile
*profile
, struct aa_perms
*perms
,
91 const char *op
, u32 request
, const char *name
,
92 const char *target
, struct aa_label
*tlabel
,
93 kuid_t ouid
, const char *info
, int error
)
95 int type
= AUDIT_APPARMOR_AUTO
;
96 DEFINE_AUDIT_DATA(sa
, LSM_AUDIT_DATA_TASK
, op
);
99 aad(&sa
)->request
= request
;
100 aad(&sa
)->name
= name
;
101 aad(&sa
)->fs
.target
= target
;
102 aad(&sa
)->peer
= tlabel
;
103 aad(&sa
)->fs
.ouid
= ouid
;
104 aad(&sa
)->info
= info
;
105 aad(&sa
)->error
= error
;
108 if (likely(!aad(&sa
)->error
)) {
109 u32 mask
= perms
->audit
;
111 if (unlikely(AUDIT_MODE(profile
) == AUDIT_ALL
))
114 /* mask off perms that are not being force audited */
115 aad(&sa
)->request
&= mask
;
117 if (likely(!aad(&sa
)->request
))
119 type
= AUDIT_APPARMOR_AUDIT
;
121 /* only report permissions that were denied */
122 aad(&sa
)->request
= aad(&sa
)->request
& ~perms
->allow
;
123 AA_BUG(!aad(&sa
)->request
);
125 if (aad(&sa
)->request
& perms
->kill
)
126 type
= AUDIT_APPARMOR_KILL
;
128 /* quiet known rejects, assumes quiet and kill do not overlap */
129 if ((aad(&sa
)->request
& perms
->quiet
) &&
130 AUDIT_MODE(profile
) != AUDIT_NOQUIET
&&
131 AUDIT_MODE(profile
) != AUDIT_ALL
)
132 aad(&sa
)->request
&= ~perms
->quiet
;
134 if (!aad(&sa
)->request
)
135 return aad(&sa
)->error
;
138 aad(&sa
)->denied
= aad(&sa
)->request
& ~perms
->allow
;
139 return aa_audit(type
, profile
, &sa
, file_audit_cb
);
143 * is_deleted - test if a file has been completely unlinked
144 * @dentry: dentry of file to test for deletion (NOT NULL)
146 * Returns: true if deleted else false
148 static inline bool is_deleted(struct dentry
*dentry
)
150 if (d_unlinked(dentry
) && d_backing_inode(dentry
)->i_nlink
== 0)
155 static int path_name(const char *op
, struct aa_label
*label
,
156 const struct path
*path
, int flags
, char *buffer
,
157 const char **name
, struct path_cond
*cond
, u32 request
)
159 struct aa_profile
*profile
;
160 const char *info
= NULL
;
163 error
= aa_path_name(path
, flags
, buffer
, name
, &info
,
164 labels_profile(label
)->disconnected
);
166 fn_for_each_confined(label
, profile
,
167 aa_audit_file(profile
, &nullperms
, op
, request
, *name
,
168 NULL
, NULL
, cond
->uid
, info
, error
));
176 * map_old_perms - map old file perms layout to the new layout
177 * @old: permission set in old mapping
179 * Returns: new permission mapping
181 static u32
map_old_perms(u32 old
)
185 new |= AA_MAY_GETATTR
| AA_MAY_OPEN
;
187 new |= AA_MAY_SETATTR
| AA_MAY_CREATE
| AA_MAY_DELETE
|
188 AA_MAY_CHMOD
| AA_MAY_CHOWN
| AA_MAY_OPEN
;
191 /* the old mapping lock and link_subset flags where overlaid
192 * and use was determined by part of a pair that they were in
195 new |= AA_MAY_LOCK
| AA_LINK_SUBSET
;
196 if (old
& 0x40) /* AA_EXEC_MMAP */
203 * aa_compute_fperms - convert dfa compressed perms to internal perms
204 * @dfa: dfa to compute perms for (NOT NULL)
205 * @state: state in dfa
206 * @cond: conditions to consider (NOT NULL)
208 * TODO: convert from dfa + state to permission entry, do computation conversion
211 * Returns: computed permission set
213 struct aa_perms
aa_compute_fperms(struct aa_dfa
*dfa
, unsigned int state
,
214 struct path_cond
*cond
)
216 /* FIXME: change over to new dfa format
217 * currently file perms are encoded in the dfa, new format
218 * splits the permissions from the dfa. This mapping can be
219 * done at profile load
221 struct aa_perms perms
= { };
223 if (uid_eq(current_fsuid(), cond
->uid
)) {
224 perms
.allow
= map_old_perms(dfa_user_allow(dfa
, state
));
225 perms
.audit
= map_old_perms(dfa_user_audit(dfa
, state
));
226 perms
.quiet
= map_old_perms(dfa_user_quiet(dfa
, state
));
227 perms
.xindex
= dfa_user_xindex(dfa
, state
);
229 perms
.allow
= map_old_perms(dfa_other_allow(dfa
, state
));
230 perms
.audit
= map_old_perms(dfa_other_audit(dfa
, state
));
231 perms
.quiet
= map_old_perms(dfa_other_quiet(dfa
, state
));
232 perms
.xindex
= dfa_other_xindex(dfa
, state
);
234 perms
.allow
|= AA_MAY_GETATTR
;
236 /* change_profile wasn't determined by ownership in old mapping */
237 if (ACCEPT_TABLE(dfa
)[state
] & 0x80000000)
238 perms
.allow
|= AA_MAY_CHANGE_PROFILE
;
239 if (ACCEPT_TABLE(dfa
)[state
] & 0x40000000)
240 perms
.allow
|= AA_MAY_ONEXEC
;
246 * aa_str_perms - find permission that match @name
247 * @dfa: to match against (MAYBE NULL)
248 * @state: state to start matching in
249 * @name: string to match against dfa (NOT NULL)
250 * @cond: conditions to consider for permission set computation (NOT NULL)
251 * @perms: Returns - the permissions found when matching @name
253 * Returns: the final state in @dfa when beginning @start and walking @name
255 unsigned int aa_str_perms(struct aa_dfa
*dfa
, unsigned int start
,
256 const char *name
, struct path_cond
*cond
,
257 struct aa_perms
*perms
)
260 state
= aa_dfa_match(dfa
, start
, name
);
261 *perms
= aa_compute_fperms(dfa
, state
, cond
);
266 int __aa_path_perm(const char *op
, struct aa_profile
*profile
, const char *name
,
267 u32 request
, struct path_cond
*cond
, int flags
,
268 struct aa_perms
*perms
)
272 if (profile_unconfined(profile
))
274 aa_str_perms(profile
->file
.dfa
, profile
->file
.start
, name
, cond
, perms
);
275 if (request
& ~perms
->allow
)
277 return aa_audit_file(profile
, perms
, op
, request
, name
, NULL
, NULL
,
282 static int profile_path_perm(const char *op
, struct aa_profile
*profile
,
283 const struct path
*path
, char *buffer
, u32 request
,
284 struct path_cond
*cond
, int flags
,
285 struct aa_perms
*perms
)
290 if (profile_unconfined(profile
))
293 error
= path_name(op
, &profile
->label
, path
,
294 flags
| profile
->path_flags
, buffer
, &name
, cond
,
298 return __aa_path_perm(op
, profile
, name
, request
, cond
, flags
,
303 * aa_path_perm - do permissions check & audit for @path
304 * @op: operation being checked
305 * @label: profile being enforced (NOT NULL)
306 * @path: path to check permissions of (NOT NULL)
307 * @flags: any additional path flags beyond what the profile specifies
308 * @request: requested permissions
309 * @cond: conditional info for this request (NOT NULL)
311 * Returns: %0 else error if access denied or other error
313 int aa_path_perm(const char *op
, struct aa_label
*label
,
314 const struct path
*path
, int flags
, u32 request
,
315 struct path_cond
*cond
)
317 struct aa_perms perms
= {};
318 struct aa_profile
*profile
;
322 flags
|= PATH_DELEGATE_DELETED
| (S_ISDIR(cond
->mode
) ? PATH_IS_DIR
:
324 buffer
= aa_get_buffer(false);
327 error
= fn_for_each_confined(label
, profile
,
328 profile_path_perm(op
, profile
, path
, buffer
, request
,
329 cond
, flags
, &perms
));
331 aa_put_buffer(buffer
);
337 * xindex_is_subset - helper for aa_path_link
338 * @link: link permission set
339 * @target: target permission set
341 * test target x permissions are equal OR a subset of link x permissions
342 * this is done as part of the subset test, where a hardlink must have
343 * a subset of permissions that the target has.
345 * Returns: true if subset else false
347 static inline bool xindex_is_subset(u32 link
, u32 target
)
349 if (((link
& ~AA_X_UNSAFE
) != (target
& ~AA_X_UNSAFE
)) ||
350 ((link
& AA_X_UNSAFE
) && !(target
& AA_X_UNSAFE
)))
356 static int profile_path_link(struct aa_profile
*profile
,
357 const struct path
*link
, char *buffer
,
358 const struct path
*target
, char *buffer2
,
359 struct path_cond
*cond
)
361 const char *lname
, *tname
= NULL
;
362 struct aa_perms lperms
= {}, perms
;
363 const char *info
= NULL
;
364 u32 request
= AA_MAY_LINK
;
368 error
= path_name(OP_LINK
, &profile
->label
, link
, profile
->path_flags
,
369 buffer
, &lname
, cond
, AA_MAY_LINK
);
373 /* buffer2 freed below, tname is pointer in buffer2 */
374 error
= path_name(OP_LINK
, &profile
->label
, target
, profile
->path_flags
,
375 buffer2
, &tname
, cond
, AA_MAY_LINK
);
380 /* aa_str_perms - handles the case of the dfa being NULL */
381 state
= aa_str_perms(profile
->file
.dfa
, profile
->file
.start
, lname
,
384 if (!(lperms
.allow
& AA_MAY_LINK
))
387 /* test to see if target can be paired with link */
388 state
= aa_dfa_null_transition(profile
->file
.dfa
, state
);
389 aa_str_perms(profile
->file
.dfa
, state
, tname
, cond
, &perms
);
391 /* force audit/quiet masks for link are stored in the second entry
394 lperms
.audit
= perms
.audit
;
395 lperms
.quiet
= perms
.quiet
;
396 lperms
.kill
= perms
.kill
;
398 if (!(perms
.allow
& AA_MAY_LINK
)) {
399 info
= "target restricted";
404 /* done if link subset test is not required */
405 if (!(perms
.allow
& AA_LINK_SUBSET
))
408 /* Do link perm subset test requiring allowed permission on link are
409 * a subset of the allowed permissions on target.
411 aa_str_perms(profile
->file
.dfa
, profile
->file
.start
, tname
, cond
,
414 /* AA_MAY_LINK is not considered in the subset test */
415 request
= lperms
.allow
& ~AA_MAY_LINK
;
416 lperms
.allow
&= perms
.allow
| AA_MAY_LINK
;
418 request
|= AA_AUDIT_FILE_MASK
& (lperms
.allow
& ~perms
.allow
);
419 if (request
& ~lperms
.allow
) {
421 } else if ((lperms
.allow
& MAY_EXEC
) &&
422 !xindex_is_subset(lperms
.xindex
, perms
.xindex
)) {
423 lperms
.allow
&= ~MAY_EXEC
;
425 info
= "link not subset of target";
433 return aa_audit_file(profile
, &lperms
, OP_LINK
, request
, lname
, tname
,
434 NULL
, cond
->uid
, info
, error
);
438 * aa_path_link - Handle hard link permission check
439 * @label: the label being enforced (NOT NULL)
440 * @old_dentry: the target dentry (NOT NULL)
441 * @new_dir: directory the new link will be created in (NOT NULL)
442 * @new_dentry: the link being created (NOT NULL)
444 * Handle the permission test for a link & target pair. Permission
445 * is encoded as a pair where the link permission is determined
446 * first, and if allowed, the target is tested. The target test
447 * is done from the point of the link match (not start of DFA)
448 * making the target permission dependent on the link permission match.
450 * The subset test if required forces that permissions granted
451 * on link are a subset of the permission granted to target.
453 * Returns: %0 if allowed else error
455 int aa_path_link(struct aa_label
*label
, struct dentry
*old_dentry
,
456 const struct path
*new_dir
, struct dentry
*new_dentry
)
458 struct path link
= { .mnt
= new_dir
->mnt
, .dentry
= new_dentry
};
459 struct path target
= { .mnt
= new_dir
->mnt
, .dentry
= old_dentry
};
460 struct path_cond cond
= {
461 d_backing_inode(old_dentry
)->i_uid
,
462 d_backing_inode(old_dentry
)->i_mode
464 char *buffer
= NULL
, *buffer2
= NULL
;
465 struct aa_profile
*profile
;
468 /* buffer freed below, lname is pointer in buffer */
469 buffer
= aa_get_buffer(false);
470 buffer2
= aa_get_buffer(false);
472 if (!buffer
|| !buffer2
)
475 error
= fn_for_each_confined(label
, profile
,
476 profile_path_link(profile
, &link
, buffer
, &target
,
479 aa_put_buffer(buffer
);
480 aa_put_buffer(buffer2
);
484 static void update_file_ctx(struct aa_file_ctx
*fctx
, struct aa_label
*label
,
487 struct aa_label
*l
, *old
;
489 /* update caching of label on file_ctx */
490 spin_lock(&fctx
->lock
);
491 old
= rcu_dereference_protected(fctx
->label
,
492 lockdep_is_held(&fctx
->lock
));
493 l
= aa_label_merge(old
, label
, GFP_ATOMIC
);
496 rcu_assign_pointer(fctx
->label
, l
);
500 fctx
->allow
|= request
;
502 spin_unlock(&fctx
->lock
);
505 static int __file_path_perm(const char *op
, struct aa_label
*label
,
506 struct aa_label
*flabel
, struct file
*file
,
507 u32 request
, u32 denied
, bool in_atomic
)
509 struct aa_profile
*profile
;
510 struct aa_perms perms
= {};
511 struct path_cond cond
= {
512 .uid
= file_inode(file
)->i_uid
,
513 .mode
= file_inode(file
)->i_mode
518 /* revalidation due to label out of date. No revocation at this time */
519 if (!denied
&& aa_label_is_subset(flabel
, label
))
520 /* TODO: check for revocation on stale profiles */
523 flags
= PATH_DELEGATE_DELETED
| (S_ISDIR(cond
.mode
) ? PATH_IS_DIR
: 0);
524 buffer
= aa_get_buffer(in_atomic
);
528 /* check every profile in task label not in current cache */
529 error
= fn_for_each_not_in_set(flabel
, label
, profile
,
530 profile_path_perm(op
, profile
, &file
->f_path
, buffer
,
531 request
, &cond
, flags
, &perms
));
532 if (denied
&& !error
) {
534 * check every profile in file label that was not tested
535 * in the initial check above.
537 * TODO: cache full perms so this only happens because of
539 * TODO: don't audit here
542 error
= fn_for_each(label
, profile
,
543 profile_path_perm(op
, profile
, &file
->f_path
,
544 buffer
, request
, &cond
, flags
,
547 error
= fn_for_each_not_in_set(label
, flabel
, profile
,
548 profile_path_perm(op
, profile
, &file
->f_path
,
549 buffer
, request
, &cond
, flags
,
553 update_file_ctx(file_ctx(file
), label
, request
);
555 aa_put_buffer(buffer
);
560 static int __file_sock_perm(const char *op
, struct aa_label
*label
,
561 struct aa_label
*flabel
, struct file
*file
,
562 u32 request
, u32 denied
)
564 struct socket
*sock
= (struct socket
*) file
->private_data
;
569 /* revalidation due to label out of date. No revocation at this time */
570 if (!denied
&& aa_label_is_subset(flabel
, label
))
573 /* TODO: improve to skip profiles cached in flabel */
574 error
= aa_sock_file_perm(label
, op
, request
, sock
);
576 /* TODO: improve to skip profiles checked above */
577 /* check every profile in file label to is cached */
578 last_error(error
, aa_sock_file_perm(flabel
, op
, request
, sock
));
581 update_file_ctx(file_ctx(file
), label
, request
);
587 * aa_file_perm - do permission revalidation check & audit for @file
588 * @op: operation being checked
589 * @label: label being enforced (NOT NULL)
590 * @file: file to revalidate access permissions on (NOT NULL)
591 * @request: requested permissions
592 * @in_atomic: whether allocations need to be done in atomic context
594 * Returns: %0 if access allowed else error
596 int aa_file_perm(const char *op
, struct aa_label
*label
, struct file
*file
,
597 u32 request
, bool in_atomic
)
599 struct aa_file_ctx
*fctx
;
600 struct aa_label
*flabel
;
607 fctx
= file_ctx(file
);
610 flabel
= rcu_dereference(fctx
->label
);
613 /* revalidate access, if task is unconfined, or the cached cred
614 * doesn't match or if the request is for more permissions than
617 * Note: the test for !unconfined(flabel) is to handle file
618 * delegation from unconfined tasks
620 denied
= request
& ~fctx
->allow
;
621 if (unconfined(label
) || unconfined(flabel
) ||
622 (!denied
&& aa_label_is_subset(flabel
, label
))) {
627 flabel
= aa_get_newest_label(flabel
);
629 /* TODO: label cross check */
631 if (file
->f_path
.mnt
&& path_mediated_fs(file
->f_path
.dentry
))
632 error
= __file_path_perm(op
, label
, flabel
, file
, request
,
635 else if (S_ISSOCK(file_inode(file
)->i_mode
))
636 error
= __file_sock_perm(op
, label
, flabel
, file
, request
,
638 aa_put_label(flabel
);
644 static void revalidate_tty(struct aa_label
*label
)
646 struct tty_struct
*tty
;
649 tty
= get_current_tty();
653 spin_lock(&tty
->files_lock
);
654 if (!list_empty(&tty
->tty_files
)) {
655 struct tty_file_private
*file_priv
;
657 /* TODO: Revalidate access to controlling tty. */
658 file_priv
= list_first_entry(&tty
->tty_files
,
659 struct tty_file_private
, list
);
660 file
= file_priv
->file
;
662 if (aa_file_perm(OP_INHERIT
, label
, file
, MAY_READ
| MAY_WRITE
,
666 spin_unlock(&tty
->files_lock
);
673 static int match_file(const void *p
, struct file
*file
, unsigned int fd
)
675 struct aa_label
*label
= (struct aa_label
*)p
;
677 if (aa_file_perm(OP_INHERIT
, label
, file
, aa_map_file_to_perms(file
),
684 /* based on selinux's flush_unauthorized_files */
685 void aa_inherit_files(const struct cred
*cred
, struct files_struct
*files
)
687 struct aa_label
*label
= aa_get_newest_cred_label(cred
);
688 struct file
*devnull
= NULL
;
691 revalidate_tty(label
);
693 /* Revalidate access to inherited open files. */
694 n
= iterate_fd(files
, 0, match_file
, label
);
695 if (!n
) /* none found? */
698 devnull
= dentry_open(&aa_null
, O_RDWR
, cred
);
701 /* replace all the matching ones with this */
703 replace_fd(n
- 1, devnull
, 0);
704 } while ((n
= iterate_fd(files
, n
, match_file
, label
)) != 0);