mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	switch dentry_open() to struct path, make it grab references itself
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									bf349a4470
								
							
						
					
					
						commit
						765927b2d5
					
				
					 15 changed files with 106 additions and 151 deletions
				
			
		|  | @ -317,7 +317,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, | |||
| 	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 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 	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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										17
									
								
								fs/open.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
							
								
								
									
										117
									
								
								ipc/mqueue.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -1297,7 +1297,7 @@ static int sel_make_bools(void) | |||
| 
 | ||||
| #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); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro