@@ -148,6 +148,9 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
int scan_value;
bool old_value, new_value;
+ if (state != current_selinux_state)
+ return -EPERM;
+
if (count >= PAGE_SIZE)
return -ENOMEM;
@@ -330,6 +333,9 @@ static ssize_t sel_write_unshare(struct file *file, const char __user *buf,
bool set;
int rc;
+ if (state != current_selinux_state)
+ return -EPERM;
+
if (count >= PAGE_SIZE)
return -ENOMEM;
@@ -662,6 +668,9 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
if (!count)
return -EINVAL;
+ if (fsi->state != current_selinux_state)
+ return -EPERM;
+
mutex_lock(&fsi->state->policy_mutex);
length = avc_has_perm(current_selinux_state,
current_sid(), SECINITSID_SECURITY,
@@ -766,6 +775,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
ssize_t length;
unsigned int new_value;
+ if (fsi->state != current_selinux_state)
+ return -EPERM;
+
length = avc_has_perm(current_selinux_state,
current_sid(), SECINITSID_SECURITY,
SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT,
@@ -822,6 +834,9 @@ static ssize_t sel_write_validatetrans(struct file *file,
u16 tclass;
int rc;
+ if (state != current_selinux_state)
+ return -EPERM;
+
rc = avc_has_perm(current_selinux_state,
current_sid(), SECINITSID_SECURITY,
SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL);
@@ -909,10 +924,14 @@ static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
{
+ struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
ino_t ino = file_inode(file)->i_ino;
char *data;
ssize_t rv;
+ if (fsi->state != current_selinux_state)
+ return -EPERM;
+
if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
return -EINVAL;
@@ -1352,6 +1371,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
const char *name = filep->f_path.dentry->d_name.name;
+ if (fsi->state != current_selinux_state)
+ return -EPERM;
+
if (count >= PAGE_SIZE)
return -ENOMEM;
@@ -1408,6 +1430,9 @@ static ssize_t sel_commit_bools_write(struct file *filep,
ssize_t length;
int new_value;
+ if (fsi->state != current_selinux_state)
+ return -EPERM;
+
if (count >= PAGE_SIZE)
return -ENOMEM;
@@ -1539,6 +1564,9 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
ssize_t ret;
unsigned int new_value;
+ if (state != current_selinux_state)
+ return -EPERM;
+
ret = avc_has_perm(current_selinux_state,
current_sid(), SECINITSID_SECURITY,
SECCLASS_SECURITY, SECURITY__SETSECPARAM,
This ensures that once a process unshares its selinux namespace, it can no longer act on the parent namespace's selinuxfs instance, irrespective of policy. This is a safety measure so that even if an otherwise unconfined process unshares its selinux namespace, it won't be able to subsequently affect the enforcing mode or policy of the parent. This also helps avoid common mistakes like failing to create a mount namespace and mount a new selinuxfs instance in order to act on one's own selinux namespace after unsharing. Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com> --- security/selinux/selinuxfs.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)