diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig | 2 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 7 | ||||
-rw-r--r-- | security/apparmor/secid.c | 1 | ||||
-rw-r--r-- | security/integrity/iint.c | 6 | ||||
-rw-r--r-- | security/security.c | 45 | ||||
-rw-r--r-- | security/selinux/hooks.c | 12 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 178 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 12 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 7 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 5 |
12 files changed, 141 insertions, 138 deletions
diff --git a/security/Kconfig b/security/Kconfig index 27d8b2688f75..d9aa521b5206 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -57,7 +57,7 @@ config SECURITY_NETWORK config PAGE_TABLE_ISOLATION bool "Remove the kernel mapping in user mode" default y - depends on X86 && !UML + depends on (X86_64 || X86_PAE) && !UML help This feature reduces the number of hardware side channels by ensuring that the majority of kernel addresses are not mapped diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8b8b70620bbe..aa35939443c4 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -732,7 +732,7 @@ static int apparmor_task_setrlimit(struct task_struct *task, return error; } -static int apparmor_task_kill(struct task_struct *target, struct siginfo *info, +static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info, int sig, const struct cred *cred) { struct aa_label *cl, *tl; @@ -1606,4 +1606,7 @@ alloc_out: return error; } -security_initcall(apparmor_init); +DEFINE_LSM(apparmor) = { + .name = "apparmor", + .init = apparmor_init, +}; diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c index f2f22d00db18..4ccec1bcf6f5 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c @@ -79,7 +79,6 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) struct aa_label *label = aa_secid_to_label(secid); int len; - AA_BUG(!secdata); AA_BUG(!seclen); if (!label) diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 5a6810041e5c..1ea05da2323d 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -22,6 +22,7 @@ #include <linux/file.h> #include <linux/uaccess.h> #include <linux/security.h> +#include <linux/lsm_hooks.h> #include "integrity.h" static struct rb_root integrity_iint_tree = RB_ROOT; @@ -174,7 +175,10 @@ static int __init integrity_iintcache_init(void) 0, SLAB_PANIC, init_once); return 0; } -security_initcall(integrity_iintcache_init); +DEFINE_LSM(integrity) = { + .name = "integrity", + .init = integrity_iintcache_init, +}; /* diff --git a/security/security.c b/security/security.c index 736e78da1ab9..04d173eb93f6 100644 --- a/security/security.c +++ b/security/security.c @@ -12,6 +12,8 @@ * (at your option) any later version. */ +#define pr_fmt(fmt) "LSM: " fmt + #include <linux/bpf.h> #include <linux/capability.h> #include <linux/dcache.h> @@ -30,8 +32,6 @@ #include <linux/string.h> #include <net/flow.h> -#include <trace/events/initcall.h> - #define MAX_LSM_EVM_XATTR 2 /* Maximum number of letters for an LSM name string */ @@ -45,20 +45,22 @@ char *lsm_names; static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; -static void __init do_security_initcalls(void) +static __initdata bool debug; +#define init_debug(...) \ + do { \ + if (debug) \ + pr_info(__VA_ARGS__); \ + } while (0) + +static void __init major_lsm_init(void) { + struct lsm_info *lsm; int ret; - initcall_t call; - initcall_entry_t *ce; - - ce = __security_initcall_start; - trace_initcall_level("security"); - while (ce < __security_initcall_end) { - call = initcall_from_entry(ce); - trace_initcall_start(call); - ret = call(); - trace_initcall_finish(call, ret); - ce++; + + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { + init_debug("initializing %s\n", lsm->name); + ret = lsm->init(); + WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); } } @@ -72,10 +74,11 @@ int __init security_init(void) int i; struct hlist_head *list = (struct hlist_head *) &security_hook_heads; + pr_info("Security Framework initializing\n"); + for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head); i++) INIT_HLIST_HEAD(&list[i]); - pr_info("Security Framework initialized\n"); /* * Load minor LSMs, with the capability module always first. @@ -87,7 +90,7 @@ int __init security_init(void) /* * Load all the remaining security modules. */ - do_security_initcalls(); + major_lsm_init(); return 0; } @@ -100,6 +103,14 @@ static int __init choose_lsm(char *str) } __setup("security=", choose_lsm); +/* Enable LSM order debugging. */ +static int __init enable_debug(char *str) +{ + debug = true; + return 1; +} +__setup("lsm.debug", enable_debug); + static bool match_last_lsm(const char *list, const char *lsm) { const char *last; @@ -1147,7 +1158,7 @@ int security_task_movememory(struct task_struct *p) return call_int_hook(task_movememory, 0, p); } -int security_task_kill(struct task_struct *p, struct siginfo *info, +int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { return call_int_hook(task_kill, 0, p, info, sig, cred); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ad9a9b8e9979..7ce683259357 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1508,6 +1508,11 @@ static int selinux_genfs_get_sid(struct dentry *dentry, } rc = security_genfs_sid(&selinux_state, sb->s_type->name, path, tclass, sid); + if (rc == -ENOENT) { + /* No match in policy, mark as unlabeled. */ + *sid = SECINITSID_UNLABELED; + rc = 0; + } } free_page((unsigned long)buffer); return rc; @@ -4186,7 +4191,7 @@ static int selinux_task_movememory(struct task_struct *p) PROCESS__SETSCHED, NULL); } -static int selinux_task_kill(struct task_struct *p, struct siginfo *info, +static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { u32 secid; @@ -7202,7 +7207,10 @@ void selinux_complete_init(void) /* SELinux requires early initialization in order to label all processes and objects when they are created. */ -security_initcall(selinux_init); +DEFINE_LSM(selinux) = { + .name = "selinux", + .init = selinux_init, +}; #if defined(CONFIG_NETFILTER) diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 39475fb455bc..2fe459df3c85 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -218,9 +218,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) /* * Set the MLS fields in the security context structure * `context' based on the string representation in - * the string `*scontext'. Update `*scontext' to - * point to the end of the string representation of - * the MLS fields. + * the string `scontext'. * * This function modifies the string in place, inserting * NULL characters to terminate the MLS fields. @@ -235,22 +233,21 @@ int mls_context_isvalid(struct policydb *p, struct context *c) */ int mls_context_to_sid(struct policydb *pol, char oldc, - char **scontext, + char *scontext, struct context *context, struct sidtab *s, u32 def_sid) { - - char delim; - char *scontextp, *p, *rngptr; + char *sensitivity, *cur_cat, *next_cat, *rngptr; struct level_datum *levdatum; struct cat_datum *catdatum, *rngdatum; - int l, rc = -EINVAL; + int l, rc, i; + char *rangep[2]; if (!pol->mls_enabled) { - if (def_sid != SECSID_NULL && oldc) - *scontext += strlen(*scontext) + 1; - return 0; + if ((def_sid != SECSID_NULL && oldc) || (*scontext) == '\0') + return 0; + return -EINVAL; } /* @@ -261,113 +258,94 @@ int mls_context_to_sid(struct policydb *pol, struct context *defcon; if (def_sid == SECSID_NULL) - goto out; + return -EINVAL; defcon = sidtab_search(s, def_sid); if (!defcon) - goto out; + return -EINVAL; - rc = mls_context_cpy(context, defcon); - goto out; + return mls_context_cpy(context, defcon); } - /* Extract low sensitivity. */ - scontextp = p = *scontext; - while (*p && *p != ':' && *p != '-') - p++; - - delim = *p; - if (delim != '\0') - *p++ = '\0'; + /* + * If we're dealing with a range, figure out where the two parts + * of the range begin. + */ + rangep[0] = scontext; + rangep[1] = strchr(scontext, '-'); + if (rangep[1]) { + rangep[1][0] = '\0'; + rangep[1]++; + } + /* For each part of the range: */ for (l = 0; l < 2; l++) { - levdatum = hashtab_search(pol->p_levels.table, scontextp); - if (!levdatum) { - rc = -EINVAL; - goto out; - } + /* Split sensitivity and category set. */ + sensitivity = rangep[l]; + if (sensitivity == NULL) + break; + next_cat = strchr(sensitivity, ':'); + if (next_cat) + *(next_cat++) = '\0'; + /* Parse sensitivity. */ + levdatum = hashtab_search(pol->p_levels.table, sensitivity); + if (!levdatum) + return -EINVAL; context->range.level[l].sens = levdatum->level->sens; - if (delim == ':') { - /* Extract category set. */ - while (1) { - scontextp = p; - while (*p && *p != ',' && *p != '-') - p++; - delim = *p; - if (delim != '\0') - *p++ = '\0'; - - /* Separate into range if exists */ - rngptr = strchr(scontextp, '.'); - if (rngptr != NULL) { - /* Remove '.' */ - *rngptr++ = '\0'; - } + /* Extract category set. */ + while (next_cat != NULL) { + cur_cat = next_cat; + next_cat = strchr(next_cat, ','); + if (next_cat != NULL) + *(next_cat++) = '\0'; + + /* Separate into range if exists */ + rngptr = strchr(cur_cat, '.'); + if (rngptr != NULL) { + /* Remove '.' */ + *rngptr++ = '\0'; + } - catdatum = hashtab_search(pol->p_cats.table, - scontextp); - if (!catdatum) { - rc = -EINVAL; - goto out; - } + catdatum = hashtab_search(pol->p_cats.table, cur_cat); + if (!catdatum) + return -EINVAL; - rc = ebitmap_set_bit(&context->range.level[l].cat, - catdatum->value - 1, 1); - if (rc) - goto out; - - /* If range, set all categories in range */ - if (rngptr) { - int i; - - rngdatum = hashtab_search(pol->p_cats.table, rngptr); - if (!rngdatum) { - rc = -EINVAL; - goto out; - } - - if (catdatum->value >= rngdatum->value) { - rc = -EINVAL; - goto out; - } - - for (i = catdatum->value; i < rngdatum->value; i++) { - rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); - if (rc) - goto out; - } - } + rc = ebitmap_set_bit(&context->range.level[l].cat, + catdatum->value - 1, 1); + if (rc) + return rc; + + /* If range, set all categories in range */ + if (rngptr == NULL) + continue; + + rngdatum = hashtab_search(pol->p_cats.table, rngptr); + if (!rngdatum) + return -EINVAL; + + if (catdatum->value >= rngdatum->value) + return -EINVAL; - if (delim != ',') - break; + for (i = catdatum->value; i < rngdatum->value; i++) { + rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); + if (rc) + return rc; } } - if (delim == '-') { - /* Extract high sensitivity. */ - scontextp = p; - while (*p && *p != ':') - p++; - - delim = *p; - if (delim != '\0') - *p++ = '\0'; - } else - break; } - if (l == 0) { + /* If we didn't see a '-', the range start is also the range end. */ + if (rangep[1] == NULL) { context->range.level[1].sens = context->range.level[0].sens; rc = ebitmap_cpy(&context->range.level[1].cat, &context->range.level[0].cat); if (rc) - goto out; + return rc; } - *scontext = ++p; - rc = 0; -out: - return rc; + + return 0; } /* @@ -379,21 +357,19 @@ out: int mls_from_string(struct policydb *p, char *str, struct context *context, gfp_t gfp_mask) { - char *tmpstr, *freestr; + char *tmpstr; int rc; if (!p->mls_enabled) return -EINVAL; - /* we need freestr because mls_context_to_sid will change - the value of tmpstr */ - tmpstr = freestr = kstrdup(str, gfp_mask); + tmpstr = kstrdup(str, gfp_mask); if (!tmpstr) { rc = -ENOMEM; } else { - rc = mls_context_to_sid(p, ':', &tmpstr, context, + rc = mls_context_to_sid(p, ':', tmpstr, context, NULL, SECSID_NULL); - kfree(freestr); + kfree(tmpstr); } return rc; diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 9a3ff7af70ad..67093647576d 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -34,7 +34,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l); int mls_context_to_sid(struct policydb *p, char oldc, - char **scontext, + char *scontext, struct context *context, struct sidtab *s, u32 def_sid); diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index e9394e7adc84..f4eadd3f7350 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -1101,7 +1101,7 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len) if ((len == 0) || (len == (u32)-1)) return -EINVAL; - str = kmalloc(len + 1, flags); + str = kmalloc(len + 1, flags | __GFP_NOWARN); if (!str) return -ENOMEM; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index f3def298a90e..12e414394530 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1365,7 +1365,6 @@ int security_sid_to_context_force(struct selinux_state *state, u32 sid, static int string_to_context_struct(struct policydb *pol, struct sidtab *sidtabp, char *scontext, - u32 scontext_len, struct context *ctx, u32 def_sid) { @@ -1426,15 +1425,12 @@ static int string_to_context_struct(struct policydb *pol, ctx->type = typdatum->value; - rc = mls_context_to_sid(pol, oldc, &p, ctx, sidtabp, def_sid); + rc = mls_context_to_sid(pol, oldc, p, ctx, sidtabp, def_sid); if (rc) goto out; - rc = -EINVAL; - if ((p - scontext) < scontext_len) - goto out; - /* Check the validity of the new context. */ + rc = -EINVAL; if (!policydb_context_isvalid(pol, ctx)) goto out; rc = 0; @@ -1489,7 +1485,7 @@ static int security_context_to_sid_core(struct selinux_state *state, policydb = &state->ss->policydb; sidtab = &state->ss->sidtab; rc = string_to_context_struct(policydb, sidtab, scontext2, - scontext_len, &context, def_sid); + &context, def_sid); if (rc == -EINVAL && force) { context.str = str; context.len = strlen(str) + 1; @@ -1958,7 +1954,7 @@ static int convert_context(u32 key, goto out; rc = string_to_context_struct(args->newp, NULL, s, - c->len, &ctx, SECSID_NULL); + &ctx, SECSID_NULL); kfree(s); if (!rc) { pr_info("SELinux: Context %s became valid (mapped).\n", diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 340fc30ad85d..934dabe150fa 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2251,7 +2251,7 @@ static int smack_task_movememory(struct task_struct *p) * Return 0 if write access is permitted * */ -static int smack_task_kill(struct task_struct *p, struct siginfo *info, +static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { struct smk_audit_info ad; @@ -4882,4 +4882,7 @@ static __init int smack_init(void) * Smack requires early initialization in order to label * all processes and objects when they are created. */ -security_initcall(smack_init); +DEFINE_LSM(smack) = { + .name = "smack", + .init = smack_init, +}; diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 9f932e2d6852..1b5b5097efd7 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -550,4 +550,7 @@ static int __init tomoyo_init(void) return 0; } -security_initcall(tomoyo_init); +DEFINE_LSM(tomoyo) = { + .name = "tomoyo", + .init = tomoyo_init, +}; |