forked from Minki/linux
selinux/stable-5.12 PR 20210322
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmBYx3gUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXPSSw/+MnJxbBEfxMXll2LwCRXvyW0Q/F++ sSLPKZL9B5E7jANbTBlkUW+tMwsckTS7euPvRuJj2+mrSujRnSTl158JAAcn34gd lpiGQpttFZD75Eh9sLNg0OZ7PflwQvAzHt52EweD8/OE5O8BLBg7o56SYMr3LkGu Up9YcZPHNlj+NhfvWebv3jSB6dv392cG33iZoqmW81wSzmlXHGdzS5UTiIFnsp3X kbhLKaZWDSBHuAVMuAxtx3x3sQO1ElfFHxKRYM1fzfl0BMy30Wv6YnXHW2nn08Hr oT26968C0Rl9carTnA+G60Nj4WoTWW2dF20Mih+05vkpqFLjdMtFra7fFndbmfNi f7Gj5DJNrbunX1dMFJkyPnO/1x74RFUhZbCKm5ffvmF8AcYVivbbsyUAy/xduPWo m9hjXDVZLUbWxGBUFxyJD6qQw/wuz+qII8B7SBCKaDdCtM74TlXBVug8prrPcWHV tO3ljjbxEjBJ6zsFIJ9IlV3rJTL0v4RbAELXXp5qcZOJpnUtuH8cxj0Ryzo3yCY5 g/m6IHhm5OfJ5TBSc5UIj2NJQi7sJ+Yv/++lms+RB2MVopx4lJ+UK7140gCA40iC 1EPOGXCnB/b1k5F38dqdpI5MD+/uAzOMusQvPfL4x0xoQidzsqDmqgaS+V8pIYl6 nisL4eEe2K7PWX4= =mFaE -----END PGP SIGNATURE----- Merge tag 'selinux-pr-20210322' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux Pull selinux fixes from Paul Moore: "Three SELinux patches: - Fix a problem where a local variable is used outside its associated function. Thankfully this can only be triggered by reloading the SELinux policy, which is a restricted operation for other obvious reasons. - Fix some incorrect, and inconsistent, audit and printk messages when loading the SELinux policy. All three patches are relatively minor and have been through our testing with no failures" * tag 'selinux-pr-20210322' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinuxfs: unify policy load error reporting selinux: fix variable scope issue in live sidtab conversion selinux: don't log MAC_POLICY_LOAD record on failed policy load
This commit is contained in:
commit
8419639062
@ -219,14 +219,21 @@ static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
|
||||
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS]);
|
||||
}
|
||||
|
||||
struct selinux_policy_convert_data;
|
||||
|
||||
struct selinux_load_state {
|
||||
struct selinux_policy *policy;
|
||||
struct selinux_policy_convert_data *convert_data;
|
||||
};
|
||||
|
||||
int security_mls_enabled(struct selinux_state *state);
|
||||
int security_load_policy(struct selinux_state *state,
|
||||
void *data, size_t len,
|
||||
struct selinux_policy **newpolicyp);
|
||||
void *data, size_t len,
|
||||
struct selinux_load_state *load_state);
|
||||
void selinux_policy_commit(struct selinux_state *state,
|
||||
struct selinux_policy *newpolicy);
|
||||
struct selinux_load_state *load_state);
|
||||
void selinux_policy_cancel(struct selinux_state *state,
|
||||
struct selinux_policy *policy);
|
||||
struct selinux_load_state *load_state);
|
||||
int security_read_policy(struct selinux_state *state,
|
||||
void **data, size_t *len);
|
||||
int security_read_state_kernel(struct selinux_state *state,
|
||||
|
@ -563,17 +563,13 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
|
||||
|
||||
ret = sel_make_bools(newpolicy, tmp_bool_dir, &tmp_bool_num,
|
||||
&tmp_bool_names, &tmp_bool_values);
|
||||
if (ret) {
|
||||
pr_err("SELinux: failed to load policy booleans\n");
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sel_make_classes(newpolicy, tmp_class_dir,
|
||||
&fsi->last_class_ino);
|
||||
if (ret) {
|
||||
pr_err("SELinux: failed to load policy classes\n");
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* booleans */
|
||||
old_dentry = fsi->bool_dir;
|
||||
@ -616,7 +612,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
|
||||
{
|
||||
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
|
||||
struct selinux_policy *newpolicy;
|
||||
struct selinux_load_state load_state;
|
||||
ssize_t length;
|
||||
void *data = NULL;
|
||||
|
||||
@ -642,23 +638,23 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
|
||||
if (copy_from_user(data, buf, count) != 0)
|
||||
goto out;
|
||||
|
||||
length = security_load_policy(fsi->state, data, count, &newpolicy);
|
||||
length = security_load_policy(fsi->state, data, count, &load_state);
|
||||
if (length) {
|
||||
pr_warn_ratelimited("SELinux: failed to load policy\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = sel_make_policy_nodes(fsi, newpolicy);
|
||||
length = sel_make_policy_nodes(fsi, load_state.policy);
|
||||
if (length) {
|
||||
selinux_policy_cancel(fsi->state, newpolicy);
|
||||
goto out1;
|
||||
pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n");
|
||||
selinux_policy_cancel(fsi->state, &load_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
selinux_policy_commit(fsi->state, newpolicy);
|
||||
selinux_policy_commit(fsi->state, &load_state);
|
||||
|
||||
length = count;
|
||||
|
||||
out1:
|
||||
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
|
||||
"auid=%u ses=%u lsm=selinux res=1",
|
||||
from_kuid(&init_user_ns, audit_get_loginuid(current)),
|
||||
|
@ -67,6 +67,17 @@
|
||||
#include "policycap_names.h"
|
||||
#include "ima.h"
|
||||
|
||||
struct convert_context_args {
|
||||
struct selinux_state *state;
|
||||
struct policydb *oldp;
|
||||
struct policydb *newp;
|
||||
};
|
||||
|
||||
struct selinux_policy_convert_data {
|
||||
struct convert_context_args args;
|
||||
struct sidtab_convert_params sidtab_params;
|
||||
};
|
||||
|
||||
/* Forward declaration. */
|
||||
static int context_struct_to_string(struct policydb *policydb,
|
||||
struct context *context,
|
||||
@ -1974,12 +1985,6 @@ static inline int convert_context_handle_invalid_context(
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct convert_context_args {
|
||||
struct selinux_state *state;
|
||||
struct policydb *oldp;
|
||||
struct policydb *newp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert the values in the security context
|
||||
* structure `oldc' from the values specified
|
||||
@ -2159,7 +2164,7 @@ static void selinux_policy_cond_free(struct selinux_policy *policy)
|
||||
}
|
||||
|
||||
void selinux_policy_cancel(struct selinux_state *state,
|
||||
struct selinux_policy *policy)
|
||||
struct selinux_load_state *load_state)
|
||||
{
|
||||
struct selinux_policy *oldpolicy;
|
||||
|
||||
@ -2167,7 +2172,8 @@ void selinux_policy_cancel(struct selinux_state *state,
|
||||
lockdep_is_held(&state->policy_mutex));
|
||||
|
||||
sidtab_cancel_convert(oldpolicy->sidtab);
|
||||
selinux_policy_free(policy);
|
||||
selinux_policy_free(load_state->policy);
|
||||
kfree(load_state->convert_data);
|
||||
}
|
||||
|
||||
static void selinux_notify_policy_change(struct selinux_state *state,
|
||||
@ -2183,9 +2189,9 @@ static void selinux_notify_policy_change(struct selinux_state *state,
|
||||
}
|
||||
|
||||
void selinux_policy_commit(struct selinux_state *state,
|
||||
struct selinux_policy *newpolicy)
|
||||
struct selinux_load_state *load_state)
|
||||
{
|
||||
struct selinux_policy *oldpolicy;
|
||||
struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
|
||||
u32 seqno;
|
||||
|
||||
oldpolicy = rcu_dereference_protected(state->policy,
|
||||
@ -2225,6 +2231,7 @@ void selinux_policy_commit(struct selinux_state *state,
|
||||
/* Free the old policy */
|
||||
synchronize_rcu();
|
||||
selinux_policy_free(oldpolicy);
|
||||
kfree(load_state->convert_data);
|
||||
|
||||
/* Notify others of the policy change */
|
||||
selinux_notify_policy_change(state, seqno);
|
||||
@ -2241,11 +2248,10 @@ void selinux_policy_commit(struct selinux_state *state,
|
||||
* loading the new policy.
|
||||
*/
|
||||
int security_load_policy(struct selinux_state *state, void *data, size_t len,
|
||||
struct selinux_policy **newpolicyp)
|
||||
struct selinux_load_state *load_state)
|
||||
{
|
||||
struct selinux_policy *newpolicy, *oldpolicy;
|
||||
struct sidtab_convert_params convert_params;
|
||||
struct convert_context_args args;
|
||||
struct selinux_policy_convert_data *convert_data;
|
||||
int rc = 0;
|
||||
struct policy_file file = { data, len }, *fp = &file;
|
||||
|
||||
@ -2275,10 +2281,10 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
|
||||
goto err_mapping;
|
||||
}
|
||||
|
||||
|
||||
if (!selinux_initialized(state)) {
|
||||
/* First policy load, so no need to preserve state from old policy */
|
||||
*newpolicyp = newpolicy;
|
||||
load_state->policy = newpolicy;
|
||||
load_state->convert_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2292,29 +2298,38 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
|
||||
goto err_free_isids;
|
||||
}
|
||||
|
||||
convert_data = kmalloc(sizeof(*convert_data), GFP_KERNEL);
|
||||
if (!convert_data) {
|
||||
rc = -ENOMEM;
|
||||
goto err_free_isids;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the internal representations of contexts
|
||||
* in the new SID table.
|
||||
*/
|
||||
args.state = state;
|
||||
args.oldp = &oldpolicy->policydb;
|
||||
args.newp = &newpolicy->policydb;
|
||||
convert_data->args.state = state;
|
||||
convert_data->args.oldp = &oldpolicy->policydb;
|
||||
convert_data->args.newp = &newpolicy->policydb;
|
||||
|
||||
convert_params.func = convert_context;
|
||||
convert_params.args = &args;
|
||||
convert_params.target = newpolicy->sidtab;
|
||||
convert_data->sidtab_params.func = convert_context;
|
||||
convert_data->sidtab_params.args = &convert_data->args;
|
||||
convert_data->sidtab_params.target = newpolicy->sidtab;
|
||||
|
||||
rc = sidtab_convert(oldpolicy->sidtab, &convert_params);
|
||||
rc = sidtab_convert(oldpolicy->sidtab, &convert_data->sidtab_params);
|
||||
if (rc) {
|
||||
pr_err("SELinux: unable to convert the internal"
|
||||
" representation of contexts in the new SID"
|
||||
" table\n");
|
||||
goto err_free_isids;
|
||||
goto err_free_convert_data;
|
||||
}
|
||||
|
||||
*newpolicyp = newpolicy;
|
||||
load_state->policy = newpolicy;
|
||||
load_state->convert_data = convert_data;
|
||||
return 0;
|
||||
|
||||
err_free_convert_data:
|
||||
kfree(convert_data);
|
||||
err_free_isids:
|
||||
sidtab_destroy(newpolicy->sidtab);
|
||||
err_mapping:
|
||||
|
Loading…
Reference in New Issue
Block a user