diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 3e3f1343c..d70c8375b 100755 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -87,6 +87,11 @@ extern int selinux_enabled_boot; struct selinux_avc; struct selinux_policy; +struct context_types { + u32 webview_zygote; + u32 zygote; +}; + struct selinux_state { #ifdef CONFIG_SECURITY_SELINUX_DISABLE bool disabled; @@ -100,6 +105,8 @@ struct selinux_state { bool android_netlink_route; bool android_netlink_getneigh; + struct context_types types; + struct page *status_page; struct mutex status_lock; diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 7415f49a3..95de633ab 100755 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -41,6 +41,8 @@ #include "security.h" #include "objsec.h" #include "conditional.h" +#include "ss/services.h" +#include "ss/symtab.h" enum sel_inos { SEL_ROOT_INO = 2, @@ -611,6 +613,30 @@ out: return ret; } +static int resolve_context_type(struct selinux_load_state *state, const char *name, u32 *out_type) +{ + struct type_datum *typdatum = symtab_search(&state->policy->policydb.p_types, name); + if (!typdatum || typdatum->attribute) { + pr_err("SELinux: missing type_datum for %s\n", name); + return -EINVAL; + } + *out_type = typdatum->value; + return 0; +} + +static int resolve_context_types(struct selinux_load_state *lstate, struct context_types *types) { + int rc; + +#define RESOLVE_TYPE(t) rc = resolve_context_type(lstate, #t, &types->t); if (rc) return rc + + RESOLVE_TYPE(webview_zygote); + RESOLVE_TYPE(zygote); + +#undef RESOLVE_TYPE + + return 0; +} + static ssize_t sel_write_load(struct file *file, const char __user *buf, size_t count, loff_t *ppos) @@ -656,6 +682,12 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, goto out; } + length = resolve_context_types(&load_state, &fsi->state->types); + if (length) { + selinux_policy_cancel(fsi->state, &load_state); + goto out; + } + selinux_policy_commit(fsi->state, &load_state); length = count; audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,