diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-06-26 21:58:53 +0400 | 
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-23 00:01:29 +0400 | 
| commit | 765927b2d508712d320c8934db963bbe14c3fcec (patch) | |
| tree | 97acdb14fae285764def396c4ed01d4d5c93e76a | |
| parent | bf349a447059656ebe63fb4fd1ccb27ac1da22ad (diff) | |
| download | olio-linux-3.10-765927b2d508712d320c8934db963bbe14c3fcec.tar.xz olio-linux-3.10-765927b2d508712d320c8934db963bbe14c3fcec.zip  | |
switch dentry_open() to struct path, make it grab references itself
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 18 | ||||
| -rw-r--r-- | fs/autofs4/dev-ioctl.c | 4 | ||||
| -rw-r--r-- | fs/cachefiles/rdwr.c | 8 | ||||
| -rw-r--r-- | fs/ecryptfs/kthread.c | 21 | ||||
| -rw-r--r-- | fs/exportfs/expfs.c | 13 | ||||
| -rw-r--r-- | fs/hppfs/hppfs.c | 20 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 10 | ||||
| -rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 8 | ||||
| -rw-r--r-- | fs/open.c | 17 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 7 | ||||
| -rw-r--r-- | include/linux/fs.h | 3 | ||||
| -rw-r--r-- | ipc/mqueue.c | 117 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 3 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 2 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 6 | 
15 files changed, 106 insertions, 151 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1c9cac0cf89..d544d7816df 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -317,7 +317,7 @@ out:  	return ret;  } -static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) +static int spufs_context_open(struct path *path)  {  	int ret;  	struct file *filp; @@ -326,11 +326,7 @@ static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)  	if (ret < 0)  		return ret; -	/* -	 * get references for dget and mntget, will be released -	 * in error path of *_open(). -	 */ -	filp = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, current_cred()); +	filp = dentry_open(path, O_RDONLY, current_cred());  	if (IS_ERR(filp)) {  		put_unused_fd(ret);  		return PTR_ERR(filp); @@ -452,6 +448,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,  	int affinity;  	struct spu_gang *gang;  	struct spu_context *neighbor; +	struct path path = {.mnt = mnt, .dentry = dentry};  	ret = -EPERM;  	if ((flags & SPU_CREATE_NOSCHED) && @@ -494,7 +491,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,  			put_spu_context(neighbor);  	} -	ret = spufs_context_open(dentry, mnt); +	ret = spufs_context_open(&path);  	if (ret < 0) {  		WARN_ON(spufs_rmdir(inode, dentry));  		if (affinity) @@ -551,7 +548,7 @@ out:  	return ret;  } -static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) +static int spufs_gang_open(struct path *path)  {  	int ret;  	struct file *filp; @@ -564,7 +561,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)  	 * get references for dget and mntget, will be released  	 * in error path of *_open().  	 */ -	filp = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, current_cred()); +	filp = dentry_open(path, O_RDONLY, current_cred());  	if (IS_ERR(filp)) {  		put_unused_fd(ret);  		return PTR_ERR(filp); @@ -579,13 +576,14 @@ static int spufs_create_gang(struct inode *inode,  			struct dentry *dentry,  			struct vfsmount *mnt, umode_t mode)  { +	struct path path = {.mnt = mnt, .dentry = dentry};  	int ret;  	ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);  	if (ret)  		goto out; -	ret = spufs_gang_open(dentry, mnt); +	ret = spufs_gang_open(&path);  	if (ret < 0) {  		int err = simple_rmdir(inode, dentry);  		WARN_ON(err); diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index aa9103f8f01..abf645c1703 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c @@ -257,8 +257,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)  		 * corresponding to the autofs fs we want to open.  		 */ -		filp = dentry_open(path.dentry, path.mnt, O_RDONLY, -				   current_cred()); +		filp = dentry_open(&path, O_RDONLY, current_cred()); +		path_put(&path);  		if (IS_ERR(filp)) {  			err = PTR_ERR(filp);  			goto out; diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0e3c0924cc3..c0353dfac51 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -891,6 +891,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)  	struct cachefiles_cache *cache;  	mm_segment_t old_fs;  	struct file *file; +	struct path path;  	loff_t pos, eof;  	size_t len;  	void *data; @@ -916,10 +917,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)  	/* write the page to the backing filesystem and let it store it in its  	 * own time */ -	dget(object->backer); -	mntget(cache->mnt); -	file = dentry_open(object->backer, cache->mnt, O_RDWR, -			   cache->cache_cred); +	path.mnt = cache->mnt; +	path.dentry = object->backer; +	file = dentry_open(&path, O_RDWR, cache->cache_cred);  	if (IS_ERR(file)) {  		ret = PTR_ERR(file);  	} else { diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index c7d199dc7d2..809e67d05ca 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c @@ -29,8 +29,7 @@  struct ecryptfs_open_req {  	struct file **lower_file; -	struct dentry *lower_dentry; -	struct vfsmount *lower_mnt; +	struct path path;  	struct completion done;  	struct list_head kthread_ctl_list;  }; @@ -74,10 +73,7 @@ static int ecryptfs_threadfn(void *ignored)  					       struct ecryptfs_open_req,  					       kthread_ctl_list);  			list_del(&req->kthread_ctl_list); -			dget(req->lower_dentry); -			mntget(req->lower_mnt); -			(*req->lower_file) = dentry_open( -				req->lower_dentry, req->lower_mnt, +			*req->lower_file = dentry_open(&req->path,  				(O_RDWR | O_LARGEFILE), current_cred());  			complete(&req->done);  		} @@ -140,23 +136,22 @@ int ecryptfs_privileged_open(struct file **lower_file,  	int flags = O_LARGEFILE;  	int rc = 0; +	init_completion(&req.done); +	req.lower_file = lower_file; +	req.path.dentry = lower_dentry; +	req.path.mnt = lower_mnt; +  	/* Corresponding dput() and mntput() are done when the  	 * lower file is fput() when all eCryptfs files for the inode are  	 * released. */ -	dget(lower_dentry); -	mntget(lower_mnt);  	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; -	(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); +	(*lower_file) = dentry_open(&req.path, flags, cred);  	if (!IS_ERR(*lower_file))  		goto out;  	if ((flags & O_ACCMODE) == O_RDONLY) {  		rc = PTR_ERR((*lower_file));  		goto out;  	} -	init_completion(&req.done); -	req.lower_file = lower_file; -	req.lower_dentry = lower_dentry; -	req.lower_mnt = lower_mnt;  	mutex_lock(&ecryptfs_kthread_ctl.mux);  	if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {  		rc = -EIO; diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b42063cf1b2..29ab099e3e0 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -19,19 +19,19 @@  #define dprintk(fmt, args...) do{}while(0) -static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, -		struct dentry *child); +static int get_name(const struct path *path, char *name, struct dentry *child);  static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,  		char *name, struct dentry *child)  {  	const struct export_operations *nop = dir->d_sb->s_export_op; +	struct path path = {.mnt = mnt, .dentry = dir};  	if (nop->get_name)  		return nop->get_name(dir, name, child);  	else -		return get_name(mnt, dir, name, child); +		return get_name(&path, name, child);  }  /* @@ -249,11 +249,10 @@ static int filldir_one(void * __buf, const char * name, int len,   * calls readdir on the parent until it finds an entry with   * the same inode number as the child, and returns that.   */ -static int get_name(struct vfsmount *mnt, struct dentry *dentry, -		char *name, struct dentry *child) +static int get_name(const struct path *path, char *name, struct dentry *child)  {  	const struct cred *cred = current_cred(); -	struct inode *dir = dentry->d_inode; +	struct inode *dir = path->dentry->d_inode;  	int error;  	struct file *file;  	struct getdents_callback buffer; @@ -267,7 +266,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,  	/*  	 * Open the directory ...  	 */ -	file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred); +	file = dentry_open(path, O_RDONLY, cred);  	error = PTR_ERR(file);  	if (IS_ERR(file))  		goto out; diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index e5c06531dcc..c1dffe47fde 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c @@ -420,8 +420,7 @@ static int hppfs_open(struct inode *inode, struct file *file)  {  	const struct cred *cred = file->f_cred;  	struct hppfs_private *data; -	struct vfsmount *proc_mnt; -	struct dentry *proc_dentry; +	struct path path;  	char *host_file;  	int err, fd, type, filter; @@ -434,12 +433,11 @@ static int hppfs_open(struct inode *inode, struct file *file)  	if (host_file == NULL)  		goto out_free2; -	proc_dentry = HPPFS_I(inode)->proc_dentry; -	proc_mnt = inode->i_sb->s_fs_info; +	path.mnt = inode->i_sb->s_fs_info; +	path.dentry = HPPFS_I(inode)->proc_dentry;  	/* XXX This isn't closed anywhere */ -	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), -				      file_mode(file->f_mode), cred); +	data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);  	err = PTR_ERR(data->proc_file);  	if (IS_ERR(data->proc_file))  		goto out_free1; @@ -484,8 +482,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)  {  	const struct cred *cred = file->f_cred;  	struct hppfs_private *data; -	struct vfsmount *proc_mnt; -	struct dentry *proc_dentry; +	struct path path;  	int err;  	err = -ENOMEM; @@ -493,10 +490,9 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)  	if (data == NULL)  		goto out; -	proc_dentry = HPPFS_I(inode)->proc_dentry; -	proc_mnt = inode->i_sb->s_fs_info; -	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), -				      file_mode(file->f_mode), cred); +	path.mnt = inode->i_sb->s_fs_info; +	path.dentry = HPPFS_I(inode)->proc_dentry; +	data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);  	err = PTR_ERR(data->proc_file);  	if (IS_ERR(data->proc_file))  		goto out_free; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 05d9eee6be3..4700a0a929d 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -745,7 +745,7 @@ __be32  nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,  			int may_flags, struct file **filp)  { -	struct dentry	*dentry; +	struct path	path;  	struct inode	*inode;  	int		flags = O_RDONLY|O_LARGEFILE;  	__be32		err; @@ -762,8 +762,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,  	if (err)  		goto out; -	dentry = fhp->fh_dentry; -	inode = dentry->d_inode; +	path.mnt = fhp->fh_export->ex_path.mnt; +	path.dentry = fhp->fh_dentry; +	inode = path.dentry->d_inode;  	/* Disallow write access to files with the append-only bit set  	 * or any access when mandatory locking enabled @@ -792,8 +793,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,  		else  			flags = O_WRONLY|O_LARGEFILE;  	} -	*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), -			    flags, current_cred()); +	*filp = dentry_open(&path, flags, current_cred());  	if (IS_ERR(*filp))  		host_err = PTR_ERR(*filp);  	else { diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3568c8a8b13..d4380366973 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -61,8 +61,6 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,  static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)  {  	int client_fd; -	struct dentry *dentry; -	struct vfsmount *mnt;  	struct file *new_file;  	pr_debug("%s: group=%p event=%p\n", __func__, group, event); @@ -81,12 +79,10 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)  	 * we need a new file handle for the userspace program so it can read even if it was  	 * originally opened O_WRONLY.  	 */ -	dentry = dget(event->path.dentry); -	mnt = mntget(event->path.mnt);  	/* it's possible this event was an overflow event.  in that case dentry and mnt  	 * are NULL;  That's fine, just don't call dentry open */ -	if (dentry && mnt) -		new_file = dentry_open(dentry, mnt, +	if (event->path.dentry && event->path.mnt) +		new_file = dentry_open(&event->path,  				       group->fanotify_data.f_flags | FMODE_NONOTIFY,  				       current_cred());  	else diff --git a/fs/open.c b/fs/open.c index 75bea868ef8..1e914b397e1 100644 --- a/fs/open.c +++ b/fs/open.c @@ -766,11 +766,7 @@ int finish_no_open(struct file *file, struct dentry *dentry)  }  EXPORT_SYMBOL(finish_no_open); -/* - * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an - * error. - */ -struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, +struct file *dentry_open(const struct path *path, int flags,  			 const struct cred *cred)  {  	int error; @@ -779,19 +775,16 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,  	validate_creds(cred);  	/* We must always pass in a valid mount pointer. */ -	BUG_ON(!mnt); +	BUG_ON(!path->mnt);  	error = -ENFILE;  	f = get_empty_filp(); -	if (f == NULL) { -		dput(dentry); -		mntput(mnt); +	if (f == NULL)  		return ERR_PTR(error); -	}  	f->f_flags = flags; -	f->f_path.mnt = mnt; -	f->f_path.dentry = dentry; +	f->f_path = *path; +	path_get(&f->f_path);  	error = do_dentry_open(f, NULL, cred);  	if (!error) {  		error = open_check_o_direct(f); diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 3a05a41b5d7..1f1535d25a9 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -208,6 +208,7 @@ xfs_open_by_handle(  	struct inode		*inode;  	struct dentry		*dentry;  	fmode_t			fmode; +	struct path		path;  	if (!capable(CAP_SYS_ADMIN))  		return -XFS_ERROR(EPERM); @@ -252,8 +253,10 @@ xfs_open_by_handle(  		goto out_dput;  	} -	filp = dentry_open(dentry, mntget(parfilp->f_path.mnt), -			   hreq->oflags, cred); +	path.mnt = parfilp->f_path.mnt; +	path.dentry = dentry; +	filp = dentry_open(&path, hreq->oflags, cred); +	dput(dentry);  	if (IS_ERR(filp)) {  		put_unused_fd(fd);  		return PTR_ERR(filp); diff --git a/include/linux/fs.h b/include/linux/fs.h index 34acf51273d..8fabb037a48 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2060,8 +2060,7 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags,  extern struct file *filp_open(const char *, int, umode_t);  extern struct file *file_open_root(struct dentry *, struct vfsmount *,  				   const char *, int); -extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, -				 const struct cred *); +extern struct file * dentry_open(const struct path *, int, const struct cred *);  extern int filp_close(struct file *, fl_owner_t id);  extern char * getname(const char __user *);  enum { diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 2dee38d53c7..f8e54f5b908 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)  /*   * Invoked when creating a new queue via sys_mq_open   */ -static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, -			struct dentry *dentry, int oflag, umode_t mode, +static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, +			struct path *path, int oflag, umode_t mode,  			struct mq_attr *attr)  {  	const struct cred *cred = current_cred(); @@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,  	if (attr) {  		ret = mq_attr_ok(ipc_ns, attr);  		if (ret) -			goto out; +			return ERR_PTR(ret);  		/* store for use during create */ -		dentry->d_fsdata = attr; +		path->dentry->d_fsdata = attr;  	} else {  		struct mq_attr def_attr; @@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,  					  ipc_ns->mq_msgsize_default);  		ret = mq_attr_ok(ipc_ns, &def_attr);  		if (ret) -			goto out; +			return ERR_PTR(ret);  	}  	mode &= ~current_umask(); -	ret = mnt_want_write(ipc_ns->mq_mnt); +	ret = mnt_want_write(path->mnt);  	if (ret) -		goto out; -	ret = vfs_create(dir->d_inode, dentry, mode, true); -	dentry->d_fsdata = NULL; -	if (ret) -		goto out_drop_write; - -	result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); +		return ERR_PTR(ret); +	ret = vfs_create(dir, path->dentry, mode, true); +	path->dentry->d_fsdata = NULL; +	if (!ret) +		result = dentry_open(path, oflag, cred); +	else +		result = ERR_PTR(ret);  	/*  	 * dentry_open() took a persistent mnt_want_write(),  	 * so we can now drop this one.  	 */ -	mnt_drop_write(ipc_ns->mq_mnt); +	mnt_drop_write(path->mnt);  	return result; - -out_drop_write: -	mnt_drop_write(ipc_ns->mq_mnt); -out: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); -	return ERR_PTR(ret);  }  /* Opens existing queue */ -static struct file *do_open(struct ipc_namespace *ipc_ns, -				struct dentry *dentry, int oflag) +static struct file *do_open(struct path *path, int oflag)  { -	int ret; -	const struct cred *cred = current_cred(); -  	static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,  						  MAY_READ | MAY_WRITE }; - -	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { -		ret = -EINVAL; -		goto err; -	} - -	if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { -		ret = -EACCES; -		goto err; -	} - -	return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); - -err: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); -	return ERR_PTR(ret); +	int acc; +	if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) +		return ERR_PTR(-EINVAL); +	acc = oflag2acc[oflag & O_ACCMODE]; +	if (inode_permission(path->dentry->d_inode, acc)) +		return ERR_PTR(-EACCES); +	return dentry_open(path, oflag, current_cred());  }  SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  		struct mq_attr __user *, u_attr)  { -	struct dentry *dentry; +	struct path path;  	struct file *filp;  	char *name;  	struct mq_attr attr;  	int fd, error;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; +	struct dentry *root = ipc_ns->mq_mnt->mnt_root;  	if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))  		return -EFAULT; @@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	if (fd < 0)  		goto out_putname; -	mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); -	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); -	if (IS_ERR(dentry)) { -		error = PTR_ERR(dentry); +	error = 0; +	mutex_lock(&root->d_inode->i_mutex); +	path.dentry = lookup_one_len(name, root, strlen(name)); +	if (IS_ERR(path.dentry)) { +		error = PTR_ERR(path.dentry);  		goto out_putfd;  	} -	mntget(ipc_ns->mq_mnt); +	path.mnt = mntget(ipc_ns->mq_mnt);  	if (oflag & O_CREAT) { -		if (dentry->d_inode) {	/* entry already exists */ -			audit_inode(name, dentry); +		if (path.dentry->d_inode) {	/* entry already exists */ +			audit_inode(name, path.dentry);  			if (oflag & O_EXCL) {  				error = -EEXIST;  				goto out;  			} -			filp = do_open(ipc_ns, dentry, oflag); +			filp = do_open(&path, oflag);  		} else { -			filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, -						dentry, oflag, mode, +			filp = do_create(ipc_ns, root->d_inode, +						&path, oflag, mode,  						u_attr ? &attr : NULL);  		}  	} else { -		if (!dentry->d_inode) { +		if (!path.dentry->d_inode) {  			error = -ENOENT;  			goto out;  		} -		audit_inode(name, dentry); -		filp = do_open(ipc_ns, dentry, oflag); +		audit_inode(name, path.dentry); +		filp = do_open(&path, oflag);  	} -	if (IS_ERR(filp)) { +	if (!IS_ERR(filp)) +		fd_install(fd, filp); +	else  		error = PTR_ERR(filp); -		goto out_putfd; -	} - -	fd_install(fd, filp); -	goto out_upsem; -  out: -	dput(dentry); -	mntput(ipc_ns->mq_mnt); +	path_put(&path);  out_putfd: -	put_unused_fd(fd); -	fd = error; -out_upsem: -	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); +	if (error) { +		put_unused_fd(fd); +		fd = error; +	} +	mutex_unlock(&root->d_inode->i_mutex);  out_putname:  	putname(name);  	return fd; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 372ec6502aa..e423f5fe67f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,  						get_file(devnull);  					} else {  						devnull = dentry_open( -							dget(selinux_null), -							mntget(selinuxfs_mount), +							&selinux_null,  							O_RDWR, cred);  						if (IS_ERR(devnull)) {  							devnull = NULL; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index dde2005407a..6d3885165d1 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno);  extern void selinux_complete_init(void);  extern int selinux_disable(void);  extern void exit_sel_fs(void); -extern struct dentry *selinux_null; +extern struct path selinux_null;  extern struct vfsmount *selinuxfs_mount;  extern void selnl_notify_setenforce(int val);  extern void selnl_notify_policyload(u32 seqno); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 3ad29025128..298e695d682 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1297,7 +1297,7 @@ out:  #define NULL_FILE_NAME "null" -struct dentry *selinux_null; +struct path selinux_null;  static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,  					    size_t count, loff_t *ppos) @@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)  	init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));  	d_add(dentry, inode); -	selinux_null = dentry; +	selinux_null.dentry = dentry;  	dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino);  	if (IS_ERR(dentry)) { @@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void)  		return err;  	} -	selinuxfs_mount = kern_mount(&sel_fs_type); +	selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);  	if (IS_ERR(selinuxfs_mount)) {  		printk(KERN_ERR "selinuxfs:  could not mount!\n");  		err = PTR_ERR(selinuxfs_mount);  |