diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/include/policy.h | 11 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 49 | ||||
-rw-r--r-- | security/selinux/avc.c | 10 | ||||
-rw-r--r-- | security/selinux/hooks.c | 39 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 12 |
5 files changed, 93 insertions, 28 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 1ce4e9bdac48..b5b4b8190e65 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -213,7 +213,16 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) return labels_profile(aa_get_newest_label(&p->label)); } -#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(unsigned char) (T)]) +static inline unsigned int PROFILE_MEDIATES(struct aa_profile *profile, + unsigned char class) +{ + if (class <= AA_CLASS_LAST) + return profile->policy.start[class]; + else + return aa_dfa_match_len(profile->policy.dfa, + profile->policy.start[0], &class, 1); +} + static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile, u16 AF) { unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET); diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 01957ce9252b..8cfc9493eefc 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -219,16 +219,21 @@ static void *kvmemdup(const void *src, size_t len) static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk) { size_t size = 0; + void *pos = e->pos; if (!inbounds(e, sizeof(u16))) - return 0; + goto fail; size = le16_to_cpu(get_unaligned((__le16 *) e->pos)); e->pos += sizeof(__le16); if (!inbounds(e, size)) - return 0; + goto fail; *chunk = e->pos; e->pos += size; return size; + +fail: + e->pos = pos; + return 0; } /* unpack control byte */ @@ -272,7 +277,7 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) char *tag = NULL; size_t size = unpack_u16_chunk(e, &tag); /* if a name is specified it must match. otherwise skip tag */ - if (name && (!size || strcmp(name, tag))) + if (name && (!size || tag[size-1] != '\0' || strcmp(name, tag))) goto fail; } else if (name) { /* if a name is specified and there is no name tag fail */ @@ -290,62 +295,84 @@ fail: static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) { + void *pos = e->pos; + if (unpack_nameX(e, AA_U8, name)) { if (!inbounds(e, sizeof(u8))) - return 0; + goto fail; if (data) *data = get_unaligned((u8 *)e->pos); e->pos += sizeof(u8); return 1; } + +fail: + e->pos = pos; return 0; } static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) { + void *pos = e->pos; + if (unpack_nameX(e, AA_U32, name)) { if (!inbounds(e, sizeof(u32))) - return 0; + goto fail; if (data) *data = le32_to_cpu(get_unaligned((__le32 *) e->pos)); e->pos += sizeof(u32); return 1; } + +fail: + e->pos = pos; return 0; } static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) { + void *pos = e->pos; + if (unpack_nameX(e, AA_U64, name)) { if (!inbounds(e, sizeof(u64))) - return 0; + goto fail; if (data) *data = le64_to_cpu(get_unaligned((__le64 *) e->pos)); e->pos += sizeof(u64); return 1; } + +fail: + e->pos = pos; return 0; } static size_t unpack_array(struct aa_ext *e, const char *name) { + void *pos = e->pos; + if (unpack_nameX(e, AA_ARRAY, name)) { int size; if (!inbounds(e, sizeof(u16))) - return 0; + goto fail; size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos)); e->pos += sizeof(u16); return size; } + +fail: + e->pos = pos; return 0; } static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) { + void *pos = e->pos; + if (unpack_nameX(e, AA_BLOB, name)) { u32 size; if (!inbounds(e, sizeof(u32))) - return 0; + goto fail; size = le32_to_cpu(get_unaligned((__le32 *) e->pos)); e->pos += sizeof(u32); if (inbounds(e, (size_t) size)) { @@ -354,6 +381,9 @@ static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) return size; } } + +fail: + e->pos = pos; return 0; } @@ -370,9 +400,10 @@ static int unpack_str(struct aa_ext *e, const char **string, const char *name) if (src_str[size - 1] != 0) goto fail; *string = src_str; + + return size; } } - return size; fail: e->pos = pos; diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 8346a4f7c5d7..a99be508f93d 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -739,14 +739,20 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext, &scontext_len); if (!rc && scontext) { - audit_log_format(ab, " srawcon=%s", scontext); + if (scontext_len && scontext[scontext_len - 1] == '\0') + scontext_len--; + audit_log_format(ab, " srawcon="); + audit_log_n_untrustedstring(ab, scontext, scontext_len); kfree(scontext); } rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext, &scontext_len); if (!rc && scontext) { - audit_log_format(ab, " trawcon=%s", scontext); + if (scontext_len && scontext[scontext_len - 1] == '\0') + scontext_len--; + audit_log_format(ab, " trawcon="); + audit_log_n_untrustedstring(ab, scontext, scontext_len); kfree(scontext); } } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3ec702cf46ca..fea66f6b31bf 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1052,15 +1052,24 @@ static int selinux_add_mnt_opt(const char *option, const char *val, int len, if (token == Opt_error) return -EINVAL; - if (token != Opt_seclabel) + if (token != Opt_seclabel) { val = kmemdup_nul(val, len, GFP_KERNEL); + if (!val) { + rc = -ENOMEM; + goto free_opt; + } + } rc = selinux_add_opt(token, val, mnt_opts); if (unlikely(rc)) { kfree(val); - if (*mnt_opts) { - selinux_free_mnt_opts(*mnt_opts); - *mnt_opts = NULL; - } + goto free_opt; + } + return rc; + +free_opt: + if (*mnt_opts) { + selinux_free_mnt_opts(*mnt_opts); + *mnt_opts = NULL; } return rc; } @@ -2616,10 +2625,11 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) char *from = options; char *to = options; bool first = true; + int rc; while (1) { int len = opt_len(from); - int token, rc; + int token; char *arg = NULL; token = match_opt_prefix(from, len, &arg); @@ -2635,15 +2645,15 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) *q++ = c; } arg = kmemdup_nul(arg, q - arg, GFP_KERNEL); + if (!arg) { + rc = -ENOMEM; + goto free_opt; + } } rc = selinux_add_opt(token, arg, mnt_opts); if (unlikely(rc)) { kfree(arg); - if (*mnt_opts) { - selinux_free_mnt_opts(*mnt_opts); - *mnt_opts = NULL; - } - return rc; + goto free_opt; } } else { if (!first) { // copy with preceding comma @@ -2661,6 +2671,13 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) } *to = '\0'; return 0; + +free_opt: + if (*mnt_opts) { + selinux_free_mnt_opts(*mnt_opts); + *mnt_opts = NULL; + } + return rc; } static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0de725f88bed..d99450b4f511 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -68,6 +68,7 @@ static struct { int len; int opt; } smk_mount_opts[] = { + {"smackfsdef", sizeof("smackfsdef") - 1, Opt_fsdefault}, A(fsdefault), A(fsfloor), A(fshat), A(fsroot), A(fstransmute) }; #undef A @@ -682,11 +683,12 @@ static int smack_fs_context_dup(struct fs_context *fc, } static const struct fs_parameter_spec smack_param_specs[] = { - fsparam_string("fsdefault", Opt_fsdefault), - fsparam_string("fsfloor", Opt_fsfloor), - fsparam_string("fshat", Opt_fshat), - fsparam_string("fsroot", Opt_fsroot), - fsparam_string("fstransmute", Opt_fstransmute), + fsparam_string("smackfsdef", Opt_fsdefault), + fsparam_string("smackfsdefault", Opt_fsdefault), + fsparam_string("smackfsfloor", Opt_fsfloor), + fsparam_string("smackfshat", Opt_fshat), + fsparam_string("smackfsroot", Opt_fsroot), + fsparam_string("smackfstransmute", Opt_fstransmute), {} }; |