Skip to content

Commit 8419639

Browse files
committed
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
2 parents 0d02ec6 + ee5de60 commit 8419639

File tree

3 files changed

+59
-41
lines changed

3 files changed

+59
-41
lines changed

security/selinux/include/security.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,21 @@ static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
219219
return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS]);
220220
}
221221

222+
struct selinux_policy_convert_data;
223+
224+
struct selinux_load_state {
225+
struct selinux_policy *policy;
226+
struct selinux_policy_convert_data *convert_data;
227+
};
228+
222229
int security_mls_enabled(struct selinux_state *state);
223230
int security_load_policy(struct selinux_state *state,
224-
void *data, size_t len,
225-
struct selinux_policy **newpolicyp);
231+
void *data, size_t len,
232+
struct selinux_load_state *load_state);
226233
void selinux_policy_commit(struct selinux_state *state,
227-
struct selinux_policy *newpolicy);
234+
struct selinux_load_state *load_state);
228235
void selinux_policy_cancel(struct selinux_state *state,
229-
struct selinux_policy *policy);
236+
struct selinux_load_state *load_state);
230237
int security_read_policy(struct selinux_state *state,
231238
void **data, size_t *len);
232239
int security_read_state_kernel(struct selinux_state *state,

security/selinux/selinuxfs.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -563,17 +563,13 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
563563

564564
ret = sel_make_bools(newpolicy, tmp_bool_dir, &tmp_bool_num,
565565
&tmp_bool_names, &tmp_bool_values);
566-
if (ret) {
567-
pr_err("SELinux: failed to load policy booleans\n");
566+
if (ret)
568567
goto out;
569-
}
570568

571569
ret = sel_make_classes(newpolicy, tmp_class_dir,
572570
&fsi->last_class_ino);
573-
if (ret) {
574-
pr_err("SELinux: failed to load policy classes\n");
571+
if (ret)
575572
goto out;
576-
}
577573

578574
/* booleans */
579575
old_dentry = fsi->bool_dir;
@@ -616,7 +612,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
616612

617613
{
618614
struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
619-
struct selinux_policy *newpolicy;
615+
struct selinux_load_state load_state;
620616
ssize_t length;
621617
void *data = NULL;
622618

@@ -642,23 +638,23 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
642638
if (copy_from_user(data, buf, count) != 0)
643639
goto out;
644640

645-
length = security_load_policy(fsi->state, data, count, &newpolicy);
641+
length = security_load_policy(fsi->state, data, count, &load_state);
646642
if (length) {
647643
pr_warn_ratelimited("SELinux: failed to load policy\n");
648644
goto out;
649645
}
650646

651-
length = sel_make_policy_nodes(fsi, newpolicy);
647+
length = sel_make_policy_nodes(fsi, load_state.policy);
652648
if (length) {
653-
selinux_policy_cancel(fsi->state, newpolicy);
654-
goto out1;
649+
pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n");
650+
selinux_policy_cancel(fsi->state, &load_state);
651+
goto out;
655652
}
656653

657-
selinux_policy_commit(fsi->state, newpolicy);
654+
selinux_policy_commit(fsi->state, &load_state);
658655

659656
length = count;
660657

661-
out1:
662658
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
663659
"auid=%u ses=%u lsm=selinux res=1",
664660
from_kuid(&init_user_ns, audit_get_loginuid(current)),

security/selinux/ss/services.c

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,17 @@
6767
#include "policycap_names.h"
6868
#include "ima.h"
6969

70+
struct convert_context_args {
71+
struct selinux_state *state;
72+
struct policydb *oldp;
73+
struct policydb *newp;
74+
};
75+
76+
struct selinux_policy_convert_data {
77+
struct convert_context_args args;
78+
struct sidtab_convert_params sidtab_params;
79+
};
80+
7081
/* Forward declaration. */
7182
static int context_struct_to_string(struct policydb *policydb,
7283
struct context *context,
@@ -1974,12 +1985,6 @@ static inline int convert_context_handle_invalid_context(
19741985
return 0;
19751986
}
19761987

1977-
struct convert_context_args {
1978-
struct selinux_state *state;
1979-
struct policydb *oldp;
1980-
struct policydb *newp;
1981-
};
1982-
19831988
/*
19841989
* Convert the values in the security context
19851990
* structure `oldc' from the values specified
@@ -2159,15 +2164,16 @@ static void selinux_policy_cond_free(struct selinux_policy *policy)
21592164
}
21602165

21612166
void selinux_policy_cancel(struct selinux_state *state,
2162-
struct selinux_policy *policy)
2167+
struct selinux_load_state *load_state)
21632168
{
21642169
struct selinux_policy *oldpolicy;
21652170

21662171
oldpolicy = rcu_dereference_protected(state->policy,
21672172
lockdep_is_held(&state->policy_mutex));
21682173

21692174
sidtab_cancel_convert(oldpolicy->sidtab);
2170-
selinux_policy_free(policy);
2175+
selinux_policy_free(load_state->policy);
2176+
kfree(load_state->convert_data);
21712177
}
21722178

21732179
static void selinux_notify_policy_change(struct selinux_state *state,
@@ -2183,9 +2189,9 @@ static void selinux_notify_policy_change(struct selinux_state *state,
21832189
}
21842190

21852191
void selinux_policy_commit(struct selinux_state *state,
2186-
struct selinux_policy *newpolicy)
2192+
struct selinux_load_state *load_state)
21872193
{
2188-
struct selinux_policy *oldpolicy;
2194+
struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
21892195
u32 seqno;
21902196

21912197
oldpolicy = rcu_dereference_protected(state->policy,
@@ -2225,6 +2231,7 @@ void selinux_policy_commit(struct selinux_state *state,
22252231
/* Free the old policy */
22262232
synchronize_rcu();
22272233
selinux_policy_free(oldpolicy);
2234+
kfree(load_state->convert_data);
22282235

22292236
/* Notify others of the policy change */
22302237
selinux_notify_policy_change(state, seqno);
@@ -2241,11 +2248,10 @@ void selinux_policy_commit(struct selinux_state *state,
22412248
* loading the new policy.
22422249
*/
22432250
int security_load_policy(struct selinux_state *state, void *data, size_t len,
2244-
struct selinux_policy **newpolicyp)
2251+
struct selinux_load_state *load_state)
22452252
{
22462253
struct selinux_policy *newpolicy, *oldpolicy;
2247-
struct sidtab_convert_params convert_params;
2248-
struct convert_context_args args;
2254+
struct selinux_policy_convert_data *convert_data;
22492255
int rc = 0;
22502256
struct policy_file file = { data, len }, *fp = &file;
22512257

@@ -2275,10 +2281,10 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
22752281
goto err_mapping;
22762282
}
22772283

2278-
22792284
if (!selinux_initialized(state)) {
22802285
/* First policy load, so no need to preserve state from old policy */
2281-
*newpolicyp = newpolicy;
2286+
load_state->policy = newpolicy;
2287+
load_state->convert_data = NULL;
22822288
return 0;
22832289
}
22842290

@@ -2292,29 +2298,38 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
22922298
goto err_free_isids;
22932299
}
22942300

2301+
convert_data = kmalloc(sizeof(*convert_data), GFP_KERNEL);
2302+
if (!convert_data) {
2303+
rc = -ENOMEM;
2304+
goto err_free_isids;
2305+
}
2306+
22952307
/*
22962308
* Convert the internal representations of contexts
22972309
* in the new SID table.
22982310
*/
2299-
args.state = state;
2300-
args.oldp = &oldpolicy->policydb;
2301-
args.newp = &newpolicy->policydb;
2311+
convert_data->args.state = state;
2312+
convert_data->args.oldp = &oldpolicy->policydb;
2313+
convert_data->args.newp = &newpolicy->policydb;
23022314

2303-
convert_params.func = convert_context;
2304-
convert_params.args = &args;
2305-
convert_params.target = newpolicy->sidtab;
2315+
convert_data->sidtab_params.func = convert_context;
2316+
convert_data->sidtab_params.args = &convert_data->args;
2317+
convert_data->sidtab_params.target = newpolicy->sidtab;
23062318

2307-
rc = sidtab_convert(oldpolicy->sidtab, &convert_params);
2319+
rc = sidtab_convert(oldpolicy->sidtab, &convert_data->sidtab_params);
23082320
if (rc) {
23092321
pr_err("SELinux: unable to convert the internal"
23102322
" representation of contexts in the new SID"
23112323
" table\n");
2312-
goto err_free_isids;
2324+
goto err_free_convert_data;
23132325
}
23142326

2315-
*newpolicyp = newpolicy;
2327+
load_state->policy = newpolicy;
2328+
load_state->convert_data = convert_data;
23162329
return 0;
23172330

2331+
err_free_convert_data:
2332+
kfree(convert_data);
23182333
err_free_isids:
23192334
sidtab_destroy(newpolicy->sidtab);
23202335
err_mapping:

0 commit comments

Comments
 (0)