Skip to content

Commit

Permalink
fs/vfs/security: pass last path component to LSM on inode creation
Browse files Browse the repository at this point in the history
SELinux would like to implement a new labeling behavior of newly created
inodes.  We currently label new inodes based on the parent and the creating
process.  This new behavior would also take into account the name of the
new object when deciding the new label.  This is not the (supposed) full path,
just the last component of the path.

This is very useful because creating /etc/shadow is different than creating
/etc/passwd but the kernel hooks are unable to differentiate these
operations.  We currently require that userspace realize it is doing some
difficult operation like that and than userspace jumps through SELinux hoops
to get things set up correctly.  This patch does not implement new
behavior, that is obviously contained in a seperate SELinux patch, but it
does pass the needed name down to the correct LSM hook.  If no such name
exists it is fine to pass NULL.

Signed-off-by: Eric Paris <[email protected]>
  • Loading branch information
eparis committed Feb 1, 2011
1 parent 8214044 commit 2a7dba3
Show file tree
Hide file tree
Showing 39 changed files with 136 additions and 94 deletions.
13 changes: 7 additions & 6 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode,
unsigned long *nr_written, int unlock);

static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir)
struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;

err = btrfs_init_acl(trans, inode, dir);
if (!err)
err = btrfs_xattr_security_init(trans, inode, dir);
err = btrfs_xattr_security_init(trans, inode, dir, qstr);
return err;
}

Expand Down Expand Up @@ -4675,7 +4676,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down Expand Up @@ -4736,7 +4737,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down Expand Up @@ -4864,7 +4865,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

drop_on_err = 1;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err)
goto out_fail;

Expand Down Expand Up @@ -6946,7 +6947,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode))
goto out_unlock;

err = btrfs_init_inode_security(trans, inode, dir);
err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
if (err) {
drop_inode = 1;
goto out_unlock;
Expand Down
6 changes: 4 additions & 2 deletions fs/btrfs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,17 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
}

int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir)
struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *suffix;
char *name;

err = security_inode_init_security(inode, dir, &suffix, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
&len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name,
extern int btrfs_removexattr(struct dentry *dentry, const char *name);

extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
struct inode *inode, struct inode *dir);
struct inode *inode, struct inode *dir,
const struct qstr *qstr);

#endif /* __XATTR__ */
2 changes: 1 addition & 1 deletion fs/ext2/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int);

/* ialloc.c */
extern struct inode * ext2_new_inode (struct inode *, int);
extern struct inode * ext2_new_inode (struct inode *, int, const struct qstr *);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
extern void ext2_check_inodes_bitmap (struct super_block *);
Expand Down
5 changes: 3 additions & 2 deletions fs/ext2/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
return group;
}

struct inode *ext2_new_inode(struct inode *dir, int mode)
struct inode *ext2_new_inode(struct inode *dir, int mode,
const struct qstr *qstr)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
Expand Down Expand Up @@ -585,7 +586,7 @@ struct inode *ext2_new_inode(struct inode *dir, int mode)
if (err)
goto fail_free_drop;

err = ext2_init_security(inode,dir);
err = ext2_init_security(inode, dir, qstr);
if (err)
goto fail_free_drop;

Expand Down
8 changes: 4 additions & 4 deletions fs/ext2/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st

dquot_initialize(dir);

inode = ext2_new_inode(dir, mode);
inode = ext2_new_inode(dir, mode, &dentry->d_name);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_

dquot_initialize(dir);

inode = ext2_new_inode (dir, mode);
inode = ext2_new_inode (dir, mode, &dentry->d_name);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, inode->i_mode, rdev);
Expand All @@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,

dquot_initialize(dir);

inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out;
Expand Down Expand Up @@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)

inode_inc_link_count(dir);

inode = ext2_new_inode (dir, S_IFDIR | mode);
inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_dir;
Expand Down
6 changes: 4 additions & 2 deletions fs/ext2/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,11 @@ exit_ext2_xattr(void)
# endif /* CONFIG_EXT2_FS_XATTR */

#ifdef CONFIG_EXT2_FS_SECURITY
extern int ext2_init_security(struct inode *inode, struct inode *dir);
extern int ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr);
#else
static inline int ext2_init_security(struct inode *inode, struct inode *dir)
static inline int ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions fs/ext2/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
}

int
ext2_init_security(struct inode *inode, struct inode *dir)
ext2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *name;

err = security_inode_init_security(inode, dir, &name, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
5 changes: 3 additions & 2 deletions fs/ext3/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
* For other inodes, search forward from the parent directory's block
* group to find a free inode.
*/
struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
const struct qstr *qstr, int mode)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
Expand Down Expand Up @@ -589,7 +590,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
if (err)
goto fail_free_drop;

err = ext3_init_security(handle,inode, dir);
err = ext3_init_security(handle, inode, dir, qstr);
if (err)
goto fail_free_drop;

Expand Down
8 changes: 4 additions & 4 deletions fs/ext3/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1707,7 +1707,7 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
if (IS_DIRSYNC(dir))
handle->h_sync = 1;

inode = ext3_new_inode (handle, dir, mode);
inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
inode->i_op = &ext3_file_inode_operations;
Expand Down Expand Up @@ -1743,7 +1743,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
if (IS_DIRSYNC(dir))
handle->h_sync = 1;

inode = ext3_new_inode (handle, dir, mode);
inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
init_special_inode(inode, inode->i_mode, rdev);
Expand Down Expand Up @@ -1781,7 +1781,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if (IS_DIRSYNC(dir))
handle->h_sync = 1;

inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFDIR | mode);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_stop;
Expand Down Expand Up @@ -2195,7 +2195,7 @@ static int ext3_symlink (struct inode * dir,
if (IS_DIRSYNC(dir))
handle->h_sync = 1;

inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFLNK|S_IRWXUGO);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_stop;
Expand Down
4 changes: 2 additions & 2 deletions fs/ext3/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ exit_ext3_xattr(void)

#ifdef CONFIG_EXT3_FS_SECURITY
extern int ext3_init_security(handle_t *handle, struct inode *inode,
struct inode *dir);
struct inode *dir, const struct qstr *qstr);
#else
static inline int ext3_init_security(handle_t *handle, struct inode *inode,
struct inode *dir)
struct inode *dir, const struct qstr *qstr)
{
return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions fs/ext3/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
}

int
ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *name;

err = security_inode_init_security(inode, dir, &name, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
2 changes: 1 addition & 1 deletion fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
if (err)
goto fail_free_drop;

err = ext4_init_security(handle, inode, dir);
err = ext4_init_security(handle, inode, dir, qstr);
if (err)
goto fail_free_drop;

Expand Down
4 changes: 2 additions & 2 deletions fs/ext4/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,

#ifdef CONFIG_EXT4_FS_SECURITY
extern int ext4_init_security(handle_t *handle, struct inode *inode,
struct inode *dir);
struct inode *dir, const struct qstr *qstr);
#else
static inline int ext4_init_security(handle_t *handle, struct inode *inode,
struct inode *dir)
struct inode *dir, const struct qstr *qstr)
{
return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions fs/ext4/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
}

int
ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *name;

err = security_inode_init_security(inode, dir, &name, &value, &len);
err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
if (err) {
if (err == -EOPNOTSUPP)
return 0;
Expand Down
7 changes: 4 additions & 3 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,14 +791,15 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
return error;
}

static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
const struct qstr *qstr)
{
int err;
size_t len;
void *value;
char *name;

err = security_inode_init_security(&ip->i_inode, &dip->i_inode,
err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
&name, &value, &len);

if (err) {
Expand Down Expand Up @@ -882,7 +883,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock2;

error = gfs2_security_init(dip, GFS2_I(inode));
error = gfs2_security_init(dip, GFS2_I(inode), name);
if (error)
goto fail_gunlock2;

Expand Down
9 changes: 4 additions & 5 deletions fs/jffs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
no chance of AB-BA deadlock involving its f->sem). */
mutex_unlock(&f->sem);

ret = jffs2_do_create(c, dir_f, f, ri,
dentry->d_name.name, dentry->d_name.len);
ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name);
if (ret)
goto fail;

Expand Down Expand Up @@ -386,7 +385,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char

jffs2_complete_reservation(c);

ret = jffs2_init_security(inode, dir_i);
ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
if (ret)
goto fail;

Expand Down Expand Up @@ -530,7 +529,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)

jffs2_complete_reservation(c);

ret = jffs2_init_security(inode, dir_i);
ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
if (ret)
goto fail;

Expand Down Expand Up @@ -703,7 +702,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de

jffs2_complete_reservation(c);

ret = jffs2_init_security(inode, dir_i);
ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
if (ret)
goto fail;

Expand Down
2 changes: 1 addition & 1 deletion fs/jffs2/nodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
struct jffs2_raw_inode *ri, unsigned char *buf,
uint32_t offset, uint32_t writelen, uint32_t *retlen);
int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
struct jffs2_raw_inode *ri, const char *name, int namelen);
struct jffs2_raw_inode *ri, const struct qstr *qstr);
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
Expand Down
5 changes: 3 additions & 2 deletions fs/jffs2/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
#include "nodelist.h"

/* ---- Initial Security Label Attachment -------------- */
int jffs2_init_security(struct inode *inode, struct inode *dir)
int jffs2_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr)
{
int rc;
size_t len;
void *value;
char *name;

rc = security_inode_init_security(inode, dir, &name, &value, &len);
rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
if (rc) {
if (rc == -EOPNOTSUPP)
return 0;
Expand Down
Loading

0 comments on commit 2a7dba3

Please sign in to comment.