diff options
Diffstat (limited to 'security/apparmor')
-rw-r--r-- | security/apparmor/apparmorfs.c | 59 | ||||
-rw-r--r-- | security/apparmor/audit.c | 3 | ||||
-rw-r--r-- | security/apparmor/domain.c | 49 | ||||
-rw-r--r-- | security/apparmor/file.c | 12 | ||||
-rw-r--r-- | security/apparmor/include/domain.h | 2 | ||||
-rw-r--r-- | security/apparmor/include/label.h | 2 | ||||
-rw-r--r-- | security/apparmor/include/match.h | 11 | ||||
-rw-r--r-- | security/apparmor/label.c | 60 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 9 | ||||
-rw-r--r-- | security/apparmor/match.c | 58 | ||||
-rw-r--r-- | security/apparmor/path.c | 2 | ||||
-rw-r--r-- | security/apparmor/policy.c | 1 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 58 |
13 files changed, 195 insertions, 131 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 280741fc0f5f..5fd4a64e431f 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -341,38 +341,6 @@ static struct dentry *aafs_create_dir(const char *name, struct dentry *parent) } /** - * aafs_create_symlink - create a symlink in the apparmorfs filesystem - * @name: name of dentry to create - * @parent: parent directory for this dentry - * @target: if symlink, symlink target string - * @private: private data - * @iops: struct of inode_operations that should be used - * - * If @target parameter is %NULL, then the @iops parameter needs to be - * setup to handle .readlink and .get_link inode_operations. - */ -static struct dentry *aafs_create_symlink(const char *name, - struct dentry *parent, - const char *target, - void *private, - const struct inode_operations *iops) -{ - struct dentry *dent; - char *link = NULL; - - if (target) { - if (!link) - return ERR_PTR(-ENOMEM); - } - dent = aafs_create(name, S_IFLNK | 0444, parent, private, link, NULL, - iops); - if (IS_ERR(dent)) - kfree(link); - - return dent; -} - -/** * aafs_remove - removes a file or directory from the apparmorfs filesystem * * @dentry: dentry of the file/directory/symlink to removed. @@ -454,7 +422,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, */ error = aa_may_manage_policy(label, ns, mask); if (error) - return error; + goto end_section; data = aa_simple_write_to_buffer(buf, size, size, pos); error = PTR_ERR(data); @@ -462,6 +430,7 @@ static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, error = aa_replace_profiles(ns, label, mask, data); aa_put_loaddata(data); } +end_section: end_current_label_crit_section(label); return error; @@ -623,7 +592,7 @@ static __poll_t ns_revision_poll(struct file *file, poll_table *pt) void __aa_bump_ns_revision(struct aa_ns *ns) { - WRITE_ONCE(ns->revision, ns->revision + 1); + WRITE_ONCE(ns->revision, READ_ONCE(ns->revision) + 1); wake_up_interruptible(&ns->wait); } @@ -839,7 +808,7 @@ static ssize_t query_label(char *buf, size_t buf_len, struct multi_transaction { struct kref count; ssize_t size; - char data[0]; + char data[]; }; #define MULTI_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct multi_transaction)) @@ -1762,25 +1731,25 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent) } if (profile->rawdata) { - dent = aafs_create_symlink("raw_sha1", dir, NULL, - profile->label.proxy, - &rawdata_link_sha1_iops); + dent = aafs_create("raw_sha1", S_IFLNK | 0444, dir, + profile->label.proxy, NULL, NULL, + &rawdata_link_sha1_iops); if (IS_ERR(dent)) goto fail; aa_get_proxy(profile->label.proxy); profile->dents[AAFS_PROF_RAW_HASH] = dent; - dent = aafs_create_symlink("raw_abi", dir, NULL, - profile->label.proxy, - &rawdata_link_abi_iops); + dent = aafs_create("raw_abi", S_IFLNK | 0444, dir, + profile->label.proxy, NULL, NULL, + &rawdata_link_abi_iops); if (IS_ERR(dent)) goto fail; aa_get_proxy(profile->label.proxy); profile->dents[AAFS_PROF_RAW_ABI] = dent; - dent = aafs_create_symlink("raw_data", dir, NULL, - profile->label.proxy, - &rawdata_link_data_iops); + dent = aafs_create("raw_data", S_IFLNK | 0444, dir, + profile->label.proxy, NULL, NULL, + &rawdata_link_data_iops); if (IS_ERR(dent)) goto fail; aa_get_proxy(profile->label.proxy); @@ -2363,6 +2332,8 @@ static struct aa_sfs_entry aa_sfs_entry_versions[] = { static struct aa_sfs_entry aa_sfs_entry_policy[] = { AA_SFS_DIR("versions", aa_sfs_entry_versions), AA_SFS_FILE_BOOLEAN("set_load", 1), + /* number of out of band transitions supported */ + AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED), { } }; diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 5a98661a8b46..597732503815 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -197,8 +197,9 @@ int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr, GFP_KERNEL, true, false); if (IS_ERR(rule->label)) { + int err = PTR_ERR(rule->label); aa_audit_rule_free(rule); - return PTR_ERR(rule->label); + return err; } *vrule = rule; diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 6ceb74e0f789..1c898055a476 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -320,8 +320,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, might_sleep(); /* transition from exec match to xattr set */ - state = aa_dfa_null_transition(profile->xmatch, state); - + state = aa_dfa_outofband_transition(profile->xmatch, state); d = bprm->file->f_path.dentry; for (i = 0; i < profile->xattr_count; i++) { @@ -330,7 +329,13 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, if (size >= 0) { u32 perm; - /* Check the xattr value, not just presence */ + /* + * Check the xattr presence before value. This ensure + * that not present xattr can be distinguished from a 0 + * length value or rule that matches any value + */ + state = aa_dfa_null_transition(profile->xmatch, state); + /* Check xattr value */ state = aa_dfa_match_len(profile->xmatch, state, value, size); perm = dfa_user_allow(profile->xmatch, state); @@ -340,7 +345,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm, } } /* transition to next element */ - state = aa_dfa_null_transition(profile->xmatch, state); + state = aa_dfa_outofband_transition(profile->xmatch, state); if (size < 0) { /* * No xattr match, so verify if transition to @@ -620,8 +625,6 @@ static struct aa_label *profile_transition(struct aa_profile *profile, bool *secure_exec) { struct aa_label *new = NULL; - struct aa_profile *component; - struct label_it i; const char *info = NULL, *name = NULL, *target = NULL; unsigned int state = profile->file.start; struct aa_perms perms = {}; @@ -670,21 +673,6 @@ static struct aa_label *profile_transition(struct aa_profile *profile, info = "profile transition not found"; /* remove MAY_EXEC to audit as failure */ perms.allow &= ~MAY_EXEC; - } else { - /* verify that each component's xattr requirements are - * met, and fail execution otherwise - */ - label_for_each(i, new, component) { - if (aa_xattrs_match(bprm, component, state) < - 0) { - error = -EACCES; - info = "required xattrs not present"; - perms.allow &= ~MAY_EXEC; - aa_put_label(new); - new = NULL; - goto audit; - } - } } } else if (COMPLAIN_MODE(profile)) { /* no exec permission - learning mode */ @@ -854,14 +842,14 @@ static struct aa_label *handle_onexec(struct aa_label *label, } /** - * apparmor_bprm_set_creds - set the new creds on the bprm struct + * apparmor_bprm_creds_for_exec - Update the new creds on the bprm struct * @bprm: binprm for the exec (NOT NULL) * * Returns: %0 or error on failure * * TODO: once the other paths are done see if we can't refactor into a fn */ -int apparmor_bprm_set_creds(struct linux_binprm *bprm) +int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) { struct aa_task_ctx *ctx; struct aa_label *label, *new = NULL; @@ -875,9 +863,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) file_inode(bprm->file)->i_mode }; - if (bprm->called_set_creds) - return 0; - ctx = task_ctx(current); AA_BUG(!cred_label(bprm->cred)); AA_BUG(!ctx); @@ -929,7 +914,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) * aways results in a further reduction of permissions. */ if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && - !unconfined(label) && !aa_label_is_subset(new, ctx->nnp)) { + !unconfined(label) && + !aa_label_is_unconfined_subset(new, ctx->nnp)) { error = -EPERM; info = "no new privs"; goto audit; @@ -1207,7 +1193,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) * reduce restrictions. */ if (task_no_new_privs(current) && !unconfined(label) && - !aa_label_is_subset(new, ctx->nnp)) { + !aa_label_is_unconfined_subset(new, ctx->nnp)) { /* not an apparmor denial per se, so don't log it */ AA_DEBUG("no_new_privs - change_hat denied"); error = -EPERM; @@ -1228,7 +1214,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags) * reduce restrictions. */ if (task_no_new_privs(current) && !unconfined(label) && - !aa_label_is_subset(previous, ctx->nnp)) { + !aa_label_is_unconfined_subset(previous, ctx->nnp)) { /* not an apparmor denial per se, so don't log it */ AA_DEBUG("no_new_privs - change_hat denied"); error = -EPERM; @@ -1328,6 +1314,7 @@ int aa_change_profile(const char *fqname, int flags) ctx->nnp = aa_get_label(label); if (!fqname || !*fqname) { + aa_put_label(label); AA_DEBUG("no profile name"); return -EINVAL; } @@ -1346,8 +1333,6 @@ int aa_change_profile(const char *fqname, int flags) op = OP_CHANGE_PROFILE; } - label = aa_get_current_label(); - if (*fqname == '&') { stack = true; /* don't have label_parse() do stacking */ @@ -1424,7 +1409,7 @@ check: * reduce restrictions. */ if (task_no_new_privs(current) && !unconfined(label) && - !aa_label_is_subset(new, ctx->nnp)) { + !aa_label_is_unconfined_subset(new, ctx->nnp)) { /* not an apparmor denial per se, so don't log it */ AA_DEBUG("no_new_privs - change_hat denied"); error = -EPERM; diff --git a/security/apparmor/file.c b/security/apparmor/file.c index f1caf3674e1c..9a2d14b7c9f8 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c @@ -154,13 +154,13 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, * is_deleted - test if a file has been completely unlinked * @dentry: dentry of file to test for deletion (NOT NULL) * - * Returns: %1 if deleted else %0 + * 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 1; - return 0; + return true; + return false; } static int path_name(const char *op, struct aa_label *label, @@ -353,15 +353,15 @@ int aa_path_perm(const char *op, struct aa_label *label, * this is done as part of the subset test, where a hardlink must have * a subset of permissions that the target has. * - * Returns: %1 if subset else %0 + * Returns: true if subset else false */ static inline bool xindex_is_subset(u32 link, u32 target) { if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) || ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE))) - return 0; + return false; - return 1; + return true; } static int profile_path_link(struct aa_profile *profile, diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h index 21b875fe2d37..d14928fe1c6f 100644 --- a/security/apparmor/include/domain.h +++ b/security/apparmor/include/domain.h @@ -30,7 +30,7 @@ struct aa_domain { struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, const char **name); -int apparmor_bprm_set_creds(struct linux_binprm *bprm); +int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm); void aa_free_domain_entries(struct aa_domain *domain); int aa_change_hat(const char *hats[], int count, u64 token, int flags); diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index 47942c4ba7ca..1e90384b1523 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -275,12 +275,14 @@ void aa_labelset_destroy(struct aa_labelset *ls); void aa_labelset_init(struct aa_labelset *ls); void __aa_labelset_update_subtree(struct aa_ns *ns); +void aa_label_destroy(struct aa_label *label); void aa_label_free(struct aa_label *label); void aa_label_kref(struct kref *kref); bool aa_label_init(struct aa_label *label, int size, gfp_t gfp); struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp); bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub); +bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub); struct aa_profile *__aa_label_next_not_in_set(struct label_it *I, struct aa_label *set, struct aa_label *sub); diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h index e23f4aadc1ff..884489590588 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -37,6 +37,10 @@ #define YYTH_MAGIC 0x1B5E783D #define YYTH_FLAG_DIFF_ENCODE 1 +#define YYTH_FLAG_OOB_TRANS 2 +#define YYTH_FLAGS (YYTH_FLAG_DIFF_ENCODE | YYTH_FLAG_OOB_TRANS) + +#define MAX_OOB_SUPPORTED 1 struct table_set_header { u32 th_magic; /* YYTH_MAGIC */ @@ -94,6 +98,7 @@ struct table_header { struct aa_dfa { struct kref count; u16 flags; + u32 max_oob; struct table_header *tables[YYTD_ID_TSIZE]; }; @@ -127,6 +132,8 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, const char *str); unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state, const char c); +unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa, + unsigned int state); unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start, const char *str, const char **retpos); unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start, @@ -181,5 +188,9 @@ static inline void aa_put_dfa(struct aa_dfa *dfa) #define MATCH_FLAG_DIFF_ENCODE 0x80000000 #define MARK_DIFF_ENCODE 0x40000000 +#define MATCH_FLAG_OOB_TRANSITION 0x20000000 +#define MATCH_FLAGS_MASK 0xff000000 +#define MATCH_FLAGS_VALID (MATCH_FLAG_DIFF_ENCODE | MATCH_FLAG_OOB_TRANSITION) +#define MATCH_FLAGS_INVALID (MATCH_FLAGS_MASK & ~MATCH_FLAGS_VALID) #endif /* __AA_MATCH_H */ diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 470693239e64..e68bcedca976 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -309,10 +309,8 @@ out: } -static void label_destroy(struct aa_label *label) +void aa_label_destroy(struct aa_label *label) { - struct aa_label *tmp; - AA_BUG(!label); if (!label_isprofile(label)) { @@ -328,16 +326,13 @@ static void label_destroy(struct aa_label *label) } } - if (rcu_dereference_protected(label->proxy->label, true) == label) - rcu_assign_pointer(label->proxy->label, NULL); - + if (label->proxy) { + if (rcu_dereference_protected(label->proxy->label, true) == label) + rcu_assign_pointer(label->proxy->label, NULL); + aa_put_proxy(label->proxy); + } aa_free_secid(label->secid); - tmp = rcu_dereference_protected(label->proxy->label, true); - if (tmp == label) - rcu_assign_pointer(label->proxy->label, NULL); - - aa_put_proxy(label->proxy); label->proxy = (struct aa_proxy *) PROXY_POISON + 1; } @@ -346,7 +341,7 @@ void aa_label_free(struct aa_label *label) if (!label) return; - label_destroy(label); + aa_label_destroy(label); kfree(label); } @@ -550,6 +545,39 @@ bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub) return __aa_label_next_not_in_set(&i, set, sub) == NULL; } +/** + * aa_label_is_unconfined_subset - test if @sub is a subset of @set + * @set: label to test against + * @sub: label to test if is subset of @set + * + * This checks for subset but taking into account unconfined. IF + * @sub contains an unconfined profile that does not have a matching + * unconfined in @set then this will not cause the test to fail. + * Conversely we don't care about an unconfined in @set that is not in + * @sub + * + * Returns: true if @sub is special_subset of @set + * else false + */ +bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub) +{ + struct label_it i = { }; + struct aa_profile *p; + + AA_BUG(!set); + AA_BUG(!sub); + + if (sub == set) + return true; + + do { + p = __aa_label_next_not_in_set(&i, set, sub); + if (p && !profile_unconfined(p)) + break; + } while (p); + + return p == NULL; +} /** @@ -1531,13 +1559,13 @@ static const char *label_modename(struct aa_ns *ns, struct aa_label *label, label_for_each(i, label, profile) { if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { - if (profile->mode == APPARMOR_UNCONFINED) + count++; + if (profile == profile->ns->unconfined) /* special case unconfined so stacks with * unconfined don't report as mixed. ie. * profile_foo//&:ns1:unconfined (mixed) */ continue; - count++; if (mode == -1) mode = profile->mode; else if (mode != profile->mode) @@ -1749,13 +1777,13 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, AA_DEBUG("label print error"); return; } - seq_printf(f, "%s", str); + seq_puts(f, str); kfree(str); } else if (display_mode(ns, label, flags)) seq_printf(f, "%s (%s)", label->hname, label_modename(ns, label, flags)); else - seq_printf(f, "%s", label->hname); + seq_puts(f, label->hname); } void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index b621ad74f54a..ffeaee5ed968 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -804,7 +804,12 @@ static void apparmor_sk_clone_security(const struct sock *sk, struct aa_sk_ctx *ctx = SK_CTX(sk); struct aa_sk_ctx *new = SK_CTX(newsk); + if (new->label) + aa_put_label(new->label); new->label = aa_get_label(ctx->label); + + if (new->peer) + aa_put_label(new->peer); new->peer = aa_get_label(ctx->peer); } @@ -1232,7 +1237,7 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer), - LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds), + LSM_HOOK_INIT(bprm_creds_for_exec, apparmor_bprm_creds_for_exec), LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds), LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds), @@ -1696,7 +1701,7 @@ static int __init alloc_buffers(void) #ifdef CONFIG_SYSCTL static int apparmor_dointvec(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) + void *buffer, size_t *lenp, loff_t *ppos) { if (!policy_admin_capable(NULL)) return -EPERM; diff --git a/security/apparmor/match.c b/security/apparmor/match.c index 525ce22dc0e9..3e9e1eaf990e 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -97,6 +97,9 @@ static struct table_header *unpack_table(char *blob, size_t bsize) th.td_flags == YYTD_DATA8)) goto out; + /* if we have a table it must have some entries */ + if (th.td_lolen == 0) + goto out; tsize = table_size(th.td_lolen, th.td_flags); if (bsize < tsize) goto out; @@ -198,10 +201,32 @@ static int verify_dfa(struct aa_dfa *dfa) state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen; + if (state_count == 0) + goto out; for (i = 0; i < state_count; i++) { if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) && (DEFAULT_TABLE(dfa)[i] >= state_count)) goto out; + if (BASE_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) { + pr_err("AppArmor DFA state with invalid match flags"); + goto out; + } + if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE)) { + if (!(dfa->flags & YYTH_FLAG_DIFF_ENCODE)) { + pr_err("AppArmor DFA diff encoded transition state without header flag"); + goto out; + } + } + if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_OOB_TRANSITION)) { + if (base_idx(BASE_TABLE(dfa)[i]) < dfa->max_oob) { + pr_err("AppArmor DFA out of bad transition out of range"); + goto out; + } + if (!(dfa->flags & YYTH_FLAG_OOB_TRANS)) { + pr_err("AppArmor DFA out of bad transition state without header flag"); + goto out; + } + } if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) { pr_err("AppArmor DFA next/check upper bounds error\n"); goto out; @@ -304,9 +329,23 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags) goto fail; dfa->flags = ntohs(*(__be16 *) (data + 12)); - if (dfa->flags != 0 && dfa->flags != YYTH_FLAG_DIFF_ENCODE) + if (dfa->flags & ~(YYTH_FLAGS)) goto fail; + /* + * TODO: needed for dfa to support more than 1 oob + * if (dfa->flags & YYTH_FLAGS_OOB_TRANS) { + * if (hsize < 16 + 4) + * goto fail; + * dfa->max_oob = ntol(*(__be32 *) (data + 16)); + * if (dfa->max <= MAX_OOB_SUPPORTED) { + * pr_err("AppArmor DFA OOB greater than supported\n"); + * goto fail; + * } + * } + */ + dfa->max_oob = 1; + data += hsize; size -= hsize; @@ -495,6 +534,23 @@ unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state, return state; } +unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa, unsigned int state) +{ + u16 *def = DEFAULT_TABLE(dfa); + u32 *base = BASE_TABLE(dfa); + u16 *next = NEXT_TABLE(dfa); + u16 *check = CHECK_TABLE(dfa); + u32 b = (base)[(state)]; + + if (!(b & MATCH_FLAG_OOB_TRANSITION)) + return DFA_NOMATCH; + + /* No Equivalence class remapping for outofband transitions */ + match_char(state, def, base, next, check, -1); + + return state; +} + /** * aa_dfa_match_until - traverse @dfa until accept state or end of input * @dfa: the dfa to match @str against (NOT NULL) diff --git a/security/apparmor/path.c b/security/apparmor/path.c index c6da542de27b..b02dfdbff7cd 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c @@ -142,7 +142,7 @@ static int d_namespace_path(const struct path *path, char *buf, char **name, error = PTR_ERR(res); *name = buf; goto out; - }; + } } else if (!our_mnt(path->mnt)) connected = 0; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 269f2f53c0b1..af4f50fda9e3 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -242,6 +242,7 @@ void aa_free_profile(struct aa_profile *profile) kzfree(profile->hash); aa_put_loaddata(profile->rawdata); + aa_label_destroy(&profile->label); kzfree(profile); } diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 2d743c004bc4..b67322abcc33 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -243,11 +243,11 @@ fail: static bool unpack_X(struct aa_ext *e, enum aa_code code) { if (!inbounds(e, 1)) - return 0; + return false; if (*(u8 *) e->pos != code) - return 0; + return false; e->pos++; - return 1; + return true; } /** @@ -261,10 +261,10 @@ static bool unpack_X(struct aa_ext *e, enum aa_code code) * name element in the stream. If @name is NULL any name element will be * skipped and only the typecode will be tested. * - * Returns 1 on success (both type code and name tests match) and the read + * Returns true on success (both type code and name tests match) and the read * head is advanced past the headers * - * Returns: 0 if either match fails, the read head does not move + * Returns: false if either match fails, the read head does not move */ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) { @@ -289,11 +289,11 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) /* now check if type code matches */ if (unpack_X(e, code)) - return 1; + return true; fail: e->pos = pos; - return 0; + return false; } static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) @@ -306,12 +306,12 @@ static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) if (data) *data = get_unaligned((u8 *)e->pos); e->pos += sizeof(u8); - return 1; + return true; } fail: e->pos = pos; - return 0; + return false; } static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) @@ -324,12 +324,12 @@ static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) if (data) *data = le32_to_cpu(get_unaligned((__le32 *) e->pos)); e->pos += sizeof(u32); - return 1; + return true; } fail: e->pos = pos; - return 0; + return false; } static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) @@ -342,12 +342,12 @@ static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) if (data) *data = le64_to_cpu(get_unaligned((__le64 *) e->pos)); e->pos += sizeof(u64); - return 1; + return true; } fail: e->pos = pos; - return 0; + return false; } static size_t unpack_array(struct aa_ext *e, const char *name) @@ -472,7 +472,7 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e) * @e: serialized data extent information (NOT NULL) * @profile: profile to add the accept table to (NOT NULL) * - * Returns: 1 if table successfully unpacked + * Returns: true if table successfully unpacked */ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) { @@ -535,12 +535,12 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) if (!unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; } - return 1; + return true; fail: aa_free_domain_entries(&profile->file.trans); e->pos = saved_pos; - return 0; + return false; } static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile) @@ -565,11 +565,11 @@ static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile) goto fail; } - return 1; + return true; fail: e->pos = pos; - return 0; + return false; } static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) @@ -601,7 +601,7 @@ static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) goto fail; } - return 1; + return true; fail: if (profile->secmark) { @@ -613,7 +613,7 @@ fail: } e->pos = pos; - return 0; + return false; } static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) @@ -643,11 +643,11 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) if (!unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; } - return 1; + return true; fail: e->pos = pos; - return 0; + return false; } static u32 strhash(const void *data, u32 len, u32 seed) @@ -748,10 +748,14 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) goto fail; if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) profile->mode = APPARMOR_COMPLAIN; + else if (tmp == PACKED_MODE_ENFORCE) + profile->mode = APPARMOR_ENFORCE; else if (tmp == PACKED_MODE_KILL) profile->mode = APPARMOR_KILL; else if (tmp == PACKED_MODE_UNCONFINED) profile->mode = APPARMOR_UNCONFINED; + else + goto fail; if (!unpack_u32(e, &tmp, NULL)) goto fail; if (tmp) @@ -990,8 +994,8 @@ static bool verify_xindex(int xindex, int table_size) xtype = xindex & AA_X_TYPE_MASK; index = xindex & AA_X_INDEX_MASK; if (xtype == AA_X_TABLE && index >= table_size) - return 0; - return 1; + return false; + return true; } /* verify dfa xindexes are in range of transition tables */ @@ -1000,11 +1004,11 @@ static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size) int i; for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { if (!verify_xindex(dfa_user_xindex(dfa, i), table_size)) - return 0; + return false; if (!verify_xindex(dfa_other_xindex(dfa, i), table_size)) - return 0; + return false; } - return 1; + return true; } /** |