aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r--security/selinux/selinuxfs.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index a2e7a8563b38..8eb102c72606 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -68,6 +68,8 @@ static int *bool_pending_values;
68static struct dentry *class_dir; 68static struct dentry *class_dir;
69static unsigned long last_class_ino; 69static unsigned long last_class_ino;
70 70
71static char policy_opened;
72
71/* global data for policy capabilities */ 73/* global data for policy capabilities */
72static struct dentry *policycap_dir; 74static struct dentry *policycap_dir;
73 75
@@ -111,6 +113,7 @@ enum sel_inos {
111 SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */ 113 SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
112 SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ 114 SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
113 SEL_STATUS, /* export current status using mmap() */ 115 SEL_STATUS, /* export current status using mmap() */
116 SEL_POLICY, /* allow userspace to read the in kernel policy */
114 SEL_INO_NEXT, /* The next inode number to use */ 117 SEL_INO_NEXT, /* The next inode number to use */
115}; 118};
116 119
@@ -351,6 +354,97 @@ static const struct file_operations sel_mls_ops = {
351 .llseek = generic_file_llseek, 354 .llseek = generic_file_llseek,
352}; 355};
353 356
357struct policy_load_memory {
358 size_t len;
359 void *data;
360};
361
362static int sel_open_policy(struct inode *inode, struct file *filp)
363{
364 struct policy_load_memory *plm = NULL;
365 int rc;
366
367 BUG_ON(filp->private_data);
368
369 mutex_lock(&sel_mutex);
370
371 rc = task_has_security(current, SECURITY__READ_POLICY);
372 if (rc)
373 goto err;
374
375 rc = -EBUSY;
376 if (policy_opened)
377 goto err;
378
379 rc = -ENOMEM;
380 plm = kzalloc(sizeof(*plm), GFP_KERNEL);
381 if (!plm)
382 goto err;
383
384 if (i_size_read(inode) != security_policydb_len()) {
385 mutex_lock(&inode->i_mutex);
386 i_size_write(inode, security_policydb_len());
387 mutex_unlock(&inode->i_mutex);
388 }
389
390 rc = security_read_policy(&plm->data, &plm->len);
391 if (rc)
392 goto err;
393
394 policy_opened = 1;
395
396 filp->private_data = plm;
397
398 mutex_unlock(&sel_mutex);
399
400 return 0;
401err:
402 mutex_unlock(&sel_mutex);
403
404 if (plm)
405 vfree(plm->data);
406 kfree(plm);
407 return rc;
408}
409
410static int sel_release_policy(struct inode *inode, struct file *filp)
411{
412 struct policy_load_memory *plm = filp->private_data;
413
414 BUG_ON(!plm);
415
416 policy_opened = 0;
417
418 vfree(plm->data);
419 kfree(plm);
420
421 return 0;
422}
423
424static ssize_t sel_read_policy(struct file *filp, char __user *buf,
425 size_t count, loff_t *ppos)
426{
427 struct policy_load_memory *plm = filp->private_data;
428 int ret;
429
430 mutex_lock(&sel_mutex);
431
432 ret = task_has_security(current, SECURITY__READ_POLICY);
433 if (ret)
434 goto out;
435
436 ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
437out:
438 mutex_unlock(&sel_mutex);
439 return ret;
440}
441
442static const struct file_operations sel_policy_ops = {
443 .open = sel_open_policy,
444 .read = sel_read_policy,
445 .release = sel_release_policy,
446};
447
354static ssize_t sel_write_load(struct file *file, const char __user *buf, 448static ssize_t sel_write_load(struct file *file, const char __user *buf,
355 size_t count, loff_t *ppos) 449 size_t count, loff_t *ppos)
356 450
@@ -1668,6 +1762,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
1668 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1762 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1669 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, 1763 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
1670 [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, 1764 [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
1765 [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
1671 /* last one */ {""} 1766 /* last one */ {""}
1672 }; 1767 };
1673 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1768 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);