aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/selinuxfs.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-13 17:50:25 -0400
committerJames Morris <jmorris@namei.org>2010-10-20 19:12:58 -0400
commitcee74f47a6baba0ac457e87687fdcf0abd599f0a (patch)
tree3d9fdb073050664e62d9cdb6c28112090cd138da /security/selinux/selinuxfs.c
parent00d85c83ac52e2c1a66397f1abc589f80c543425 (diff)
SELinux: allow userspace to read policy back out of the kernel
There is interest in being able to see what the actual policy is that was loaded into the kernel. The patch creates a new selinuxfs file /selinux/policy which can be read by userspace. The actual policy that is loaded into the kernel will be written back out to userspace. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
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);