summaryrefslogtreecommitdiff
path: root/security/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/inode.c')
-rw-r--r--security/inode.c81
1 files changed, 55 insertions, 26 deletions
diff --git a/security/inode.c b/security/inode.c
index 43382ef8896e..81fb5d6dd33e 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -22,6 +22,8 @@
#include <linux/lsm_hooks.h>
#include <linux/magic.h>
+#include "lsm.h"
+
static struct vfsmount *mount;
static int mount_count;
@@ -70,7 +72,7 @@ static struct file_system_type fs_type = {
.owner = THIS_MODULE,
.name = "securityfs",
.init_fs_context = securityfs_init_fs_context,
- .kill_sb = kill_litter_super,
+ .kill_sb = kill_anon_super,
};
/**
@@ -127,24 +129,19 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
parent = mount->mnt_root;
}
- dir = d_inode(parent);
-
- inode_lock(dir);
- dentry = lookup_noperm(&QSTR(name), parent);
- if (IS_ERR(dentry))
+ inode = new_inode(parent->d_sb);
+ if (unlikely(!inode)) {
+ dentry = ERR_PTR(-ENOMEM);
goto out;
-
- if (d_really_is_positive(dentry)) {
- error = -EEXIST;
- goto out1;
}
- inode = new_inode(dir->i_sb);
- if (!inode) {
- error = -ENOMEM;
- goto out1;
- }
+ dir = d_inode(parent);
+ dentry = simple_start_creating(parent, name);
+ if (IS_ERR(dentry)) {
+ iput(inode);
+ goto out;
+ }
inode->i_ino = get_next_ino();
inode->i_mode = mode;
simple_inode_init_ts(inode);
@@ -160,15 +157,11 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
} else {
inode->i_fop = fops;
}
- d_instantiate(dentry, inode);
- inode_unlock(dir);
- return dentry;
+ d_make_persistent(dentry, inode);
+ simple_done_creating(dentry);
+ return dentry; // borrowed
-out1:
- dput(dentry);
- dentry = ERR_PTR(error);
out:
- inode_unlock(dir);
if (pinned)
simple_release_fs(&mount, &mount_count);
return dentry;
@@ -315,12 +308,49 @@ void securityfs_remove(struct dentry *dentry)
EXPORT_SYMBOL_GPL(securityfs_remove);
#ifdef CONFIG_SECURITY
+#include <linux/spinlock.h>
+
static struct dentry *lsm_dentry;
+
static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count,
loff_t *ppos)
{
- return simple_read_from_buffer(buf, count, ppos, lsm_names,
- strlen(lsm_names));
+ int i;
+ static char *str;
+ static size_t len;
+ static DEFINE_SPINLOCK(lock);
+
+ /* NOTE: we never free or modify the string once it is set */
+
+ if (unlikely(!str || !len)) {
+ char *str_tmp;
+ size_t len_tmp = 0;
+
+ for (i = 0; i < lsm_active_cnt; i++)
+ /* the '+ 1' accounts for either a comma or a NUL */
+ len_tmp += strlen(lsm_idlist[i]->name) + 1;
+
+ str_tmp = kmalloc(len_tmp, GFP_KERNEL);
+ if (!str_tmp)
+ return -ENOMEM;
+ str_tmp[0] = '\0';
+
+ for (i = 0; i < lsm_active_cnt; i++) {
+ if (i > 0)
+ strcat(str_tmp, ",");
+ strcat(str_tmp, lsm_idlist[i]->name);
+ }
+
+ spin_lock(&lock);
+ if (!str) {
+ str = str_tmp;
+ len = len_tmp - 1;
+ } else
+ kfree(str_tmp);
+ spin_unlock(&lock);
+ }
+
+ return simple_read_from_buffer(buf, count, ppos, str, len);
}
static const struct file_operations lsm_ops = {
@@ -329,7 +359,7 @@ static const struct file_operations lsm_ops = {
};
#endif
-static int __init securityfs_init(void)
+int __init securityfs_init(void)
{
int retval;
@@ -348,4 +378,3 @@ static int __init securityfs_init(void)
#endif
return 0;
}
-core_initcall(securityfs_init);