diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-15 00:42:09 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-15 00:42:09 +0300 |
commit | 93761c93e9da28d8a020777cee2a84133082b477 (patch) | |
tree | b84216293efb4b85724dcf83b27e099436e1509a /security/apparmor/file.c | |
parent | 64e7003c6b85626a533a67c1ba938b75a3db24e6 (diff) | |
parent | 4295c60bbe9e63e35d330546eeaa1d2b62dae303 (diff) | |
download | linux-93761c93e9da28d8a020777cee2a84133082b477.tar.xz |
Merge tag 'apparmor-pr-2022-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen:
"Features:
- switch to zstd compression for profile raw data
Cleanups:
- simplify obtaining the newest label on a cred
- remove useless static inline functions
- compute permission conversion on policy unpack
- refactor code to share common permissins
- refactor unpack to group policy backwards compatiblity code
- add __init annotation to aa_{setup/teardown}_dfa_engine()
Bug Fixes:
- fix a memleak in
- multi_transaction_new()
- free_ruleset()
- unpack_profile()
- alloc_ns()
- fix lockdep warning when removing a namespace
- fix regression in stacking due to label flags
- fix loading of child before parent
- fix kernel-doc comments that differ from fns
- fix spelling errors in comments
- store return value of unpack_perms_table() to signed variable"
* tag 'apparmor-pr-2022-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (64 commits)
apparmor: Fix uninitialized symbol 'array_size' in policy_unpack_test.c
apparmor: Add __init annotation to aa_{setup/teardown}_dfa_engine()
apparmor: Fix memleak in alloc_ns()
apparmor: Fix memleak issue in unpack_profile()
apparmor: fix a memleak in free_ruleset()
apparmor: Fix spelling of function name in comment block
apparmor: Use pointer to struct aa_label for lbs_cred
AppArmor: Fix kernel-doc
LSM: Fix kernel-doc
AppArmor: Fix kernel-doc
apparmor: Fix loading of child before parent
apparmor: refactor code that alloc null profiles
apparmor: fix obsoleted comments for aa_getprocattr() and audit_resource()
apparmor: remove useless static inline functions
apparmor: Fix unpack_profile() warn: passing zero to 'ERR_PTR'
apparmor: fix uninitialize table variable in error in unpack_trans_table
apparmor: store return value of unpack_perms_table() to signed variable
apparmor: Fix kunit test for out of bounds array
apparmor: Fix decompression of rawdata for read back to userspace
apparmor: Fix undefined references to zstd_ symbols
...
Diffstat (limited to 'security/apparmor/file.c')
-rw-r--r-- | security/apparmor/file.c | 125 |
1 files changed, 37 insertions, 88 deletions
diff --git a/security/apparmor/file.c b/security/apparmor/file.c index d43679894d23..cb3d3060d104 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -95,7 +95,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, kuid_t ouid, const char *info, int error) { int type = AUDIT_APPARMOR_AUTO; - DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op); + DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op); sa.u.tsk = NULL; aad(&sa)->request = request; @@ -141,19 +141,6 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, return aa_audit(type, profile, &sa, file_audit_cb); } -/** - * is_deleted - test if a file has been completely unlinked - * @dentry: dentry of file to test for deletion (NOT NULL) - * - * Returns: true if deleted else false - */ -static inline bool is_deleted(struct dentry *dentry) -{ - if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) - return true; - return false; -} - static int path_name(const char *op, struct aa_label *label, const struct path *path, int flags, char *buffer, const char **name, struct path_cond *cond, u32 request) @@ -175,73 +162,28 @@ static int path_name(const char *op, struct aa_label *label, } /** - * map_old_perms - map old file perms layout to the new layout - * @old: permission set in old mapping - * - * Returns: new permission mapping - */ -static u32 map_old_perms(u32 old) -{ - u32 new = old & 0xf; - if (old & MAY_READ) - new |= AA_MAY_GETATTR | AA_MAY_OPEN; - if (old & MAY_WRITE) - new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE | - AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN; - if (old & 0x10) - new |= AA_MAY_LINK; - /* the old mapping lock and link_subset flags where overlaid - * and use was determined by part of a pair that they were in - */ - if (old & 0x20) - new |= AA_MAY_LOCK | AA_LINK_SUBSET; - if (old & 0x40) /* AA_EXEC_MMAP */ - new |= AA_EXEC_MMAP; - - return new; -} - -/** - * aa_compute_fperms - convert dfa compressed perms to internal perms - * @dfa: dfa to compute perms for (NOT NULL) + * aa_lookup_fperms - convert dfa compressed perms to internal perms + * @dfa: dfa to lookup perms for (NOT NULL) * @state: state in dfa * @cond: conditions to consider (NOT NULL) * - * TODO: convert from dfa + state to permission entry, do computation conversion - * at load time. + * TODO: convert from dfa + state to permission entry * - * Returns: computed permission set + * Returns: a pointer to a file permission set */ -struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state, - struct path_cond *cond) +struct aa_perms default_perms = {}; +struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules, + aa_state_t state, struct path_cond *cond) { - /* FIXME: change over to new dfa format - * currently file perms are encoded in the dfa, new format - * splits the permissions from the dfa. This mapping can be - * done at profile load - */ - struct aa_perms perms = { }; + unsigned int index = ACCEPT_TABLE(file_rules->dfa)[state]; - if (uid_eq(current_fsuid(), cond->uid)) { - perms.allow = map_old_perms(dfa_user_allow(dfa, state)); - perms.audit = map_old_perms(dfa_user_audit(dfa, state)); - perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); - perms.xindex = dfa_user_xindex(dfa, state); - } else { - perms.allow = map_old_perms(dfa_other_allow(dfa, state)); - perms.audit = map_old_perms(dfa_other_audit(dfa, state)); - perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); - perms.xindex = dfa_other_xindex(dfa, state); - } - perms.allow |= AA_MAY_GETATTR; + if (!(file_rules->perms)) + return &default_perms; - /* change_profile wasn't determined by ownership in old mapping */ - if (ACCEPT_TABLE(dfa)[state] & 0x80000000) - perms.allow |= AA_MAY_CHANGE_PROFILE; - if (ACCEPT_TABLE(dfa)[state] & 0x40000000) - perms.allow |= AA_MAY_ONEXEC; + if (uid_eq(current_fsuid(), cond->uid)) + return &(file_rules->perms[index]); - return perms; + return &(file_rules->perms[index + 1]); } /** @@ -254,26 +196,30 @@ struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state, * * Returns: the final state in @dfa when beginning @start and walking @name */ -unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, - const char *name, struct path_cond *cond, - struct aa_perms *perms) +aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start, + const char *name, struct path_cond *cond, + struct aa_perms *perms) { - unsigned int state; - state = aa_dfa_match(dfa, start, name); - *perms = aa_compute_fperms(dfa, state, cond); + aa_state_t state; + state = aa_dfa_match(file_rules->dfa, start, name); + *perms = *(aa_lookup_fperms(file_rules, state, cond)); return state; } -int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, - u32 request, struct path_cond *cond, int flags, - struct aa_perms *perms) +static int __aa_path_perm(const char *op, struct aa_profile *profile, + const char *name, u32 request, + struct path_cond *cond, int flags, + struct aa_perms *perms) { + struct aa_ruleset *rules = list_first_entry(&profile->rules, + typeof(*rules), list); int e = 0; if (profile_unconfined(profile)) return 0; - aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); + aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + name, cond, perms); if (request & ~perms->allow) e = -EACCES; return aa_audit_file(profile, perms, op, request, name, NULL, NULL, @@ -360,11 +306,13 @@ static int profile_path_link(struct aa_profile *profile, const struct path *target, char *buffer2, struct path_cond *cond) { + struct aa_ruleset *rules = list_first_entry(&profile->rules, + typeof(*rules), list); const char *lname, *tname = NULL; struct aa_perms lperms = {}, perms; const char *info = NULL; u32 request = AA_MAY_LINK; - unsigned int state; + aa_state_t state; int error; error = path_name(OP_LINK, &profile->label, link, profile->path_flags, @@ -380,15 +328,16 @@ static int profile_path_link(struct aa_profile *profile, error = -EACCES; /* aa_str_perms - handles the case of the dfa being NULL */ - state = aa_str_perms(profile->file.dfa, profile->file.start, lname, + state = aa_str_perms(&(rules->file), + rules->file.start[AA_CLASS_FILE], lname, cond, &lperms); if (!(lperms.allow & AA_MAY_LINK)) goto audit; /* test to see if target can be paired with link */ - state = aa_dfa_null_transition(profile->file.dfa, state); - aa_str_perms(profile->file.dfa, state, tname, cond, &perms); + state = aa_dfa_null_transition(rules->file.dfa, state); + aa_str_perms(&(rules->file), state, tname, cond, &perms); /* force audit/quiet masks for link are stored in the second entry * in the link pair. @@ -410,8 +359,8 @@ static int profile_path_link(struct aa_profile *profile, /* Do link perm subset test requiring allowed permission on link are * a subset of the allowed permissions on target. */ - aa_str_perms(profile->file.dfa, profile->file.start, tname, cond, - &perms); + aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], + tname, cond, &perms); /* AA_MAY_LINK is not considered in the subset test */ request = lperms.allow & ~AA_MAY_LINK; |