Beispiel #1
0
static int recv_fds(int minor, struct ancillary *data,
					struct msg_control *msg_ctrl)
{
	int rc, i, j;
	struct msghdr msghdr;
	struct cmsghdr *cmsg;
	endpoint_t to_ep;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
							++call_count);
#endif

	msghdr.msg_control = msg_ctrl->msg_control;
	msghdr.msg_controllen = msg_ctrl->msg_controllen;

	cmsg = CMSG_FIRSTHDR(&msghdr);
	cmsg->cmsg_len = CMSG_LEN(sizeof(int) * data->nfiledes);
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;

	to_ep = uds_fd_table[minor].owner;

	/* copy to the target endpoint */
	for (i = 0; i < data->nfiledes; i++) {
		rc = copy_filp(to_ep, data->filps[i]);
		if (rc < 0) {
			/* revert set_filp() calls */
			for (j = 0; j < data->nfiledes; j++) {
				put_filp(data->filps[j]);
			}
			/* revert copy_filp() calls */
			for (j = i; j >= 0; j--) {
				cancel_fd(to_ep, data->fds[j]);
			}
			return rc;
		}
		data->fds[i] = rc; /* data->fds[i] now has the new FD */
	}

	for (i = 0; i < data->nfiledes; i++) {
		put_filp(data->filps[i]);
#if DEBUG == 1
		printf("(uds) recv_fds() => %d\n", data->fds[i]);
#endif
		((int *)CMSG_DATA(cmsg))[i] = data->fds[i];
		data->fds[i] = -1;
		data->filps[i] = NULL;
	}

	data->nfiledes = 0;

	return OK;
}
Beispiel #2
0
static int send_fds(int minor, struct ancillary *data)
{
	int rc, i, j;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] send_fds() call_count=%d\n", minor, ++call_count);
#endif

	/* verify the file descriptors and get their filps. */
	for (i = 0; i < data->nfiledes; i++) {
		data->filps[i] = verify_fd(uds_fd_table[minor].owner,
						data->fds[i]);

		if (data->filps[i] == NULL) {
			return EINVAL;
		}
	}

	/* set them as in-flight */
	for (i = 0; i < data->nfiledes; i++) {
		rc = set_filp(data->filps[i]);
		if (rc != OK) {
			/* revert set_filp() calls */
			for (j = i; j >= 0; j--) {
				put_filp(data->filps[j]);
			}
			return rc;
		}
	}

	return OK;
}
struct file *dentry_open(const struct path *path, int flags,
			 const struct cred *cred)
{
	int error;
	struct file *f;

	validate_creds(cred);

	
	BUG_ON(!path->mnt);

	f = get_empty_filp();
	if (!IS_ERR(f)) {
		f->f_flags = flags;
		f->f_path = *path;
		error = do_dentry_open(f, NULL, cred);
		if (!error) {
			
			error = open_check_o_direct(f);
			if (error) {
				fput(f);
				f = ERR_PTR(error);
			}
		} else { 
			put_filp(f);
			f = ERR_PTR(error);
		}
	}
	return f;
}
static struct file *vperfctr_get_filp(void)
{
	struct file *filp;
	struct inode *inode;
	struct dentry *dentry;

	filp = get_empty_filp();
	if (!filp)
		goto out;
	inode = vperfctr_get_inode();
	if (!inode)
		goto out_filp;
	dentry = vperfctr_d_alloc_root(inode);
	if (!dentry)
		goto out_inode;

	filp->f_vfsmnt = mntget(vperfctr_mnt);
	filp->f_dentry = dentry;
	filp->f_mapping = dentry->d_inode->i_mapping;

	filp->f_pos = 0;
	filp->f_flags = 0;
	filp->f_op = &vperfctr_file_ops; /* fops_get() if MODULE */
	filp->f_mode = FMODE_READ;
	filp->f_version = 0;

	return filp;

 out_inode:
	iput(inode);
 out_filp:
	put_filp(filp);	/* doesn't run ->release() like fput() does */
 out:
	return NULL;
}
Beispiel #5
0
struct file *dentry_open(const struct path *path, int flags,
			 const struct cred *cred)
{
	int error;
	struct file *f;

	validate_creds(cred);

	/* We must always pass in a valid mount pointer. */
	BUG_ON(!path->mnt);

	f = get_empty_filp();
	if (!IS_ERR(f)) {
		f->f_flags = flags;
		f->f_path = *path;
		error = do_dentry_open(f, NULL, cred);
		if (!error) {
			/* from now on we need fput() to dispose of f */
			error = open_check_o_direct(f);
			if (error) {
				fput(f);
				f = ERR_PTR(error);
			}
		} else { 
			put_filp(f);
			f = ERR_PTR(error);
		}
	}
	return f;
}
Beispiel #6
0
struct file *dentry_open(const struct path *path, int flags,
			 const struct cred *cred)
{
	int error;
	struct file *f;

	validate_creds(cred);

	/* We must always pass in a valid mount pointer. */
	BUG_ON(!path->mnt);

	error = -ENFILE;
	f = get_empty_filp();
	if (f == NULL)
		return ERR_PTR(error);

	f->f_flags = flags;
	error = vfs_open(path, f, cred);
	if (!error) {
		error = open_check_o_direct(f);
		if (error) {
			fput(f);
			f = ERR_PTR(error);
		}
	} else { 
		put_filp(f);
		f = ERR_PTR(error);
	}
	return f;
}
Beispiel #7
0
int clear_fds(int minor, struct ancillary *data)
{
/* This function calls put_filp() for all of the FDs in data.
 * This is used when a Unix Domain Socket is closed and there
 * exists references to file descriptors that haven't been received
 * with recvmsg().
 */
	int i;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
							++call_count);
#endif

	for (i = 0; i < data->nfiledes; i++) {
		put_filp(data->filps[i]);
#if DEBUG == 1
		printf("(uds) clear_fds() => %d\n", data->fds[i]);
#endif
		data->fds[i] = -1;
		data->filps[i] = NULL;
	}

	data->nfiledes = 0;

	return OK;
}
Beispiel #8
0
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
	struct file * f;
	struct inode *inode;
	int error;

	error = -ENFILE;
	f = get_empty_filp();
	if (!f)
		goto cleanup_dentry;
	f->f_flags = flags;
	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_mapping = inode->i_mapping;
	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	if (f->f_op && f->f_op->open) {
		error = f->f_op->open(inode,f);
		if (error)
			goto cleanup_all;
	}
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	file_kill(f);
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
cleanup_dentry:
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #9
0
/*
 * shmem_file_setup - get an unlinked file living in tmpfs
 *
 * @name: name for dentry (to be seen in /proc/<pid>/maps
 * @size: size to be set for the file
 *
 */
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
{
	int error;
	struct file *file;
	struct inode *inode;
	struct dentry *dentry, *root;
	struct qstr this;

	if (IS_ERR(shm_mnt))
		return (void *)shm_mnt;

	error = -ENOMEM;
	this.name = name;
	this.len = strlen(name);
	this.hash = 0; /* will go */
	root = shm_mnt->mnt_root;
	dentry = d_alloc(root, &this);
	if (!dentry)
		goto put_memory;

	error = -ENFILE;
	file = get_empty_filp();
	if (!file)
		goto put_dentry;

	error = -ENOSPC;
	inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
	if (!inode)
		goto close_file;

	d_instantiate(dentry, inode);
	inode->i_nlink = 0;	/* It is unlinked */

	file->f_path.mnt = mntget(shm_mnt);
	file->f_path.dentry = dentry;
	file->f_mapping = inode->i_mapping;
	file->f_op = &ramfs_file_operations;
	file->f_mode = FMODE_WRITE | FMODE_READ;

	/* notify everyone as to the change of file size */
	error = do_truncate(dentry, size, 0, file);
	if (error < 0)
		goto close_file;

	return file;

close_file:
	put_filp(file);
put_dentry:
	dput(dentry);
put_memory:
	return ERR_PTR(error);
}
Beispiel #10
0
int remove_physical_dir (struct file *file)
{
	struct dentry *dentry;
	struct inode *dir;
	int res = 0;

	dentry = file->f_dentry;
	dir = dentry->d_parent->d_inode;

	res = vfs_rmdir (dir, dentry);
	dput (dentry);
	put_filp (file);

	return res;
}
Beispiel #11
0
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
	struct file * f;
	struct inode *inode;
	int error;

	error = -ENFILE;
	f = get_empty_filp();
	if (!f)
		goto cleanup_dentry;
	f->f_flags = flags;
	f->f_mode = (flags+1) & O_ACCMODE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;
	f->f_reada = 0;
	f->f_op = fops_get(inode->i_fop);
	if (inode->i_sb)
		file_move(f, &inode->i_sb->s_files);
	if (f->f_op && f->f_op->open) {
		error = f->f_op->open(inode,f);
		if (error)
			goto cleanup_all;
	}
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
cleanup_dentry:
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #12
0
static struct file *__dentry_open(struct path *path, struct file *f,
				int (*open)(struct inode *, struct file *),
				const struct cred *cred)
{
	struct file *res = do_dentry_open(path, f, open, cred);
	if (!IS_ERR(res)) {
		int error = open_check_o_direct(f);
		if (error) {
			fput(res);
			res = ERR_PTR(error);
		}
	} else {
		put_filp(f);
	}
	return res;
}
Beispiel #13
0
Datei: open.c Projekt: krzk/linux
struct file *filp_clone_open(struct file *oldfile)
{
	struct file *file;
	int retval;

	file = get_empty_filp();
	if (IS_ERR(file))
		return file;

	file->f_flags = oldfile->f_flags;
	retval = vfs_open(&oldfile->f_path, file, oldfile->f_cred);
	if (retval) {
		put_filp(file);
		return ERR_PTR(retval);
	}

	return file;
}
Beispiel #14
0
/*
 * Note that while the flag value (low two bits) for sys_open means:
 *	00 - read-only
 *	01 - write-only
 *	10 - read-write
 *	11 - special
 * it is changed into
 *	00 - no permissions needed
 *	01 - read-permission
 *	10 - write-permission
 *	11 - read-write
 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
 * used by symlinks.
 */
struct file *filp_open(const char * filename, int flags, int mode)
{
	int namei_flags, error;
	struct nameidata nd;
	struct file *f;

	namei_flags = flags;
	if ((namei_flags+1) & O_ACCMODE)
		namei_flags++;
	if (namei_flags & O_TRUNC)
		namei_flags |= 2;

	error = -ENFILE;
	f = get_empty_filp();
	if (f == NULL)
		return ERR_PTR(error);

	error = open_namei(filename, namei_flags, mode, &nd);
	if (!error)
		return __dentry_open(nd.dentry, nd.mnt, flags, f);

	put_filp(f);
	return ERR_PTR(error);
}
Beispiel #15
0
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					struct file *f,
					int (*open)(struct inode *, struct file *),
					const struct cred *cred)
{
	static const struct file_operations empty_fops = {};
	struct inode *inode;
	int error;

	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;

	if (unlikely(f->f_flags & O_PATH))
		f->f_mode = FMODE_PATH;

	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = __get_file_write_access(inode, mnt);
		if (error)
			goto cleanup_file;
		if (!special_file(inode->i_mode))
			file_take_write(f);
	}

	f->f_mapping = inode->i_mapping;
	f->f_path.dentry = dentry;
	f->f_path.mnt = mnt;
	f->f_pos = 0;
	file_sb_list_add(f, inode->i_sb);

	if (unlikely(f->f_mode & FMODE_PATH)) {
		f->f_op = &empty_fops;
		return f;
	}

	f->f_op = fops_get(inode->i_fop);

	error = security_dentry_open(f, cred);
	if (error)
		goto cleanup_all;

	error = break_lease(inode, f->f_flags);
	if (error)
		goto cleanup_all;

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}
	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
		i_readcount_inc(inode);

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_mem))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE) {
		put_write_access(inode);
		if (!special_file(inode->i_mode)) {
			/*
			 * We don't consider this a real
			 * mnt_want/drop_write() pair
			 * because it all happenend right
			 * here, so just reset the state.
			 */
			file_reset_write(f);
			mnt_drop_write(mnt);
		}
	}
	file_sb_list_del(f);
	f->f_path.dentry = NULL;
	f->f_path.mnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #16
0
static struct file *__dentry_open(struct _dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct _inode *, struct file *))
{
	struct _inode *inode;
	int error;
	struct super_block *sb;
	struct _file *_f = tx_cache_get_file(f);

	_f->f_flags = flags;
	_f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
		 		FMODE_PREAD | FMODE_PWRITE;
	inode = d_get_inode(dentry);
	sb = inode->i_sb;

	if (_f->f_mode & FMODE_WRITE) {
		error = get_write_access(parent(inode));
		if (error)
			goto cleanup_file;
	}

	f->f_mapping = inode->i_mapping;
	_f->f_path.dentry = parent(dentry);
	_f->f_path.mnt = mnt;
	_f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &sb->s_files);

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	_f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, 
			   tx_cache_get_inode(f->f_mapping->host)->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (_f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_page))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (_f->f_mode & FMODE_WRITE)
		put_write_access(parent(inode));
	file_kill(f);
	_f->f_path.dentry = NULL;
	_f->f_path.mnt = NULL;
cleanup_file:
	/* Avoid issues if we recycle this object */
	if(live_transaction())
		early_release(&f->xobj, 1);
	put_filp(f);
	dput(parent(dentry));
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #17
0
int do_pipe(int *fd)
{
	struct inode * inode;
	struct file *f1, *f2;
	int error;
	int i,j;

	error = -ENFILE;
	f1 = get_empty_filp();
	if (!f1)
		goto no_files;

	f2 = get_empty_filp();
	if (!f2)
		goto close_f1;

	inode = get_pipe_inode();
	if (!inode)
		goto close_f12;

	error = get_unused_fd();
	if (error < 0)
		goto close_f12_inode;
	i = error;

	error = get_unused_fd();
	if (error < 0)
		goto close_f12_inode_i;
	j = error;

	error = -ENOMEM;
	f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode, NULL));
	if (!f1->f_dentry)
		goto close_f12_inode_i_j;

	/* read file */
	f1->f_pos = f2->f_pos = 0;
	f1->f_flags = O_RDONLY;
	f1->f_op = &read_pipe_fops;
	f1->f_mode = 1;

	/* write file */
	f2->f_flags = O_WRONLY;
	f2->f_op = &write_pipe_fops;
	f2->f_mode = 2;

	fd_install(i, f1);
	fd_install(j, f2);
	fd[0] = i;
	fd[1] = j;
	return 0;

close_f12_inode_i_j:
	put_unused_fd(j);
close_f12_inode_i:
	put_unused_fd(i);
close_f12_inode:
	free_page((unsigned long) PIPE_BASE(*inode));
	iput(inode);
close_f12:
	put_filp(f2);
close_f1:
	put_filp(f1);
no_files:
	return error;	
}
Beispiel #18
0
/**
 * anon_inode_getfd - creates a new file instance by hooking it up to and
 *                    anonymous inode, and a dentry that describe the "class"
 *                    of the file
 *
 * @pfd:     [out]   pointer to the file descriptor
 * @dpinode: [out]   pointer to the inode
 * @pfile:   [out]   pointer to the file struct
 * @name:    [in]    name of the "class" of the new file
 * @fops     [in]    file operations for the new file
 * @priv     [in]    private data for the new file (will be file's private_data)
 *
 * Creates a new file by hooking it on a single inode. This is useful for files
 * that do not need to have a full-fledged inode in order to operate correctly.
 * All the files created with anon_inode_getfd() will share a single inode, by
 * hence saving memory and avoiding code duplication for the file/inode/dentry
 * setup.
 */
int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
		     const char *name, const struct file_operations *fops,
		     void *priv)
{
	struct qstr this;
	struct dentry *dentry;
	struct _dentry *_dentry;
	struct inode *inode;
	struct _inode *_inode;
	struct file *file;
	struct _file *_file;
	int error, fd;

	if (IS_ERR(anon_inode_inode))
		return -ENODEV;
	file = get_empty_filp();
	if (!file)
		return -ENFILE;

	_file = tx_cache_get_file(file);

	inode = igrab(anon_inode_inode);
	if (IS_ERR(inode)) {
		error = PTR_ERR(inode);
		goto err_put_filp;
	}

	_inode = tx_cache_get_inode(inode);

	error = get_unused_fd();
	if (error < 0)
		goto err_iput;
	fd = error;

	/*
	 * Link the inode to a directory entry by creating a unique name
	 * using the inode sequence number.
	 */
	error = -ENOMEM;
	this.name = name;
	this.len = strlen(name);
	this.hash = 0;
	dentry = d_alloc(tx_cache_get_dentry(anon_inode_mnt->mnt_sb->s_root), &this);
	if (!dentry)
		goto err_put_unused_fd;
	_dentry = tx_cache_get_dentry(dentry);
	_dentry->d_op = &anon_inodefs_dentry_operations;
	/* Do not publish this dentry inside the global dentry hash table */
	_dentry->d_flags &= ~DCACHE_UNHASHED;
	d_instantiate(_dentry, _inode);

	_file->f_path.mnt = mntget(anon_inode_mnt);
	_file->f_path.dentry = dentry;
	file->f_mapping = _inode->i_mapping;

	_file->f_pos = 0;
	_file->f_flags = O_RDWR;
	file->f_op = fops;
	_file->f_mode = FMODE_READ | FMODE_WRITE;
	_file->f_version = 0;
	file->private_data = priv;

	fd_install(fd, file);

	*pfd = fd;
	*pinode = inode;
	*pfile = file;
	return 0;

err_put_unused_fd:
	put_unused_fd(fd);
err_iput:
	iput(inode);
err_put_filp:
	put_filp(file);
	return error;
}
Beispiel #19
0
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, struct file *f)
{
	struct inode *inode;
	static LIST_HEAD(kill_list);
	int error;

	f->f_flags = flags;
	f->f_mode = (flags+1) & O_ACCMODE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = get_write_access(inode);
		if (error)
			goto cleanup_file;
	}

	f->f_dentry = dentry;
	f->f_vfsmnt = mnt;
	f->f_pos = 0;
	f->f_reada = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	/* preallocate kiobuf for O_DIRECT */
	f->f_iobuf = NULL;
	f->f_iobuf_lock = 0;
	if (f->f_flags & O_DIRECT) {
		error = alloc_kiovec(1, &f->f_iobuf);
		if (error)
			goto cleanup_all;
	}

	if (f->f_op && f->f_op->open) {
		error = f->f_op->open(inode,f);
		if (error)
			goto cleanup_all;
	}
	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!inode->i_mapping || !inode->i_mapping->a_ops ||
		    !(inode->i_mapping->a_ops->direct_IO ||
		      inode->i_mapping->a_ops->direct_sector_IO)) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	if (f->f_iobuf)
		free_kiovec(1, &f->f_iobuf);
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE)
		put_write_access(inode);
	file_move(f, &kill_list); /* out of the way.. */
	f->f_dentry = NULL;
	f->f_vfsmnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #20
0
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
					int flags, struct file *f,
					int (*open)(struct inode *, struct file *))
{
	struct inode *inode;
	int error;

	f->f_flags = flags;
	f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK |
				FMODE_PREAD | FMODE_PWRITE;
	inode = dentry->d_inode;
	if (f->f_mode & FMODE_WRITE) {
		error = __get_file_write_access(inode, mnt);
		if (error)
			goto cleanup_file;
		if (!special_file(inode->i_mode))
			file_take_write(f);
	}

	f->f_mapping = inode->i_mapping;
	f->f_path.dentry = dentry;
	f->f_path.mnt = mnt;
	f->f_pos = 0;
	f->f_op = fops_get(inode->i_fop);
	file_move(f, &inode->i_sb->s_files);

	error = security_dentry_open(f);
	if (error)
		goto cleanup_all;

	if (!open && f->f_op)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	/* NB: we're sure to have correct a_ops only after f_op->open */
	if (f->f_flags & O_DIRECT) {
		if (!f->f_mapping->a_ops ||
		    ((!f->f_mapping->a_ops->direct_IO) &&
		    (!f->f_mapping->a_ops->get_xip_mem))) {
			fput(f);
			f = ERR_PTR(-EINVAL);
		}
	}

	return f;

cleanup_all:
	fops_put(f->f_op);
	if (f->f_mode & FMODE_WRITE) {
		put_write_access(inode);
		if (!special_file(inode->i_mode)) {
			/*
			 * We don't consider this a real
			 * mnt_want/drop_write() pair
			 * because it all happenend right
			 * here, so just reset the state.
			 */
			file_reset_write(f);
			mnt_drop_write(mnt);
		}
	}
	file_kill(f);
	f->f_path.dentry = NULL;
	f->f_path.mnt = NULL;
cleanup_file:
	put_filp(f);
	dput(dentry);
	mntput(mnt);
	return ERR_PTR(error);
}
Beispiel #21
0
/**
 * lookup_instantiate_filp - instantiates the open intent filp
 * @nd: pointer to nameidata
 * @dentry: pointer to dentry
 * @open: open callback
 *
 * Helper for filesystems that want to use lookup open intents and pass back
 * a fully instantiated struct file to the caller.
 * This function is meant to be called from within a filesystem's
 * lookup method.
 * Beware of calling it for non-regular files! Those ->open methods might block
 * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
 * leading to a deadlock, as nobody can open that fifo anymore, because
 * another process to open fifo will block on locked parent when doing lookup).
 * Note that in case of error, nd->intent.open.file is destroyed, but the
 * path information remains valid.
 * If the open callback is set to NULL, then the standard f_op->open()
 * filesystem callback is substituted.
 */
struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
		int (*open)(struct inode *, struct file *))
{
	struct path path = { .dentry = dentry, .mnt = nd->path.mnt };
	const struct cred *cred = current_cred();

	if (IS_ERR(nd->intent.open.file))
		goto out;
	if (IS_ERR(dentry))
		goto out_err;
	nd->intent.open.file = __dentry_open(&path, nd->intent.open.file,
					     open, cred);
out:
	return nd->intent.open.file;
out_err:
	release_open_intent(nd);
	nd->intent.open.file = (struct file *)dentry;
	goto out;
}
EXPORT_SYMBOL_GPL(lookup_instantiate_filp);

/**
 * nameidata_to_filp - convert a nameidata to an open filp.
 * @nd: pointer to nameidata
 * @flags: open flags
 *
 * Note that this function destroys the original nameidata
 */
struct file *nameidata_to_filp(struct nameidata *nd)
{
	const struct cred *cred = current_cred();
	struct file *filp;

	/* Pick up the filp from the open intent */
	filp = nd->intent.open.file;
	nd->intent.open.file = NULL;

	/* Has the filesystem initialised the file for us? */
	if (filp->f_path.dentry == NULL) {
		struct inode *inode = nd->path.dentry->d_inode;

		if (inode->i_op->open) {
			int flags = filp->f_flags;
			put_filp(filp);
			filp = inode->i_op->open(nd->path.dentry, flags, cred);
		} else {
			filp = __dentry_open(&nd->path, filp, NULL, cred);
		}
	}

	return filp;
}

/*
 * 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,
			 const struct cred *cred)
{
	struct path path = { .dentry = dentry, .mnt = mnt };
	struct file *ret;

	/* We must always pass in a valid mount pointer. */
	BUG_ON(!mnt);

	ret = vfs_open(&path, flags, cred);
	path_put(&path);

	return ret;
}
EXPORT_SYMBOL(dentry_open);

/**
 * vfs_open - open the file at the given path
 * @path: path to open
 * @flags: open flags
 * @cred: credentials to use
 *
 * Open the file.  If successful, the returned file will have acquired
 * an additional reference for path.
 */
struct file *vfs_open(struct path *path, int flags, const struct cred *cred)
{
	struct file *f;
	struct inode *inode = path->dentry->d_inode;

	validate_creds(cred);

	if (inode->i_op->open)
		return inode->i_op->open(path->dentry, flags, cred);
	f = get_empty_filp();
	if (f == NULL)
		return ERR_PTR(-ENFILE);

	f->f_flags = flags;
	return __dentry_open(path, f, NULL, cred);
}
EXPORT_SYMBOL(vfs_open);

static void __put_unused_fd(struct files_struct *files, unsigned int fd)
{
	struct fdtable *fdt = files_fdtable(files);
	__FD_CLR(fd, fdt->open_fds);
	if (fd < files->next_fd)
		files->next_fd = fd;
}

void put_unused_fd(unsigned int fd)
{
	struct files_struct *files = current->files;
	spin_lock(&files->file_lock);
	__put_unused_fd(files, fd);
	spin_unlock(&files->file_lock);
}

EXPORT_SYMBOL(put_unused_fd);

/*
 * Install a file pointer in the fd array.
 *
 * The VFS is full of places where we drop the files lock between
 * setting the open_fds bitmap and installing the file in the file
 * array.  At any such point, we are vulnerable to a dup2() race
 * installing a file in the array before us.  We need to detect this and
 * fput() the struct file we are about to overwrite in this case.
 *
 * It should never happen - if we allow dup2() do it, _really_ bad things
 * will follow.
 */

void fd_install(unsigned int fd, struct file *file)
{
	struct files_struct *files = current->files;
	struct fdtable *fdt;
	spin_lock(&files->file_lock);
	fdt = files_fdtable(files);
	BUG_ON(fdt->fd[fd] != NULL);
	rcu_assign_pointer(fdt->fd[fd], file);
	spin_unlock(&files->file_lock);
}

EXPORT_SYMBOL(fd_install);

static inline int build_open_flags(int flags, int mode, struct open_flags *op)
{
	int lookup_flags = 0;
	int acc_mode;

	if (!(flags & O_CREAT))
		mode = 0;
	op->mode = mode;

	/* Must never be set by userspace */
	flags &= ~FMODE_NONOTIFY;

	/*
	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
	 * check for O_DSYNC if the need any syncing at all we enforce it's
	 * always set instead of having to deal with possibly weird behaviour
	 * for malicious applications setting only __O_SYNC.
	 */
	if (flags & __O_SYNC)
		flags |= O_DSYNC;

	/*
	 * If we have O_PATH in the open flag. Then we
	 * cannot have anything other than the below set of flags
	 */
	if (flags & O_PATH) {
		flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
		acc_mode = 0;
	} else {
		acc_mode = MAY_OPEN | ACC_MODE(flags);
	}

	op->open_flag = flags;

	/* O_TRUNC implies we need access checks for write permissions */
	if (flags & O_TRUNC)
		acc_mode |= MAY_WRITE;

	/* Allow the LSM permission hook to distinguish append
	   access from general write access. */
	if (flags & O_APPEND)
		acc_mode |= MAY_APPEND;

	op->acc_mode = acc_mode;

	op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;

	if (flags & O_CREAT) {
		op->intent |= LOOKUP_CREATE;
		if (flags & O_EXCL)
			op->intent |= LOOKUP_EXCL;
	}

	if (flags & O_DIRECTORY)
		lookup_flags |= LOOKUP_DIRECTORY;
	if (!(flags & O_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;
	return lookup_flags;
}
Beispiel #22
0
int do_pipe(int *fd)
{
	struct qstr this;
	char name[32];
	struct dentry *dentry;
	struct inode * inode;
	struct file *f1, *f2;
	int error;
	int i,j;

	error = -ENFILE;
	f1 = get_empty_filp();
	if (!f1)
		goto no_files;

	f2 = get_empty_filp();
	if (!f2)
		goto close_f1;

	inode = get_pipe_inode();
	if (!inode)
		goto close_f12;

	error = get_unused_fd();
	if (error < 0)
		goto close_f12_inode;
	i = error;

	error = get_unused_fd();
	if (error < 0)
		goto close_f12_inode_i;
	j = error;

	error = -ENOMEM;
	sprintf(name, "[%lu]", inode->i_ino);
	this.name = name;
	this.len = strlen(name);
	this.hash = inode->i_ino; /* will go */
	dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &this);
	if (!dentry)
		goto close_f12_inode_i_j;
	dentry->d_op = &pipefs_dentry_operations;
	d_add(dentry, inode);
	f1->f_vfsmnt = f2->f_vfsmnt = mntget(mntget(pipe_mnt));
	f1->f_dentry = f2->f_dentry = dget(dentry);

	/* read file */
	f1->f_pos = f2->f_pos = 0;
	f1->f_flags = O_RDONLY;
	f1->f_op = &read_pipe_fops;
	f1->f_mode = 1;
	f1->f_version = 0;

	/* write file */
	f2->f_flags = O_WRONLY;
	f2->f_op = &write_pipe_fops;
	f2->f_mode = 2;
	f2->f_version = 0;

	fd_install(i, f1);
	fd_install(j, f2);
	fd[0] = i;
	fd[1] = j;
	return 0;

close_f12_inode_i_j:
	put_unused_fd(j);
close_f12_inode_i:
	put_unused_fd(i);
close_f12_inode:
	free_page((unsigned long) PIPE_BASE(*inode));
	kfree(inode->i_pipe);
	inode->i_pipe = NULL;
	iput(inode);
close_f12:
	put_filp(f2);
close_f1:
	put_filp(f1);
no_files:
	return error;	
}
Beispiel #23
0
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
    struct file * f;
    struct inode *inode;
    static LIST_HEAD(kill_list);
    int error;

    error = -ENFILE;
    f = get_empty_filp();
    if (!f)
        goto cleanup_dentry;
    f->f_flags = flags;
    f->f_mode = (flags+1) & O_ACCMODE;
    inode = dentry->d_inode;
    if (f->f_mode & FMODE_WRITE) {
        error = get_write_access(inode);
        if (error)
            goto cleanup_file;
    }

    f->f_dentry = dentry;
    f->f_vfsmnt = mnt;
    f->f_pos = 0;
    f->f_reada = 0;
    f->f_op = fops_get(inode->i_fop);
    file_move(f, &inode->i_sb->s_files);

    /* preallocate kiobuf for O_DIRECT */
    f->f_iobuf = NULL;
    f->f_iobuf_lock = 0;
    if (f->f_flags & O_DIRECT) {
        error = alloc_kiovec(1, &f->f_iobuf);
        if (error)
            goto cleanup_all;
    }

    if (f->f_op && f->f_op->open) {
        error = f->f_op->open(inode,f);
        if (error)
            goto cleanup_all;
    }
    f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);

    return f;

cleanup_all:
    if (f->f_iobuf)
        free_kiovec(1, &f->f_iobuf);
    fops_put(f->f_op);
    if (f->f_mode & FMODE_WRITE)
        put_write_access(inode);
    file_move(f, &kill_list); /* out of the way.. */
    f->f_dentry = NULL;
    f->f_vfsmnt = NULL;
cleanup_file:
    put_filp(f);
cleanup_dentry:
    dput(dentry);
    mntput(mnt);
    return ERR_PTR(error);
}