mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
selinuxfs: new helper for attaching files to tree
allocating dentry after the inode has been set up reduces the amount of boilerplate - "attach this inode under that name and this parent or drop inode in case of failure" simplifies quite a few places. Acked-by: Paul Moore <paul@paul-moore.com> Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com> Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -1197,6 +1197,25 @@ static struct inode *sel_make_inode(struct super_block *sb, umode_t mode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dentry *sel_attach(struct dentry *parent, const char *name,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct dentry *dentry = d_alloc_name(parent, name);
|
||||
if (unlikely(!dentry)) {
|
||||
iput(inode);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
d_add(dentry, inode);
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static int sel_attach_file(struct dentry *parent, const char *name,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct dentry *dentry = sel_attach(parent, name, inode);
|
||||
return PTR_ERR_OR_ZERO(dentry);
|
||||
}
|
||||
|
||||
static ssize_t sel_read_bool(struct file *filep, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@@ -1356,8 +1375,7 @@ static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_
|
||||
*bool_num = num;
|
||||
*bool_pending_names = names;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
struct dentry *dentry;
|
||||
for (i = 0; !ret && i < num; i++) {
|
||||
struct inode *inode;
|
||||
struct inode_security_struct *isec;
|
||||
ssize_t len;
|
||||
@@ -1368,15 +1386,9 @@ static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_
|
||||
ret = -ENAMETOOLONG;
|
||||
break;
|
||||
}
|
||||
dentry = d_alloc_name(bool_dir, names[i]);
|
||||
if (!dentry) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
inode = sel_make_inode(bool_dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
@@ -1394,7 +1406,8 @@ static int sel_make_bools(struct selinux_policy *newpolicy, struct dentry *bool_
|
||||
isec->initialized = LABEL_INITIALIZED;
|
||||
inode->i_fop = &sel_bool_ops;
|
||||
inode->i_ino = i|SEL_BOOL_INO_OFFSET;
|
||||
d_add(dentry, inode);
|
||||
|
||||
ret = sel_attach_file(bool_dir, names[i], inode);
|
||||
}
|
||||
out:
|
||||
free_page((unsigned long)page);
|
||||
@@ -1579,6 +1592,7 @@ static int sel_make_avc_files(struct dentry *dir)
|
||||
struct super_block *sb = dir->d_sb;
|
||||
struct selinux_fs_info *fsi = sb->s_fs_info;
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
static const struct tree_descr files[] = {
|
||||
{ "cache_threshold",
|
||||
&sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR },
|
||||
@@ -1588,26 +1602,20 @@ static int sel_make_avc_files(struct dentry *dir)
|
||||
#endif
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
for (i = 0; !err && i < ARRAY_SIZE(files); i++) {
|
||||
struct inode *inode;
|
||||
struct dentry *dentry;
|
||||
|
||||
dentry = d_alloc_name(dir, files[i].name);
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode->i_fop = files[i].ops;
|
||||
inode->i_ino = ++fsi->last_ino;
|
||||
d_add(dentry, inode);
|
||||
|
||||
err = sel_attach_file(dir, files[i].name, inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sel_make_ss_files(struct dentry *dir)
|
||||
@@ -1615,30 +1623,25 @@ static int sel_make_ss_files(struct dentry *dir)
|
||||
struct super_block *sb = dir->d_sb;
|
||||
struct selinux_fs_info *fsi = sb->s_fs_info;
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
static const struct tree_descr files[] = {
|
||||
{ "sidtab_hash_stats", &sel_sidtab_hash_stats_ops, S_IRUGO },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(files); i++) {
|
||||
for (i = 0; !err && i < ARRAY_SIZE(files); i++) {
|
||||
struct inode *inode;
|
||||
struct dentry *dentry;
|
||||
|
||||
dentry = d_alloc_name(dir, files[i].name);
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode->i_fop = files[i].ops;
|
||||
inode->i_ino = ++fsi->last_ino;
|
||||
d_add(dentry, inode);
|
||||
|
||||
err = sel_attach_file(dir, files[i].name, inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t sel_read_initcon(struct file *file, char __user *buf,
|
||||
@@ -1666,30 +1669,25 @@ static const struct file_operations sel_initcon_ops = {
|
||||
static int sel_make_initcon_files(struct dentry *dir)
|
||||
{
|
||||
unsigned int i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 1; i <= SECINITSID_NUM; i++) {
|
||||
struct inode *inode;
|
||||
struct dentry *dentry;
|
||||
for (i = 1; !err && i <= SECINITSID_NUM; i++) {
|
||||
const char *s = security_get_initial_sid_context(i);
|
||||
struct inode *inode;
|
||||
|
||||
if (!s)
|
||||
continue;
|
||||
dentry = d_alloc_name(dir, s);
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode->i_fop = &sel_initcon_ops;
|
||||
inode->i_ino = i|SEL_INITCON_INO_OFFSET;
|
||||
d_add(dentry, inode);
|
||||
err = sel_attach_file(dir, s, inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline unsigned long sel_class_to_ino(u16 class)
|
||||
@@ -1771,29 +1769,21 @@ static int sel_make_perm_files(struct selinux_policy *newpolicy,
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < nperms; i++) {
|
||||
for (i = 0; !rc && i < nperms; i++) {
|
||||
struct inode *inode;
|
||||
struct dentry *dentry;
|
||||
|
||||
rc = -ENOMEM;
|
||||
dentry = d_alloc_name(dir, perms[i]);
|
||||
if (!dentry)
|
||||
goto out;
|
||||
|
||||
rc = -ENOMEM;
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
goto out;
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
inode->i_fop = &sel_perm_ops;
|
||||
/* i+1 since perm values are 1-indexed */
|
||||
inode->i_ino = sel_perm_to_ino(classvalue, i + 1);
|
||||
d_add(dentry, inode);
|
||||
|
||||
rc = sel_attach_file(dir, perms[i], inode);
|
||||
}
|
||||
rc = 0;
|
||||
out:
|
||||
for (i = 0; i < nperms; i++)
|
||||
kfree(perms[i]);
|
||||
kfree(perms);
|
||||
@@ -1808,20 +1798,18 @@ static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
|
||||
struct selinux_fs_info *fsi = sb->s_fs_info;
|
||||
struct dentry *dentry = NULL;
|
||||
struct inode *inode = NULL;
|
||||
|
||||
dentry = d_alloc_name(dir, "index");
|
||||
if (!dentry)
|
||||
return -ENOMEM;
|
||||
int err;
|
||||
|
||||
inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode->i_fop = &sel_class_ops;
|
||||
inode->i_ino = sel_class_to_ino(index);
|
||||
d_add(dentry, inode);
|
||||
|
||||
err = sel_attach_file(dir, "index", inode);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
dentry = sel_make_dir(dir, "perms", &fsi->last_class_ino);
|
||||
if (IS_ERR(dentry))
|
||||
@@ -1873,58 +1861,47 @@ static int sel_make_policycap(struct dentry *dir)
|
||||
{
|
||||
struct super_block *sb = dir->d_sb;
|
||||
unsigned int iter;
|
||||
struct dentry *dentry = NULL;
|
||||
struct inode *inode = NULL;
|
||||
int err = 0;
|
||||
|
||||
for (iter = 0; !err && iter <= POLICYDB_CAP_MAX; iter++) {
|
||||
const char *name;
|
||||
|
||||
for (iter = 0; iter <= POLICYDB_CAP_MAX; iter++) {
|
||||
if (iter < ARRAY_SIZE(selinux_policycap_names))
|
||||
dentry = d_alloc_name(dir,
|
||||
selinux_policycap_names[iter]);
|
||||
name = selinux_policycap_names[iter];
|
||||
else
|
||||
dentry = d_alloc_name(dir, "unknown");
|
||||
|
||||
if (dentry == NULL)
|
||||
return -ENOMEM;
|
||||
name = "unknown";
|
||||
|
||||
inode = sel_make_inode(sb, S_IFREG | 0444);
|
||||
if (inode == NULL) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode->i_fop = &sel_policycap_ops;
|
||||
inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET;
|
||||
d_add(dentry, inode);
|
||||
err = sel_attach_file(dir, name, inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
|
||||
unsigned long *ino)
|
||||
{
|
||||
struct dentry *dentry = d_alloc_name(dir, name);
|
||||
struct inode *inode;
|
||||
|
||||
if (!dentry)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
inode = sel_make_inode(dir->d_sb, S_IFDIR | S_IRUGO | S_IXUGO);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
inode->i_ino = ++(*ino);
|
||||
/* directory inodes start off with i_nlink == 2 (for "." entry) */
|
||||
inc_nlink(inode);
|
||||
d_add(dentry, inode);
|
||||
/* bump link count on parent directory, too */
|
||||
inc_nlink(d_inode(dir));
|
||||
|
||||
return dentry;
|
||||
return sel_attach(dir, name, inode);
|
||||
}
|
||||
|
||||
static int reject_all(struct mnt_idmap *idmap, struct inode *inode, int mask)
|
||||
@@ -2012,17 +1989,10 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
|
||||
if (!dentry)
|
||||
goto err;
|
||||
|
||||
ret = -ENOMEM;
|
||||
inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
|
||||
if (!inode) {
|
||||
dput(dentry);
|
||||
if (!inode)
|
||||
goto err;
|
||||
}
|
||||
|
||||
inode->i_ino = ++fsi->last_ino;
|
||||
isec = selinux_inode(inode);
|
||||
@@ -2031,7 +2001,9 @@ static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
isec->initialized = LABEL_INITIALIZED;
|
||||
|
||||
init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
|
||||
d_add(dentry, inode);
|
||||
ret = sel_attach_file(sb->s_root, NULL_FILE_NAME, inode);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
dentry = sel_make_dir(sb->s_root, "avc", &fsi->last_ino);
|
||||
if (IS_ERR(dentry)) {
|
||||
|
||||
Reference in New Issue
Block a user