Skip to content

Commit 34a484d

Browse files
committed
Merge tag 'selinux-pr-20180629' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux fix from Paul Moore: "One fairly straightforward patch to fix a longstanding issue where a process could stall while accessing files in selinuxfs and block everyone else due to a held mutex. The patch passes all our tests and looks to apply cleanly to your current tree" * tag 'selinux-pr-20180629' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: move user accesses in selinuxfs out of locked regions
2 parents e6e5bec + 0da7412 commit 34a484d

1 file changed

Lines changed: 33 additions & 45 deletions

File tree

security/selinux/selinuxfs.c

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -441,22 +441,16 @@ static int sel_release_policy(struct inode *inode, struct file *filp)
441441
static ssize_t sel_read_policy(struct file *filp, char __user *buf,
442442
size_t count, loff_t *ppos)
443443
{
444-
struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
445444
struct policy_load_memory *plm = filp->private_data;
446445
int ret;
447446

448-
mutex_lock(&fsi->mutex);
449-
450447
ret = avc_has_perm(&selinux_state,
451448
current_sid(), SECINITSID_SECURITY,
452449
SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
453450
if (ret)
454-
goto out;
451+
return ret;
455452

456-
ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
457-
out:
458-
mutex_unlock(&fsi->mutex);
459-
return ret;
453+
return simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
460454
}
461455

462456
static vm_fault_t sel_mmap_policy_fault(struct vm_fault *vmf)
@@ -1188,25 +1182,29 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
11881182
ret = -EINVAL;
11891183
if (index >= fsi->bool_num || strcmp(name,
11901184
fsi->bool_pending_names[index]))
1191-
goto out;
1185+
goto out_unlock;
11921186

11931187
ret = -ENOMEM;
11941188
page = (char *)get_zeroed_page(GFP_KERNEL);
11951189
if (!page)
1196-
goto out;
1190+
goto out_unlock;
11971191

11981192
cur_enforcing = security_get_bool_value(fsi->state, index);
11991193
if (cur_enforcing < 0) {
12001194
ret = cur_enforcing;
1201-
goto out;
1195+
goto out_unlock;
12021196
}
12031197
length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
12041198
fsi->bool_pending_values[index]);
1205-
ret = simple_read_from_buffer(buf, count, ppos, page, length);
1206-
out:
12071199
mutex_unlock(&fsi->mutex);
1200+
ret = simple_read_from_buffer(buf, count, ppos, page, length);
1201+
out_free:
12081202
free_page((unsigned long)page);
12091203
return ret;
1204+
1205+
out_unlock:
1206+
mutex_unlock(&fsi->mutex);
1207+
goto out_free;
12101208
}
12111209

12121210
static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
@@ -1219,6 +1217,17 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
12191217
unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
12201218
const char *name = filep->f_path.dentry->d_name.name;
12211219

1220+
if (count >= PAGE_SIZE)
1221+
return -ENOMEM;
1222+
1223+
/* No partial writes. */
1224+
if (*ppos != 0)
1225+
return -EINVAL;
1226+
1227+
page = memdup_user_nul(buf, count);
1228+
if (IS_ERR(page))
1229+
return PTR_ERR(page);
1230+
12221231
mutex_lock(&fsi->mutex);
12231232

12241233
length = avc_has_perm(&selinux_state,
@@ -1233,22 +1242,6 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
12331242
fsi->bool_pending_names[index]))
12341243
goto out;
12351244

1236-
length = -ENOMEM;
1237-
if (count >= PAGE_SIZE)
1238-
goto out;
1239-
1240-
/* No partial writes. */
1241-
length = -EINVAL;
1242-
if (*ppos != 0)
1243-
goto out;
1244-
1245-
page = memdup_user_nul(buf, count);
1246-
if (IS_ERR(page)) {
1247-
length = PTR_ERR(page);
1248-
page = NULL;
1249-
goto out;
1250-
}
1251-
12521245
length = -EINVAL;
12531246
if (sscanf(page, "%d", &new_value) != 1)
12541247
goto out;
@@ -1280,6 +1273,17 @@ static ssize_t sel_commit_bools_write(struct file *filep,
12801273
ssize_t length;
12811274
int new_value;
12821275

1276+
if (count >= PAGE_SIZE)
1277+
return -ENOMEM;
1278+
1279+
/* No partial writes. */
1280+
if (*ppos != 0)
1281+
return -EINVAL;
1282+
1283+
page = memdup_user_nul(buf, count);
1284+
if (IS_ERR(page))
1285+
return PTR_ERR(page);
1286+
12831287
mutex_lock(&fsi->mutex);
12841288

12851289
length = avc_has_perm(&selinux_state,
@@ -1289,22 +1293,6 @@ static ssize_t sel_commit_bools_write(struct file *filep,
12891293
if (length)
12901294
goto out;
12911295

1292-
length = -ENOMEM;
1293-
if (count >= PAGE_SIZE)
1294-
goto out;
1295-
1296-
/* No partial writes. */
1297-
length = -EINVAL;
1298-
if (*ppos != 0)
1299-
goto out;
1300-
1301-
page = memdup_user_nul(buf, count);
1302-
if (IS_ERR(page)) {
1303-
length = PTR_ERR(page);
1304-
page = NULL;
1305-
goto out;
1306-
}
1307-
13081296
length = -EINVAL;
13091297
if (sscanf(page, "%d", &new_value) != 1)
13101298
goto out;

0 commit comments

Comments
 (0)