diff options
| author | James Morris <jmorris@namei.org> | 2011-03-08 11:38:10 +1100 | 
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2011-03-08 11:38:10 +1100 | 
| commit | fe3fa43039d47ee4e22caf460b79b62a14937f79 (patch) | |
| tree | 9eab8d00f1227b9fe0959f32a62d892ed35803ba | |
| parent | ee009e4a0d4555ed522a631bae9896399674f064 (diff) | |
| parent | 026eb167ae77244458fa4b4b9fc171209c079ba7 (diff) | |
| download | olio-linux-3.10-fe3fa43039d47ee4e22caf460b79b62a14937f79.tar.xz olio-linux-3.10-fe3fa43039d47ee4e22caf460b79b62a14937f79.zip  | |
Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next
52 files changed, 594 insertions, 323 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0efdb65953c..a45785ab197 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -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;  } @@ -4704,7 +4705,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; @@ -4765,7 +4766,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; @@ -4893,7 +4894,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; @@ -7104,7 +7105,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; diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index a5776531dc2..d779cefcfd7 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -370,7 +370,8 @@ 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; @@ -378,7 +379,8 @@ int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,  	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; diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h index 7a43fd640bb..b3cc8039134 100644 --- a/fs/btrfs/xattr.h +++ b/fs/btrfs/xattr.h @@ -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__ */ diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 6346a2acf32..1b48c337087 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -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 *); diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index ad70479aabf..ee9ed31948e 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -429,7 +429,8 @@ found:  	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; @@ -585,7 +586,7 @@ got:  	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; diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index adb91855ccd..ed5c5d496ee 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -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); @@ -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); @@ -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; @@ -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; diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h index a1a1c218461..5e41cccff76 100644 --- a/fs/ext2/xattr.h +++ b/fs/ext2/xattr.h @@ -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;  } diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index 3004e15d5da..5d979b4347b 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -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; diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 9724aef2246..bfc2dc43681 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -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; @@ -589,7 +590,7 @@ got:  	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; diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index b27ba71810e..9dba3bd69d9 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1710,7 +1710,7 @@ retry:  	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; @@ -1746,7 +1746,7 @@ retry:  	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); @@ -1784,7 +1784,7 @@ retry:  	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; @@ -2206,7 +2206,7 @@ retry:  	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; diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 377fe720116..2be4f69bfa6 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -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;  } diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c index 03a99bfc59f..b8d9f83aa5c 100644 --- a/fs/ext3/xattr_security.c +++ b/fs/ext3/xattr_security.c @@ -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; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index eb9097aec6f..78b79e1bd7e 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1042,7 +1042,7 @@ got:  	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; diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index 1ef16520b95..25b7387ff18 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h @@ -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;  } diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index 9b21268e121..007c3bfbf09 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -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; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 7aa7d4f8984..97d54a28776 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -763,14 +763,15 @@ fail:  	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) { @@ -854,7 +855,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; diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 92978658ed1..82faddd1f32 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -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; @@ -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; @@ -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; @@ -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; diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 5a53d9bdb2b..e4619b00f7c 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -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, diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c index 239f51216a6..cfeb7164b08 100644 --- a/fs/jffs2/security.c +++ b/fs/jffs2/security.c @@ -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; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index c819eb0e982..30d175b6d29 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -424,7 +424,9 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,  	return ret;  } -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) +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 struct qstr *qstr)  {  	struct jffs2_raw_dirent *rd;  	struct jffs2_full_dnode *fn; @@ -466,15 +468,15 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str  	mutex_unlock(&f->sem);  	jffs2_complete_reservation(c); -	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode); +	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);  	if (ret)  		return ret;  	ret = jffs2_init_acl_post(&f->vfs_inode);  	if (ret)  		return ret; -	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, -				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); +	ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen, +				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len));  	if (ret) {  		/* Eep. */ @@ -493,19 +495,19 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str  	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);  	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); -	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); +	rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len);  	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));  	rd->pino = cpu_to_je32(dir_f->inocache->ino);  	rd->version = cpu_to_je32(++dir_f->highest_version);  	rd->ino = ri->ino;  	rd->mctime = ri->ctime; -	rd->nsize = namelen; +	rd->nsize = qstr->len;  	rd->type = DT_REG;  	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); -	rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); +	rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len)); -	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); +	fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL);  	jffs2_free_raw_dirent(rd); diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h index cf4f5759b42..7be4beb306f 100644 --- a/fs/jffs2/xattr.h +++ b/fs/jffs2/xattr.h @@ -121,10 +121,11 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);  #endif /* CONFIG_JFFS2_FS_XATTR */  #ifdef CONFIG_JFFS2_FS_SECURITY -extern int jffs2_init_security(struct inode *inode, struct inode *dir); +extern int jffs2_init_security(struct inode *inode, struct inode *dir, +			       const struct qstr *qstr);  extern const struct xattr_handler jffs2_security_xattr_handler;  #else -#define jffs2_init_security(inode,dir)	(0) +#define jffs2_init_security(inode,dir,qstr)	(0)  #endif /* CONFIG_JFFS2_FS_SECURITY */  #endif /* _JFFS2_FS_XATTR_H_ */ diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h index 88b6cc535bf..e9e100fd7c0 100644 --- a/fs/jfs/jfs_xattr.h +++ b/fs/jfs/jfs_xattr.h @@ -62,10 +62,11 @@ extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);  extern int jfs_removexattr(struct dentry *, const char *);  #ifdef CONFIG_JFS_SECURITY -extern int jfs_init_security(tid_t, struct inode *, struct inode *); +extern int jfs_init_security(tid_t, struct inode *, struct inode *, +			     const struct qstr *);  #else  static inline int jfs_init_security(tid_t tid, struct inode *inode, -				    struct inode *dir) +				    struct inode *dir, const struct qstr *qstr)  {  	return 0;  } diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 81ead850ddb..2a37d2fdd70 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -115,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,  	if (rc)  		goto out3; -	rc = jfs_init_security(tid, ip, dip); +	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);  	if (rc) {  		txAbort(tid, 0);  		goto out3; @@ -253,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)  	if (rc)  		goto out3; -	rc = jfs_init_security(tid, ip, dip); +	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);  	if (rc) {  		txAbort(tid, 0);  		goto out3; @@ -932,7 +932,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,  	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);  	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); -	rc = jfs_init_security(tid, ip, dip); +	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);  	if (rc)  		goto out3; @@ -1395,7 +1395,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,  	if (rc)  		goto out3; -	rc = jfs_init_security(tid, ip, dir); +	rc = jfs_init_security(tid, ip, dir, &dentry->d_name);  	if (rc) {  		txAbort(tid, 0);  		goto out3; diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 2d7f165d0f1..3fa4c32272d 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -1091,7 +1091,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name)  }  #ifdef CONFIG_JFS_SECURITY -int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir) +int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, +		      const struct qstr *qstr)  {  	int rc;  	size_t len; @@ -1099,7 +1100,8 @@ int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)  	char *suffix;  	char *name; -	rc = security_inode_init_security(inode, dir, &suffix, &value, &len); +	rc = security_inode_init_security(inode, dir, qstr, &suffix, &value, +					  &len);  	if (rc) {  		if (rc == -EOPNOTSUPP)  			return 0; diff --git a/fs/namespace.c b/fs/namespace.c index d1edf26025d..a66feed7311 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1767,6 +1767,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,  	if (path->dentry != path->mnt->mnt_root)  		return -EINVAL; +	err = security_sb_remount(sb, data); +	if (err) +		return err; +  	down_write(&sb->s_umount);  	if (flags & MS_BIND)  		err = change_mount_flags(path->mnt, flags); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 849fb4a2e81..d6c25d76b53 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -293,7 +293,7 @@ static int ocfs2_mknod(struct inode *dir,  	}  	/* get security xattr */ -	status = ocfs2_init_security_get(inode, dir, &si); +	status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si);  	if (status) {  		if (status == -EOPNOTSUPP)  			si.enable = 0; @@ -1665,7 +1665,7 @@ static int ocfs2_symlink(struct inode *dir,  	}  	/* get security xattr */ -	status = ocfs2_init_security_get(inode, dir, &si); +	status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si);  	if (status) {  		if (status == -EOPNOTSUPP)  			si.enable = 0; diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 19ebc5aad39..35798b88042 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -4328,7 +4328,8 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,  	/* If the security isn't preserved, we need to re-initialize them. */  	if (!preserve) { -		error = ocfs2_init_security_and_acl(dir, new_orphan_inode); +		error = ocfs2_init_security_and_acl(dir, new_orphan_inode, +						    &new_dentry->d_name);  		if (error)  			mlog_errno(error);  	} diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 67cd4391464..6bb602486c6 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -7185,7 +7185,8 @@ out:   * must not hold any lock expect i_mutex.   */  int ocfs2_init_security_and_acl(struct inode *dir, -				struct inode *inode) +				struct inode *inode, +				const struct qstr *qstr)  {  	int ret = 0;  	struct buffer_head *dir_bh = NULL; @@ -7193,7 +7194,7 @@ int ocfs2_init_security_and_acl(struct inode *dir,  		.enable = 1,  	}; -	ret = ocfs2_init_security_get(inode, dir, &si); +	ret = ocfs2_init_security_get(inode, dir, qstr, &si);  	if (!ret) {  		ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,  				      si.name, si.value, si.value_len, @@ -7261,13 +7262,14 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,  int ocfs2_init_security_get(struct inode *inode,  			    struct inode *dir, +			    const struct qstr *qstr,  			    struct ocfs2_security_xattr_info *si)  {  	/* check whether ocfs2 support feature xattr */  	if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))  		return -EOPNOTSUPP; -	return security_inode_init_security(inode, dir, &si->name, &si->value, -					    &si->value_len); +	return security_inode_init_security(inode, dir, qstr, &si->name, +					    &si->value, &si->value_len);  }  int ocfs2_init_security_set(handle_t *handle, diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h index aa64bb37a65..d63cfb72316 100644 --- a/fs/ocfs2/xattr.h +++ b/fs/ocfs2/xattr.h @@ -57,6 +57,7 @@ int ocfs2_has_inline_xattr_value_outside(struct inode *inode,  					 struct ocfs2_dinode *di);  int ocfs2_xattr_remove(struct inode *, struct buffer_head *);  int ocfs2_init_security_get(struct inode *, struct inode *, +			    const struct qstr *,  			    struct ocfs2_security_xattr_info *);  int ocfs2_init_security_set(handle_t *, struct inode *,  			    struct buffer_head *, @@ -94,5 +95,6 @@ int ocfs2_reflink_xattrs(struct inode *old_inode,  			 struct buffer_head *new_bh,  			 bool preserve_security);  int ocfs2_init_security_and_acl(struct inode *dir, -				struct inode *inode); +				struct inode *inode, +				const struct qstr *qstr);  #endif /* OCFS2_XATTR_H */ diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 09a1f92a34e..fb707e018a8 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -32,7 +32,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,  	ei->sysctl_entry = table;  	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; -	inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */  	inode->i_mode = table->mode;  	if (!table->child) {  		inode->i_mode |= S_IFREG; diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 68fdf45cc6c..82f45542dcf 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -593,7 +593,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,  	new_inode_init(inode, dir, mode);  	jbegin_count += reiserfs_cache_default_acl(dir); -	retval = reiserfs_security_init(dir, inode, &security); +	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);  	if (retval < 0) {  		drop_new_inode(inode);  		return retval; @@ -667,7 +667,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,  	new_inode_init(inode, dir, mode);  	jbegin_count += reiserfs_cache_default_acl(dir); -	retval = reiserfs_security_init(dir, inode, &security); +	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);  	if (retval < 0) {  		drop_new_inode(inode);  		return retval; @@ -747,7 +747,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  	new_inode_init(inode, dir, mode);  	jbegin_count += reiserfs_cache_default_acl(dir); -	retval = reiserfs_security_init(dir, inode, &security); +	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);  	if (retval < 0) {  		drop_new_inode(inode);  		return retval; @@ -1032,7 +1032,8 @@ static int reiserfs_symlink(struct inode *parent_dir,  	}  	new_inode_init(inode, parent_dir, mode); -	retval = reiserfs_security_init(parent_dir, inode, &security); +	retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name, +					&security);  	if (retval < 0) {  		drop_new_inode(inode);  		return retval; diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 237c6928d3c..ef66c18a933 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -54,6 +54,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len,   * of blocks needed for the transaction. If successful, reiserfs_security   * must be released using reiserfs_security_free when the caller is done. */  int reiserfs_security_init(struct inode *dir, struct inode *inode, +			   const struct qstr *qstr,  			   struct reiserfs_security_handle *sec)  {  	int blocks = 0; @@ -65,7 +66,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,  	if (IS_PRIVATE(dir))  		return 0; -	error = security_inode_init_security(inode, dir, &sec->name, +	error = security_inode_init_security(inode, dir, qstr, &sec->name,  					     &sec->value, &sec->length);  	if (error) {  		if (error == -EOPNOTSUPP) diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index bd5727852fd..9ff7fc603d2 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -102,7 +102,8 @@ xfs_mark_inode_dirty(  STATIC int  xfs_init_security(  	struct inode	*inode, -	struct inode	*dir) +	struct inode	*dir, +	const struct qstr *qstr)  {  	struct xfs_inode *ip = XFS_I(inode);  	size_t		length; @@ -110,7 +111,7 @@ xfs_init_security(  	unsigned char	*name;  	int		error; -	error = security_inode_init_security(inode, dir, (char **)&name, +	error = security_inode_init_security(inode, dir, qstr, (char **)&name,  					     &value, &length);  	if (error) {  		if (error == -EOPNOTSUPP) @@ -194,7 +195,7 @@ xfs_vn_mknod(  	inode = VFS_I(ip); -	error = xfs_init_security(inode, dir); +	error = xfs_init_security(inode, dir, &dentry->d_name);  	if (unlikely(error))  		goto out_cleanup_inode; @@ -367,7 +368,7 @@ xfs_vn_symlink(  	inode = VFS_I(cip); -	error = xfs_init_security(inode, dir); +	error = xfs_init_security(inode, dir, &dentry->d_name);  	if (unlikely(error))  		goto out_cleanup_inode; diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 65990ef612f..6043c64c207 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -884,7 +884,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct  			  dx_hash_info *hinfo);  /* ialloc.c */ -extern struct inode * ext3_new_inode (handle_t *, struct inode *, int); +extern struct inode * ext3_new_inode (handle_t *, struct inode *, +				      const struct qstr *, int);  extern void ext3_free_inode (handle_t *, struct inode *);  extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);  extern unsigned long ext3_count_free_inodes (struct super_block *); diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index 3b94c91f20a..6deef5dc95f 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h @@ -63,6 +63,7 @@ extern const struct xattr_handler reiserfs_xattr_trusted_handler;  extern const struct xattr_handler reiserfs_xattr_security_handler;  #ifdef CONFIG_REISERFS_FS_SECURITY  int reiserfs_security_init(struct inode *dir, struct inode *inode, +			   const struct qstr *qstr,  			   struct reiserfs_security_handle *sec);  int reiserfs_security_write(struct reiserfs_transaction_handle *th,  			    struct inode *inode, @@ -130,6 +131,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode)  #ifndef CONFIG_REISERFS_FS_SECURITY  static inline int reiserfs_security_init(struct inode *dir,  					 struct inode *inode, +					 const struct qstr *qstr,  					 struct reiserfs_security_handle *sec)  {  	return 0; diff --git a/include/linux/security.h b/include/linux/security.h index b2b7f9749f5..84a202ac3de 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -25,6 +25,7 @@  #include <linux/fs.h>  #include <linux/fsnotify.h>  #include <linux/binfmts.h> +#include <linux/dcache.h>  #include <linux/signal.h>  #include <linux/resource.h>  #include <linux/sem.h> @@ -267,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   *	@orig the original mount data copied from userspace.   *	@copy copied data which will be passed to the security module.   *	Returns 0 if the copy was successful. + * @sb_remount: + *	Extracts security system specifc mount options and verifys no changes + *	are being made to those options. + *	@sb superblock being remounted + *	@data contains the filesystem-specific data. + *	Return 0 if permission is granted.   * @sb_umount:   *	Check permission before the @mnt file system is unmounted.   *	@mnt contains the mounted file system. @@ -315,6 +322,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   *	then it should return -EOPNOTSUPP to skip this processing.   *	@inode contains the inode structure of the newly created inode.   *	@dir contains the inode structure of the parent directory. + *	@qstr contains the last path component of the new object   *	@name will be set to the allocated name suffix (e.g. selinux).   *	@value will be set to the allocated attribute value.   *	@len will be set to the length of the value. @@ -1257,12 +1265,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   *	@cap contains the capability <include/linux/capability.h>.   *	@audit: Whether to write an audit message or not   *	Return 0 if the capability is granted for @tsk. - * @sysctl: - *	Check permission before accessing the @table sysctl variable in the - *	manner specified by @op. - *	@table contains the ctl_table structure for the sysctl variable. - *	@op contains the operation (001 = search, 002 = write, 004 = read). - *	Return 0 if permission is granted.   * @syslog:   *	Check permission before accessing the kernel message ring or changing   *	logging to the console. @@ -1383,7 +1385,6 @@ struct security_operations {  		       const kernel_cap_t *permitted);  	int (*capable) (struct task_struct *tsk, const struct cred *cred,  			int cap, int audit); -	int (*sysctl) (struct ctl_table *table, int op);  	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);  	int (*quota_on) (struct dentry *dentry);  	int (*syslog) (int type); @@ -1399,6 +1400,7 @@ struct security_operations {  	int (*sb_alloc_security) (struct super_block *sb);  	void (*sb_free_security) (struct super_block *sb);  	int (*sb_copy_data) (char *orig, char *copy); +	int (*sb_remount) (struct super_block *sb, void *data);  	int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);  	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);  	int (*sb_statfs) (struct dentry *dentry); @@ -1435,7 +1437,8 @@ struct security_operations {  	int (*inode_alloc_security) (struct inode *inode);  	void (*inode_free_security) (struct inode *inode);  	int (*inode_init_security) (struct inode *inode, struct inode *dir, -				    char **name, void **value, size_t *len); +				    const struct qstr *qstr, char **name, +				    void **value, size_t *len);  	int (*inode_create) (struct inode *dir,  			     struct dentry *dentry, int mode);  	int (*inode_link) (struct dentry *old_dentry, @@ -1665,7 +1668,6 @@ int security_capset(struct cred *new, const struct cred *old,  int security_capable(const struct cred *cred, int cap);  int security_real_capable(struct task_struct *tsk, int cap);  int security_real_capable_noaudit(struct task_struct *tsk, int cap); -int security_sysctl(struct ctl_table *table, int op);  int security_quotactl(int cmds, int type, int id, struct super_block *sb);  int security_quota_on(struct dentry *dentry);  int security_syslog(int type); @@ -1681,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm);  int security_sb_alloc(struct super_block *sb);  void security_sb_free(struct super_block *sb);  int security_sb_copy_data(char *orig, char *copy); +int security_sb_remount(struct super_block *sb, void *data);  int security_sb_kern_mount(struct super_block *sb, int flags, void *data);  int security_sb_show_options(struct seq_file *m, struct super_block *sb);  int security_sb_statfs(struct dentry *dentry); @@ -1696,7 +1699,8 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);  int security_inode_alloc(struct inode *inode);  void security_inode_free(struct inode *inode);  int security_inode_init_security(struct inode *inode, struct inode *dir, -				  char **name, void **value, size_t *len); +				 const struct qstr *qstr, char **name, +				 void **value, size_t *len);  int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);  int security_inode_link(struct dentry *old_dentry, struct inode *dir,  			 struct dentry *new_dentry); @@ -1883,11 +1887,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)  	return ret;  } -static inline int security_sysctl(struct ctl_table *table, int op) -{ -	return 0; -} -  static inline int security_quotactl(int cmds, int type, int id,  				     struct super_block *sb)  { @@ -1964,6 +1963,11 @@ static inline int security_sb_copy_data(char *orig, char *copy)  	return 0;  } +static inline int security_sb_remount(struct super_block *sb, void *data) +{ +	return 0; +} +  static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data)  {  	return 0; @@ -2023,6 +2027,7 @@ static inline void security_inode_free(struct inode *inode)  static inline int security_inode_init_security(struct inode *inode,  						struct inode *dir, +						const struct qstr *qstr,  						char **name,  						void **value,  						size_t *len) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0f1bd83db98..56f6fc1178a 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1685,13 +1685,8 @@ static int test_perm(int mode, int op)  int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)  { -	int error;  	int mode; -	error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); -	if (error) -		return error; -  	if (root->permissions)  		mode = root->permissions(root, current->nsproxy, table);  	else diff --git a/mm/shmem.c b/mm/shmem.c index 5ee67c99060..7c9cdc6fe13 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1843,8 +1843,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)  	inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);  	if (inode) { -		error = security_inode_init_security(inode, dir, NULL, NULL, -						     NULL); +		error = security_inode_init_security(inode, dir, +						     &dentry->d_name, NULL, +						     NULL, NULL);  		if (error) {  			if (error != -EOPNOTSUPP) {  				iput(inode); @@ -1983,8 +1984,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s  	if (!inode)  		return -ENOSPC; -	error = security_inode_init_security(inode, dir, NULL, NULL, -					     NULL); +	error = security_inode_init_security(inode, dir, &dentry->d_name, NULL, +					     NULL, NULL);  	if (error) {  		if (error != -EOPNOTSUPP) {  			iput(inode); diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index 58a12c27870..539855ff31f 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c @@ -43,6 +43,8 @@ int main(int argc, char *argv[])  	int i, j, k;  	int isids_len;  	FILE *fout; +	const char *needle = "SOCKET"; +	char *substr;  	progname = argv[0]; @@ -88,6 +90,24 @@ int main(int argc, char *argv[])  		fprintf(fout, "%2d\n", i);  	}  	fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); +	fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n"); +	fprintf(fout, "{\n"); +	fprintf(fout, "\tbool sock = false;\n\n"); +	fprintf(fout, "\tswitch (kern_tclass) {\n"); +	for (i = 0; secclass_map[i].name; i++) { +		struct security_class_mapping *map = &secclass_map[i]; +		substr = strstr(map->name, needle); +		if (substr && strcmp(substr, needle) == 0) +			fprintf(fout, "\tcase SECCLASS_%s:\n", map->name); +	} +	fprintf(fout, "\t\tsock = true;\n"); +	fprintf(fout, "\t\tbreak;\n"); +	fprintf(fout, "\tdefault:\n"); +	fprintf(fout, "\t\tbreak;\n"); +	fprintf(fout, "\t}\n\n"); +	fprintf(fout, "\treturn sock;\n"); +	fprintf(fout, "}\n"); +  	fprintf(fout, "\n#endif\n");  	fclose(fout); diff --git a/security/capability.c b/security/capability.c index 2a5df2b7da8..ab3d807accc 100644 --- a/security/capability.c +++ b/security/capability.c @@ -12,11 +12,6 @@  #include <linux/security.h> -static int cap_sysctl(ctl_table *table, int op) -{ -	return 0; -} -  static int cap_syslog(int type)  {  	return 0; @@ -59,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy)  	return 0;  } +static int cap_sb_remount(struct super_block *sb, void *data) +{ +	return 0; +} +  static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data)  {  	return 0; @@ -118,7 +118,8 @@ static void cap_inode_free_security(struct inode *inode)  }  static int cap_inode_init_security(struct inode *inode, struct inode *dir, -				   char **name, void **value, size_t *len) +				   const struct qstr *qstr, char **name, +				   void **value, size_t *len)  {  	return -EOPNOTSUPP;  } @@ -880,7 +881,6 @@ void __init security_fixup_ops(struct security_operations *ops)  	set_to_cap_if_null(ops, capable);  	set_to_cap_if_null(ops, quotactl);  	set_to_cap_if_null(ops, quota_on); -	set_to_cap_if_null(ops, sysctl);  	set_to_cap_if_null(ops, syslog);  	set_to_cap_if_null(ops, settime);  	set_to_cap_if_null(ops, vm_enough_memory); @@ -892,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops)  	set_to_cap_if_null(ops, sb_alloc_security);  	set_to_cap_if_null(ops, sb_free_security);  	set_to_cap_if_null(ops, sb_copy_data); +	set_to_cap_if_null(ops, sb_remount);  	set_to_cap_if_null(ops, sb_kern_mount);  	set_to_cap_if_null(ops, sb_show_options);  	set_to_cap_if_null(ops, sb_statfs); diff --git a/security/security.c b/security/security.c index 1a4993b1144..47b8a447118 100644 --- a/security/security.c +++ b/security/security.c @@ -181,11 +181,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)  	return ret;  } -int security_sysctl(struct ctl_table *table, int op) -{ -	return security_ops->sysctl(table, op); -} -  int security_quotactl(int cmds, int type, int id, struct super_block *sb)  {  	return security_ops->quotactl(cmds, type, id, sb); @@ -271,6 +266,11 @@ int security_sb_copy_data(char *orig, char *copy)  }  EXPORT_SYMBOL(security_sb_copy_data); +int security_sb_remount(struct super_block *sb, void *data) +{ +	return security_ops->sb_remount(sb, data); +} +  int security_sb_kern_mount(struct super_block *sb, int flags, void *data)  {  	return security_ops->sb_kern_mount(sb, flags, data); @@ -335,11 +335,13 @@ void security_inode_free(struct inode *inode)  }  int security_inode_init_security(struct inode *inode, struct inode *dir, -				  char **name, void **value, size_t *len) +				 const struct qstr *qstr, char **name, +				 void **value, size_t *len)  {  	if (unlikely(IS_PRIVATE(inode)))  		return -EOPNOTSUPP; -	return security_ops->inode_init_security(inode, dir, name, value, len); +	return security_ops->inode_init_security(inode, dir, qstr, name, value, +						 len);  }  EXPORT_SYMBOL(security_inode_init_security); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c8d69927068..d52a9250741 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -24,9 +24,11 @@   */  #include <linux/init.h> +#include <linux/kd.h>  #include <linux/kernel.h>  #include <linux/tracehook.h>  #include <linux/errno.h> +#include <linux/ext2_fs.h>  #include <linux/sched.h>  #include <linux/security.h>  #include <linux/xattr.h> @@ -36,14 +38,15 @@  #include <linux/mman.h>  #include <linux/slab.h>  #include <linux/pagemap.h> +#include <linux/proc_fs.h>  #include <linux/swap.h>  #include <linux/spinlock.h>  #include <linux/syscalls.h> +#include <linux/dcache.h>  #include <linux/file.h>  #include <linux/fdtable.h>  #include <linux/namei.h>  #include <linux/mount.h> -#include <linux/proc_fs.h>  #include <linux/netfilter_ipv4.h>  #include <linux/netfilter_ipv6.h>  #include <linux/tty.h> @@ -70,7 +73,6 @@  #include <net/ipv6.h>  #include <linux/hugetlb.h>  #include <linux/personality.h> -#include <linux/sysctl.h>  #include <linux/audit.h>  #include <linux/string.h>  #include <linux/selinux.h> @@ -1120,39 +1122,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc  }  #ifdef CONFIG_PROC_FS -static int selinux_proc_get_sid(struct proc_dir_entry *de, +static int selinux_proc_get_sid(struct dentry *dentry,  				u16 tclass,  				u32 *sid)  { -	int buflen, rc; -	char *buffer, *path, *end; +	int rc; +	char *buffer, *path;  	buffer = (char *)__get_free_page(GFP_KERNEL);  	if (!buffer)  		return -ENOMEM; -	buflen = PAGE_SIZE; -	end = buffer+buflen; -	*--end = '\0'; -	buflen--; -	path = end-1; -	*path = '/'; -	while (de && de != de->parent) { -		buflen -= de->namelen + 1; -		if (buflen < 0) -			break; -		end -= de->namelen; -		memcpy(end, de->name, de->namelen); -		*--end = '/'; -		path = end; -		de = de->parent; +	path = dentry_path_raw(dentry, buffer, PAGE_SIZE); +	if (IS_ERR(path)) +		rc = PTR_ERR(path); +	else { +		/* each process gets a /proc/PID/ entry. Strip off the +		 * PID part to get a valid selinux labeling. +		 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ +		while (path[1] >= '0' && path[1] <= '9') { +			path[1] = '/'; +			path++; +		} +		rc = security_genfs_sid("proc", path, tclass, sid);  	} -	rc = security_genfs_sid("proc", path, tclass, sid);  	free_page((unsigned long)buffer);  	return rc;  }  #else -static int selinux_proc_get_sid(struct proc_dir_entry *de, +static int selinux_proc_get_sid(struct dentry *dentry,  				u16 tclass,  				u32 *sid)  { @@ -1300,10 +1298,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent  		/* Try to obtain a transition SID. */  		isec->sclass = inode_mode_to_security_class(inode->i_mode); -		rc = security_transition_sid(isec->task_sid, -					     sbsec->sid, -					     isec->sclass, -					     &sid); +		rc = security_transition_sid(isec->task_sid, sbsec->sid, +					     isec->sclass, NULL, &sid);  		if (rc)  			goto out_unlock;  		isec->sid = sid; @@ -1316,10 +1312,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent  		isec->sid = sbsec->sid;  		if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { -			struct proc_inode *proci = PROC_I(inode); -			if (proci->pde) { +			if (opt_dentry) {  				isec->sclass = inode_mode_to_security_class(inode->i_mode); -				rc = selinux_proc_get_sid(proci->pde, +				rc = selinux_proc_get_sid(opt_dentry,  							  isec->sclass,  							  &sid);  				if (rc) @@ -1578,7 +1573,7 @@ static int may_create(struct inode *dir,  		return rc;  	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { -		rc = security_transition_sid(sid, dsec->sid, tclass, &newsid); +		rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);  		if (rc)  			return rc;  	} @@ -1862,82 +1857,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred,  	return task_has_capability(tsk, cred, cap, audit);  } -static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) -{ -	int buflen, rc; -	char *buffer, *path, *end; - -	rc = -ENOMEM; -	buffer = (char *)__get_free_page(GFP_KERNEL); -	if (!buffer) -		goto out; - -	buflen = PAGE_SIZE; -	end = buffer+buflen; -	*--end = '\0'; -	buflen--; -	path = end-1; -	*path = '/'; -	while (table) { -		const char *name = table->procname; -		size_t namelen = strlen(name); -		buflen -= namelen + 1; -		if (buflen < 0) -			goto out_free; -		end -= namelen; -		memcpy(end, name, namelen); -		*--end = '/'; -		path = end; -		table = table->parent; -	} -	buflen -= 4; -	if (buflen < 0) -		goto out_free; -	end -= 4; -	memcpy(end, "/sys", 4); -	path = end; -	rc = security_genfs_sid("proc", path, tclass, sid); -out_free: -	free_page((unsigned long)buffer); -out: -	return rc; -} - -static int selinux_sysctl(ctl_table *table, int op) -{ -	int error = 0; -	u32 av; -	u32 tsid, sid; -	int rc; - -	sid = current_sid(); - -	rc = selinux_sysctl_get_sid(table, (op == 0001) ? -				    SECCLASS_DIR : SECCLASS_FILE, &tsid); -	if (rc) { -		/* Default to the well-defined sysctl SID. */ -		tsid = SECINITSID_SYSCTL; -	} - -	/* The op values are "defined" in sysctl.c, thereby creating -	 * a bad coupling between this module and sysctl.c */ -	if (op == 001) { -		error = avc_has_perm(sid, tsid, -				     SECCLASS_DIR, DIR__SEARCH, NULL); -	} else { -		av = 0; -		if (op & 004) -			av |= FILE__READ; -		if (op & 002) -			av |= FILE__WRITE; -		if (av) -			error = avc_has_perm(sid, tsid, -					     SECCLASS_FILE, av, NULL); -	} - -	return error; -} -  static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)  {  	const struct cred *cred = current_cred(); @@ -2060,7 +1979,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)  	} else {  		/* Check for a default transition on this program. */  		rc = security_transition_sid(old_tsec->sid, isec->sid, -					     SECCLASS_PROCESS, &new_tsec->sid); +					     SECCLASS_PROCESS, NULL, +					     &new_tsec->sid);  		if (rc)  			return rc;  	} @@ -2443,6 +2363,91 @@ out:  	return rc;  } +static int selinux_sb_remount(struct super_block *sb, void *data) +{ +	int rc, i, *flags; +	struct security_mnt_opts opts; +	char *secdata, **mount_options; +	struct superblock_security_struct *sbsec = sb->s_security; + +	if (!(sbsec->flags & SE_SBINITIALIZED)) +		return 0; + +	if (!data) +		return 0; + +	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) +		return 0; + +	security_init_mnt_opts(&opts); +	secdata = alloc_secdata(); +	if (!secdata) +		return -ENOMEM; +	rc = selinux_sb_copy_data(data, secdata); +	if (rc) +		goto out_free_secdata; + +	rc = selinux_parse_opts_str(secdata, &opts); +	if (rc) +		goto out_free_secdata; + +	mount_options = opts.mnt_opts; +	flags = opts.mnt_opts_flags; + +	for (i = 0; i < opts.num_mnt_opts; i++) { +		u32 sid; +		size_t len; + +		if (flags[i] == SE_SBLABELSUPP) +			continue; +		len = strlen(mount_options[i]); +		rc = security_context_to_sid(mount_options[i], len, &sid); +		if (rc) { +			printk(KERN_WARNING "SELinux: security_context_to_sid" +			       "(%s) failed for (dev %s, type %s) errno=%d\n", +			       mount_options[i], sb->s_id, sb->s_type->name, rc); +			goto out_free_opts; +		} +		rc = -EINVAL; +		switch (flags[i]) { +		case FSCONTEXT_MNT: +			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) +				goto out_bad_option; +			break; +		case CONTEXT_MNT: +			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) +				goto out_bad_option; +			break; +		case ROOTCONTEXT_MNT: { +			struct inode_security_struct *root_isec; +			root_isec = sb->s_root->d_inode->i_security; + +			if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) +				goto out_bad_option; +			break; +		} +		case DEFCONTEXT_MNT: +			if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) +				goto out_bad_option; +			break; +		default: +			goto out_free_opts; +		} +	} + +	rc = 0; +out_free_opts: +	security_free_mnt_opts(&opts); +out_free_secdata: +	free_secdata(secdata); +	return rc; +out_bad_option: +	printk(KERN_WARNING "SELinux: unable to change security options " +	       "during remount (dev %s, type=%s)\n", sb->s_id, +	       sb->s_type->name); +	goto out_free_opts; +} +  static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)  {  	const struct cred *cred = current_cred(); @@ -2509,8 +2514,8 @@ static void selinux_inode_free_security(struct inode *inode)  }  static int selinux_inode_init_security(struct inode *inode, struct inode *dir, -				       char **name, void **value, -				       size_t *len) +				       const struct qstr *qstr, char **name, +				       void **value, size_t *len)  {  	const struct task_security_struct *tsec = current_security();  	struct inode_security_struct *dsec; @@ -2531,7 +2536,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,  	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {  		rc = security_transition_sid(sid, dsec->sid,  					     inode_mode_to_security_class(inode->i_mode), -					     &newsid); +					     qstr, &newsid);  		if (rc) {  			printk(KERN_WARNING "%s:  "  			       "security_transition_sid failed, rc=%d (dev=%s " @@ -2932,16 +2937,47 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,  			      unsigned long arg)  {  	const struct cred *cred = current_cred(); -	u32 av = 0; +	int error = 0; -	if (_IOC_DIR(cmd) & _IOC_WRITE) -		av |= FILE__WRITE; -	if (_IOC_DIR(cmd) & _IOC_READ) -		av |= FILE__READ; -	if (!av) -		av = FILE__IOCTL; +	switch (cmd) { +	case FIONREAD: +	/* fall through */ +	case FIBMAP: +	/* fall through */ +	case FIGETBSZ: +	/* fall through */ +	case EXT2_IOC_GETFLAGS: +	/* fall through */ +	case EXT2_IOC_GETVERSION: +		error = file_has_perm(cred, file, FILE__GETATTR); +		break; + +	case EXT2_IOC_SETFLAGS: +	/* fall through */ +	case EXT2_IOC_SETVERSION: +		error = file_has_perm(cred, file, FILE__SETATTR); +		break; + +	/* sys_ioctl() checks */ +	case FIONBIO: +	/* fall through */ +	case FIOASYNC: +		error = file_has_perm(cred, file, 0); +		break; -	return file_has_perm(cred, file, av); +	case KDSKBENT: +	case KDSKBSENT: +		error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG, +					    SECURITY_CAP_AUDIT); +		break; + +	/* default case assumes that the command will go +	 * to the file's ioctl() function. +	 */ +	default: +		error = file_has_perm(cred, file, FILE__IOCTL); +	} +	return error;  }  static int default_noexec; @@ -3644,9 +3680,16 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)  /* socket security operations */ -static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) +static int socket_sockcreate_sid(const struct task_security_struct *tsec, +				 u16 secclass, u32 *socksid)  { -	return tsec->sockcreate_sid ? : tsec->sid; +	if (tsec->sockcreate_sid > SECSID_NULL) { +		*socksid = tsec->sockcreate_sid; +		return 0; +	} + +	return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL, +				       socksid);  }  static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) @@ -3670,12 +3713,16 @@ static int selinux_socket_create(int family, int type,  	const struct task_security_struct *tsec = current_security();  	u32 newsid;  	u16 secclass; +	int rc;  	if (kern)  		return 0; -	newsid = socket_sockcreate_sid(tsec);  	secclass = socket_type_to_security_class(family, type, protocol); +	rc = socket_sockcreate_sid(tsec, secclass, &newsid); +	if (rc) +		return rc; +  	return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);  } @@ -3687,12 +3734,16 @@ static int selinux_socket_post_create(struct socket *sock, int family,  	struct sk_security_struct *sksec;  	int err = 0; +	isec->sclass = socket_type_to_security_class(family, type, protocol); +  	if (kern)  		isec->sid = SECINITSID_KERNEL; -	else -		isec->sid = socket_sockcreate_sid(tsec); +	else { +		err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid)); +		if (err) +			return err; +	} -	isec->sclass = socket_type_to_security_class(family, type, protocol);  	isec->initialized = 1;  	if (sock->sk) { @@ -4002,7 +4053,6 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,  {  	int err = 0;  	struct sk_security_struct *sksec = sk->sk_security; -	u32 peer_sid;  	u32 sk_sid = sksec->sid;  	struct common_audit_data ad;  	char *addrp; @@ -4021,20 +4071,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,  			return err;  	} -	if (selinux_policycap_netpeer) { -		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); -		if (err) -			return err; -		err = avc_has_perm(sk_sid, peer_sid, -				   SECCLASS_PEER, PEER__RECV, &ad); -		if (err) -			selinux_netlbl_err(skb, err, 0); -	} else { -		err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); -		if (err) -			return err; -		err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); -	} +	err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad); +	if (err) +		return err; +	err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);  	return err;  } @@ -4529,9 +4569,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,  				 SECCLASS_PACKET, PACKET__SEND, &ad))  			return NF_DROP_ERR(-ECONNREFUSED); -	if (selinux_policycap_netpeer) -		if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) -			return NF_DROP_ERR(-ECONNREFUSED); +	if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) +		return NF_DROP_ERR(-ECONNREFUSED);  	return NF_ACCEPT;  } @@ -4574,27 +4613,14 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,  	 * from the sending socket, otherwise use the kernel's sid */  	sk = skb->sk;  	if (sk == NULL) { -		switch (family) { -		case PF_INET: -			if (IPCB(skb)->flags & IPSKB_FORWARDED) -				secmark_perm = PACKET__FORWARD_OUT; -			else -				secmark_perm = PACKET__SEND; -			break; -		case PF_INET6: -			if (IP6CB(skb)->flags & IP6SKB_FORWARDED) -				secmark_perm = PACKET__FORWARD_OUT; -			else -				secmark_perm = PACKET__SEND; -			break; -		default: -			return NF_DROP_ERR(-ECONNREFUSED); -		} -		if (secmark_perm == PACKET__FORWARD_OUT) { +		if (skb->skb_iif) { +			secmark_perm = PACKET__FORWARD_OUT;  			if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))  				return NF_DROP; -		} else +		} else { +			secmark_perm = PACKET__SEND;  			peer_sid = SECINITSID_KERNEL; +		}  	} else {  		struct sk_security_struct *sksec = sk->sk_security;  		peer_sid = sksec->sid; @@ -4848,7 +4874,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,  		 * message queue this message will be stored in  		 */  		rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG, -					     &msec->sid); +					     NULL, &msec->sid);  		if (rc)  			return rc;  	} @@ -5402,7 +5428,6 @@ static struct security_operations selinux_ops = {  	.ptrace_traceme =		selinux_ptrace_traceme,  	.capget =			selinux_capget,  	.capset =			selinux_capset, -	.sysctl =			selinux_sysctl,  	.capable =			selinux_capable,  	.quotactl =			selinux_quotactl,  	.quota_on =			selinux_quota_on, @@ -5420,6 +5445,7 @@ static struct security_operations selinux_ops = {  	.sb_alloc_security =		selinux_sb_alloc_security,  	.sb_free_security =		selinux_sb_free_security,  	.sb_copy_data =			selinux_sb_copy_data, +	.sb_remount =			selinux_sb_remount,  	.sb_kern_mount =		selinux_sb_kern_mount,  	.sb_show_options =		selinux_sb_show_options,  	.sb_statfs =			selinux_sb_statfs, diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 7ed3663332e..b8c53723e09 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -12,6 +12,10 @@  #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \  	    "write", "associate", "unix_read", "unix_write" +/* + * Note: The name for any socket class should be suffixed by "socket", + *	 and doesn't contain more than one substr of "socket". + */  struct security_class_mapping secclass_map[] = {  	{ "security",  	  { "compute_av", "compute_create", "compute_member", @@ -132,8 +136,7 @@ struct security_class_mapping secclass_map[] = {  	{ "appletalk_socket",  	  { COMMON_SOCK_PERMS, NULL } },  	{ "packet", -	  { "send", "recv", "relabelto", "flow_in", "flow_out", -	    "forward_in", "forward_out", NULL } }, +	  { "send", "recv", "relabelto", "forward_in", "forward_out", NULL } },  	{ "key",  	  { "view", "read", "write", "search", "link", "setattr", "create",  	    NULL } }, diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 671273eb111..348eb00cb66 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -8,6 +8,7 @@  #ifndef _SELINUX_SECURITY_H_  #define _SELINUX_SECURITY_H_ +#include <linux/dcache.h>  #include <linux/magic.h>  #include <linux/types.h>  #include "flask.h" @@ -28,13 +29,14 @@  #define POLICYDB_VERSION_POLCAP		22  #define POLICYDB_VERSION_PERMISSIVE	23  #define POLICYDB_VERSION_BOUNDARY	24 +#define POLICYDB_VERSION_FILENAME_TRANS	25  /* Range of policy versions we understand*/  #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE  #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX  #define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE  #else -#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_BOUNDARY +#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_FILENAME_TRANS  #endif  /* Mask for just the mount related flags */ @@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid,  void security_compute_av_user(u32 ssid, u32 tsid,  			     u16 tclass, struct av_decision *avd); -int security_transition_sid(u32 ssid, u32 tsid, -			    u16 tclass, u32 *out_sid); +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, +			    const struct qstr *qstr, u32 *out_sid);  int security_transition_sid_user(u32 ssid, u32 tsid,  				 u16 tclass, u32 *out_sid); diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 3417f9cc1cb..63ce2f9e441 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -14,7 +14,7 @@   *   * Copyright (C) 2003 Tresys Technology, LLC   *	This program is free software; you can redistribute it and/or modify - *  	it under the terms of the GNU General Public License as published by + *	it under the terms of the GNU General Public License as published by   *	the Free Software Foundation, version 2.   *   * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp> @@ -27,16 +27,16 @@ struct avtab_key {  	u16 source_type;	/* source type */  	u16 target_type;	/* target type */  	u16 target_class;	/* target object class */ -#define AVTAB_ALLOWED     1 -#define AVTAB_AUDITALLOW  2 -#define AVTAB_AUDITDENY   4 -#define AVTAB_AV         (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) -#define AVTAB_TRANSITION 16 -#define AVTAB_MEMBER     32 -#define AVTAB_CHANGE     64 -#define AVTAB_TYPE       (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) -#define AVTAB_ENABLED_OLD    0x80000000 /* reserved for used in cond_avtab */ -#define AVTAB_ENABLED    0x8000 /* reserved for used in cond_avtab */ +#define AVTAB_ALLOWED		0x0001 +#define AVTAB_AUDITALLOW	0x0002 +#define AVTAB_AUDITDENY		0x0004 +#define AVTAB_AV		(AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) +#define AVTAB_TRANSITION	0x0010 +#define AVTAB_MEMBER		0x0020 +#define AVTAB_CHANGE		0x0040 +#define AVTAB_TYPE		(AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) +#define AVTAB_ENABLED_OLD   0x80000000 /* reserved for used in cond_avtab */ +#define AVTAB_ENABLED		0x8000 /* reserved for used in cond_avtab */  	u16 specified;	/* what field is specified */  }; diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 1ef8e4e8988..e96174216bc 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext,  		    struct context *tcontext,  		    u16 tclass,  		    u32 specified, -		    struct context *newcontext) +		    struct context *newcontext, +		    bool sock)  {  	struct range_trans rtr;  	struct mls_range *r; @@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext,  			return mls_range_set(newcontext, r);  		/* Fallthrough */  	case AVTAB_CHANGE: -		if (tclass == policydb.process_class) +		if ((tclass == policydb.process_class) || (sock == true))  			/* Use the process MLS attributes. */  			return mls_context_cpy(newcontext, scontext);  		else diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index cd9152632e5..037bf9d82d4 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext,  		    struct context *tcontext,  		    u16 tclass,  		    u32 specified, -		    struct context *newcontext); +		    struct context *newcontext, +		    bool sock);  int mls_setup_user_range(struct context *fromcon, struct user_datum *user,  			 struct context *usercon); diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 57363562f0f..e7b850ad57e 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = {  		.sym_num	= SYM_NUM,  		.ocon_num	= OCON_NUM,  	}, +	{ +		.version	= POLICYDB_VERSION_FILENAME_TRANS, +		.sym_num	= SYM_NUM, +		.ocon_num	= OCON_NUM, +	},  };  static struct policydb_compat_info *policydb_lookup_compat(int version) @@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p)  	int i;  	struct role_allow *ra, *lra = NULL;  	struct role_trans *tr, *ltr = NULL; +	struct filename_trans *ft, *nft;  	for (i = 0; i < SYM_NUM; i++) {  		cond_resched(); @@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p)  		}  		flex_array_free(p->type_attr_map_array);  	} + +	ft = p->filename_trans; +	while (ft) { +		nft = ft->next; +		kfree(ft->name); +		kfree(ft); +		ft = nft; +	} +  	ebitmap_destroy(&p->policycaps);  	ebitmap_destroy(&p->permissive_map); @@ -1788,6 +1803,76 @@ out:  	return rc;  } +static int filename_trans_read(struct policydb *p, void *fp) +{ +	struct filename_trans *ft, *last; +	u32 nel, len; +	char *name; +	__le32 buf[4]; +	int rc, i; + +	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) +		return 0; + +	rc = next_entry(buf, fp, sizeof(u32)); +	if (rc) +		goto out; +	nel = le32_to_cpu(buf[0]); + +	printk(KERN_ERR "%s: nel=%d\n", __func__, nel); + +	last = p->filename_trans; +	while (last && last->next) +		last = last->next; + +	for (i = 0; i < nel; i++) { +		rc = -ENOMEM; +		ft = kzalloc(sizeof(*ft), GFP_KERNEL); +		if (!ft) +			goto out; + +		/* add it to the tail of the list */ +		if (!last) +			p->filename_trans = ft; +		else +			last->next = ft; +		last = ft; + +		/* length of the path component string */ +		rc = next_entry(buf, fp, sizeof(u32)); +		if (rc) +			goto out; +		len = le32_to_cpu(buf[0]); + +		rc = -ENOMEM; +		name = kmalloc(len + 1, GFP_KERNEL); +		if (!name) +			goto out; + +		ft->name = name; + +		/* path component string */ +		rc = next_entry(name, fp, len); +		if (rc) +			goto out; +		name[len] = 0; + +		printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name); + +		rc = next_entry(buf, fp, sizeof(u32) * 4); +		if (rc) +			goto out; + +		ft->stype = le32_to_cpu(buf[0]); +		ft->ttype = le32_to_cpu(buf[1]); +		ft->tclass = le32_to_cpu(buf[2]); +		ft->otype = le32_to_cpu(buf[3]); +	} +	rc = 0; +out: +	return rc; +} +  static int genfs_read(struct policydb *p, void *fp)  {  	int i, j, rc; @@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp)  		lra = ra;  	} +	rc = filename_trans_read(p, fp); +	if (rc) +		goto bad; +  	rc = policydb_index(p);  	if (rc)  		goto bad; @@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp)  	return 0;  } +static int filename_trans_write(struct policydb *p, void *fp) +{ +	struct filename_trans *ft; +	u32 len, nel = 0; +	__le32 buf[4]; +	int rc; + +	for (ft = p->filename_trans; ft; ft = ft->next) +		nel++; + +	buf[0] = cpu_to_le32(nel); +	rc = put_entry(buf, sizeof(u32), 1, fp); +	if (rc) +		return rc; + +	for (ft = p->filename_trans; ft; ft = ft->next) { +		len = strlen(ft->name); +		buf[0] = cpu_to_le32(len); +		rc = put_entry(buf, sizeof(u32), 1, fp); +		if (rc) +			return rc; + +		rc = put_entry(ft->name, sizeof(char), len, fp); +		if (rc) +			return rc; + +		buf[0] = ft->stype; +		buf[1] = ft->ttype; +		buf[2] = ft->tclass; +		buf[3] = ft->otype; + +		rc = put_entry(buf, sizeof(u32), 4, fp); +		if (rc) +			return rc; +	} +	return 0; +}  /*   * Write the configuration data in a policy database   * structure to a policy database binary representation @@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp)  	if (rc)  		return rc; +	rc = filename_trans_write(p, fp); +	if (rc) +		return rc; +  	rc = ocontext_write(p, info, fp);  	if (rc)  		return rc; diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 4e3ab9d0b31..732ea4a6868 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -77,6 +77,15 @@ struct role_trans {  	struct role_trans *next;  }; +struct filename_trans { +	struct filename_trans *next; +	u32 stype;		/* current process */ +	u32 ttype;		/* parent dir context */ +	u16 tclass;		/* class of new object */ +	const char *name;	/* last path component */ +	u32 otype;		/* expected of new object */ +}; +  struct role_allow {  	u32 role;		/* current role */  	u32 new_role;		/* new role */ @@ -217,6 +226,9 @@ struct policydb {  	/* role transitions */  	struct role_trans *role_tr; +	/* file transitions with the last path component */ +	struct filename_trans *filename_trans; +  	/* bools indexed by (value - 1) */  	struct cond_bool_datum **bool_val_to_struct;  	/* type enforcement conditional access vectors and transitions */ @@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)  	return 0;  } -static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp) +static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp)  {  	size_t len = bytes * num; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a03cfaf0ee0..3e7544d2a07 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)  	return tclass;  } +/* + * Get kernel value for class from its policy value + */ +static u16 map_class(u16 pol_value) +{ +	u16 i; + +	for (i = 1; i < current_mapping_size; i++) { +		if (current_mapping[i].value == pol_value) +			return i; +	} + +	return pol_value; +} +  static void map_decision(u16 tclass, struct av_decision *avd,  			 int allow_unknown)  { @@ -1343,10 +1358,27 @@ out:  	return -EACCES;  } +static void filename_compute_type(struct policydb *p, struct context *newcontext, +				  u32 scon, u32 tcon, u16 tclass, +				  const struct qstr *qstr) +{ +	struct filename_trans *ft; +	for (ft = p->filename_trans; ft; ft = ft->next) { +		if (ft->stype == scon && +		    ft->ttype == tcon && +		    ft->tclass == tclass && +		    !strcmp(ft->name, qstr->name)) { +			newcontext->type = ft->otype; +			return; +		} +	} +} +  static int security_compute_sid(u32 ssid,  				u32 tsid,  				u16 orig_tclass,  				u32 specified, +				const struct qstr *qstr,  				u32 *out_sid,  				bool kern)  { @@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid,  	struct avtab_node *node;  	u16 tclass;  	int rc = 0; +	bool sock;  	if (!ss_initialized) {  		switch (orig_tclass) { @@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid,  	read_lock(&policy_rwlock); -	if (kern) +	if (kern) {  		tclass = unmap_class(orig_tclass); -	else +		sock = security_is_socket_class(orig_tclass); +	} else {  		tclass = orig_tclass; +		sock = security_is_socket_class(map_class(tclass)); +	}  	scontext = sidtab_search(&sidtab, ssid);  	if (!scontext) { @@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid,  	}  	/* Set the role and type to default values. */ -	if (tclass == policydb.process_class) { +	if ((tclass == policydb.process_class) || (sock == true)) {  		/* Use the current role and type of process. */  		newcontext.role = scontext->role;  		newcontext.type = scontext->type; @@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid,  		newcontext.type = avdatum->data;  	} +	/* if we have a qstr this is a file trans check so check those rules */ +	if (qstr) +		filename_compute_type(&policydb, &newcontext, scontext->type, +				      tcontext->type, tclass, qstr); +  	/* Check for class-specific changes. */  	if  (tclass == policydb.process_class) {  		if (specified & AVTAB_TRANSITION) { @@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid,  	/* Set the MLS attributes.  	   This is done last because it may allocate memory. */ -	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); +	rc = mls_compute_sid(scontext, tcontext, tclass, specified, +			     &newcontext, sock);  	if (rc)  		goto out_unlock; @@ -1495,22 +1537,17 @@ out:   * if insufficient memory is available, or %0 if the new SID was   * computed successfully.   */ -int security_transition_sid(u32 ssid, -			    u32 tsid, -			    u16 tclass, -			    u32 *out_sid) +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, +			    const struct qstr *qstr, u32 *out_sid)  {  	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, -				    out_sid, true); +				    qstr, out_sid, true);  } -int security_transition_sid_user(u32 ssid, -				 u32 tsid, -				 u16 tclass, -				 u32 *out_sid) +int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)  {  	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, -				    out_sid, false); +				    NULL, out_sid, false);  }  /** @@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, -				    false); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL, +				    out_sid, false);  }  /** @@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, -				    false); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, +				    out_sid, false);  }  /* Clone the SID into the new SID table. */ diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index fff78d3b51a..728c57e3d65 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -208,7 +208,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,  	if (!uctx)  		goto not_from_user; -	if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) +	if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)  		return -EINVAL;  	str_len = uctx->ctx_len; diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5ab3f39442f..23c7a6d0c80 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -33,6 +33,7 @@  #include <net/cipso_ipv4.h>  #include <linux/audit.h>  #include <linux/magic.h> +#include <linux/dcache.h>  #include "smack.h"  #define task_security(task)	(task_cred_xxx((task), security)) @@ -501,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode)   * smack_inode_init_security - copy out the smack from an inode   * @inode: the inode   * @dir: unused + * @qstr: unused   * @name: where to put the attribute name   * @value: where to put the attribute value   * @len: where to put the length of the attribute @@ -508,7 +510,8 @@ static void smack_inode_free_security(struct inode *inode)   * Returns 0 if it all works out, -ENOMEM if there's no memory   */  static int smack_inode_init_security(struct inode *inode, struct inode *dir, -				     char **name, void **value, size_t *len) +				     const struct qstr *qstr, char **name, +				     void **value, size_t *len)  {  	char *isp = smk_of_inode(inode);  	char *dsp = smk_of_inode(dir);  |