Merge branch 'for-ovl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs into overlayfs-next
This gives us the open_with_fake_path() helper that is needed for stacked open files in overlay and mmap in particular.
This commit is contained in:
commit
9951934d76
|
@ -553,24 +553,13 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
|||
|
||||
/* Clone the lessor file to create a new file for us */
|
||||
DRM_DEBUG_LEASE("Allocating lease file\n");
|
||||
path_get(&lessor_file->f_path);
|
||||
lessee_file = alloc_file(&lessor_file->f_path,
|
||||
lessor_file->f_mode,
|
||||
fops_get(lessor_file->f_inode->i_fop));
|
||||
|
||||
lessee_file = file_clone_open(lessor_file);
|
||||
if (IS_ERR(lessee_file)) {
|
||||
ret = PTR_ERR(lessee_file);
|
||||
goto out_lessee;
|
||||
}
|
||||
|
||||
/* Initialize the new file for DRM */
|
||||
DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open);
|
||||
ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file);
|
||||
if (ret)
|
||||
goto out_lessee_file;
|
||||
|
||||
lessee_priv = lessee_file->private_data;
|
||||
|
||||
/* Change the file to a master one */
|
||||
drm_master_put(&lessee_priv->master);
|
||||
lessee_priv->master = lessee;
|
||||
|
@ -588,9 +577,6 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
|
|||
DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
|
||||
return 0;
|
||||
|
||||
out_lessee_file:
|
||||
fput(lessee_file);
|
||||
|
||||
out_lessee:
|
||||
drm_master_put(&lessee);
|
||||
|
||||
|
|
|
@ -102,16 +102,15 @@ static struct file *cxl_getfile(const char *name,
|
|||
path.mnt = mntget(cxl_vfs_mount);
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
if (IS_ERR(file))
|
||||
goto err_dput;
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file = alloc_file(&path, flags & (O_ACCMODE | O_NONBLOCK), fops);
|
||||
if (IS_ERR(file)) {
|
||||
path_put(&path);
|
||||
goto err_fs;
|
||||
}
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
||||
err_dput:
|
||||
path_put(&path);
|
||||
err_inode:
|
||||
iput(inode);
|
||||
err_fs:
|
||||
|
|
|
@ -129,20 +129,18 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
|
|||
path.mnt = mntget(ocxlflash_vfs_mount);
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
file = alloc_file(&path, flags & (O_ACCMODE | O_NONBLOCK), fops);
|
||||
if (IS_ERR(file)) {
|
||||
rc = PTR_ERR(file);
|
||||
dev_err(dev, "%s: alloc_file failed rc=%d\n",
|
||||
__func__, rc);
|
||||
goto err5;
|
||||
path_put(&path);
|
||||
goto err3;
|
||||
}
|
||||
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
out:
|
||||
return file;
|
||||
err5:
|
||||
path_put(&path);
|
||||
err4:
|
||||
iput(inode);
|
||||
err3:
|
||||
|
|
8
fs/aio.c
8
fs/aio.c
|
@ -234,13 +234,9 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
|
|||
path.mnt = mntget(aio_mnt);
|
||||
|
||||
d_instantiate(path.dentry, inode);
|
||||
file = alloc_file(&path, FMODE_READ | FMODE_WRITE, &aio_ring_fops);
|
||||
if (IS_ERR(file)) {
|
||||
file = alloc_file(&path, O_RDWR, &aio_ring_fops);
|
||||
if (IS_ERR(file))
|
||||
path_put(&path);
|
||||
return file;
|
||||
}
|
||||
|
||||
file->f_flags = O_RDWR;
|
||||
return file;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,12 +102,11 @@ struct file *anon_inode_getfile(const char *name,
|
|||
|
||||
d_instantiate(path.dentry, anon_inode_inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
file = alloc_file(&path, flags & (O_ACCMODE | O_NONBLOCK), fops);
|
||||
if (IS_ERR(file))
|
||||
goto err_dput;
|
||||
file->f_mapping = anon_inode_inode->i_mapping;
|
||||
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
|
|
@ -205,7 +205,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
|
|||
goto error;
|
||||
|
||||
if (fmt->flags & MISC_FMT_OPEN_FILE) {
|
||||
interp_file = filp_clone_open(fmt->interp_file);
|
||||
interp_file = file_clone_open(fmt->interp_file);
|
||||
if (!IS_ERR(interp_file))
|
||||
deny_write_access(interp_file);
|
||||
} else {
|
||||
|
|
|
@ -51,6 +51,7 @@ static void file_free_rcu(struct rcu_head *head)
|
|||
|
||||
static inline void file_free(struct file *f)
|
||||
{
|
||||
security_file_free(f);
|
||||
percpu_counter_dec(&nr_files);
|
||||
call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
|
||||
}
|
||||
|
@ -100,9 +101,8 @@ int proc_nr_files(struct ctl_table *table, int write,
|
|||
* done, you will imbalance int the mount's writer count
|
||||
* and a warning at __fput() time.
|
||||
*/
|
||||
struct file *get_empty_filp(void)
|
||||
struct file *alloc_empty_file(int flags, const struct cred *cred)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
static long old_max;
|
||||
struct file *f;
|
||||
int error;
|
||||
|
@ -123,11 +123,10 @@ struct file *get_empty_filp(void)
|
|||
if (unlikely(!f))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
percpu_counter_inc(&nr_files);
|
||||
f->f_cred = get_cred(cred);
|
||||
error = security_file_alloc(f);
|
||||
if (unlikely(error)) {
|
||||
file_free(f);
|
||||
file_free_rcu(&f->f_u.fu_rcuhead);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
|
@ -136,7 +135,10 @@ struct file *get_empty_filp(void)
|
|||
spin_lock_init(&f->f_lock);
|
||||
mutex_init(&f->f_pos_lock);
|
||||
eventpoll_init_file(f);
|
||||
f->f_flags = flags;
|
||||
f->f_mode = OPEN_FMODE(flags);
|
||||
/* f->f_version: 0 */
|
||||
percpu_counter_inc(&nr_files);
|
||||
return f;
|
||||
|
||||
over:
|
||||
|
@ -152,15 +154,15 @@ over:
|
|||
* alloc_file - allocate and initialize a 'struct file'
|
||||
*
|
||||
* @path: the (dentry, vfsmount) pair for the new file
|
||||
* @mode: the mode with which the new file will be opened
|
||||
* @flags: O_... flags with which the new file will be opened
|
||||
* @fop: the 'struct file_operations' for the new file
|
||||
*/
|
||||
struct file *alloc_file(const struct path *path, fmode_t mode,
|
||||
struct file *alloc_file(const struct path *path, int flags,
|
||||
const struct file_operations *fop)
|
||||
{
|
||||
struct file *file;
|
||||
|
||||
file = get_empty_filp();
|
||||
file = alloc_empty_file(flags, current_cred());
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
|
@ -168,15 +170,15 @@ struct file *alloc_file(const struct path *path, fmode_t mode,
|
|||
file->f_inode = path->dentry->d_inode;
|
||||
file->f_mapping = path->dentry->d_inode->i_mapping;
|
||||
file->f_wb_err = filemap_sample_wb_err(file->f_mapping);
|
||||
if ((mode & FMODE_READ) &&
|
||||
if ((file->f_mode & FMODE_READ) &&
|
||||
likely(fop->read || fop->read_iter))
|
||||
mode |= FMODE_CAN_READ;
|
||||
if ((mode & FMODE_WRITE) &&
|
||||
file->f_mode |= FMODE_CAN_READ;
|
||||
if ((file->f_mode & FMODE_WRITE) &&
|
||||
likely(fop->write || fop->write_iter))
|
||||
mode |= FMODE_CAN_WRITE;
|
||||
file->f_mode = mode;
|
||||
file->f_mode |= FMODE_CAN_WRITE;
|
||||
file->f_mode |= FMODE_OPENED;
|
||||
file->f_op = fop;
|
||||
if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||
if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||
i_readcount_inc(path->dentry->d_inode);
|
||||
return file;
|
||||
}
|
||||
|
@ -190,6 +192,9 @@ static void __fput(struct file *file)
|
|||
struct vfsmount *mnt = file->f_path.mnt;
|
||||
struct inode *inode = file->f_inode;
|
||||
|
||||
if (unlikely(!(file->f_mode & FMODE_OPENED)))
|
||||
goto out;
|
||||
|
||||
might_sleep();
|
||||
|
||||
fsnotify_close(file);
|
||||
|
@ -207,7 +212,6 @@ static void __fput(struct file *file)
|
|||
}
|
||||
if (file->f_op->release)
|
||||
file->f_op->release(inode, file);
|
||||
security_file_free(file);
|
||||
if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
|
||||
!(file->f_mode & FMODE_PATH))) {
|
||||
cdev_put(inode->i_cdev);
|
||||
|
@ -220,12 +224,10 @@ static void __fput(struct file *file)
|
|||
put_write_access(inode);
|
||||
__mnt_drop_write(mnt);
|
||||
}
|
||||
file->f_path.dentry = NULL;
|
||||
file->f_path.mnt = NULL;
|
||||
file->f_inode = NULL;
|
||||
file_free(file);
|
||||
dput(dentry);
|
||||
mntput(mnt);
|
||||
out:
|
||||
file_free(file);
|
||||
}
|
||||
|
||||
static LLIST_HEAD(delayed_fput_list);
|
||||
|
@ -300,14 +302,6 @@ void __fput_sync(struct file *file)
|
|||
|
||||
EXPORT_SYMBOL(fput);
|
||||
|
||||
void put_filp(struct file *file)
|
||||
{
|
||||
if (atomic_long_dec_and_test(&file->f_count)) {
|
||||
security_file_free(file);
|
||||
file_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
void __init files_init(void)
|
||||
{
|
||||
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
|
||||
|
|
|
@ -1375,8 +1375,7 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
|
|||
inode->i_size = size;
|
||||
clear_nlink(inode);
|
||||
|
||||
file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
|
||||
&hugetlbfs_file_operations);
|
||||
file = alloc_file(&path, O_RDWR, &hugetlbfs_file_operations);
|
||||
if (IS_ERR(file))
|
||||
goto out_dentry; /* inode is already attached */
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
|
|||
/*
|
||||
* file_table.c
|
||||
*/
|
||||
extern struct file *get_empty_filp(void);
|
||||
extern struct file *alloc_empty_file(int, const struct cred *);
|
||||
|
||||
/*
|
||||
* super.c
|
||||
|
@ -125,9 +125,7 @@ int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
|
|||
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
|
||||
int flag);
|
||||
|
||||
extern int open_check_o_direct(struct file *f);
|
||||
extern int vfs_open(const struct path *, struct file *, const struct cred *);
|
||||
extern struct file *filp_clone_open(struct file *);
|
||||
extern int vfs_open(const struct path *, struct file *);
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
|
|
45
fs/namei.c
45
fs/namei.c
|
@ -3396,19 +3396,15 @@ finish_open_created:
|
|||
if (error)
|
||||
goto out;
|
||||
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
|
||||
error = vfs_open(&nd->path, file, current_cred());
|
||||
error = vfs_open(&nd->path, file);
|
||||
if (error)
|
||||
goto out;
|
||||
*opened |= FILE_OPENED;
|
||||
opened:
|
||||
error = open_check_o_direct(file);
|
||||
if (!error)
|
||||
error = ima_file_check(file, op->acc_mode, *opened);
|
||||
error = ima_file_check(file, op->acc_mode, *opened);
|
||||
if (!error && will_truncate)
|
||||
error = handle_truncate(file);
|
||||
out:
|
||||
if (unlikely(error) && (*opened & FILE_OPENED))
|
||||
fput(file);
|
||||
if (unlikely(error > 0)) {
|
||||
WARN_ON(1);
|
||||
error = -EINVAL;
|
||||
|
@ -3481,11 +3477,6 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
|
|||
goto out2;
|
||||
file->f_path.mnt = path.mnt;
|
||||
error = finish_open(file, child, NULL, opened);
|
||||
if (error)
|
||||
goto out2;
|
||||
error = open_check_o_direct(file);
|
||||
if (error)
|
||||
fput(file);
|
||||
out2:
|
||||
mnt_drop_write(path.mnt);
|
||||
out:
|
||||
|
@ -3499,7 +3490,7 @@ static int do_o_path(struct nameidata *nd, unsigned flags, struct file *file)
|
|||
int error = path_lookupat(nd, flags, &path);
|
||||
if (!error) {
|
||||
audit_inode(nd->name, path.dentry, 0);
|
||||
error = vfs_open(&path, file, current_cred());
|
||||
error = vfs_open(&path, file);
|
||||
path_put(&path);
|
||||
}
|
||||
return error;
|
||||
|
@ -3513,12 +3504,10 @@ static struct file *path_openat(struct nameidata *nd,
|
|||
int opened = 0;
|
||||
int error;
|
||||
|
||||
file = get_empty_filp();
|
||||
file = alloc_empty_file(op->open_flag, current_cred());
|
||||
if (IS_ERR(file))
|
||||
return file;
|
||||
|
||||
file->f_flags = op->open_flag;
|
||||
|
||||
if (unlikely(file->f_flags & __O_TMPFILE)) {
|
||||
error = do_tmpfile(nd, flags, op, file, &opened);
|
||||
goto out2;
|
||||
|
@ -3533,7 +3522,7 @@ static struct file *path_openat(struct nameidata *nd,
|
|||
|
||||
s = path_init(nd, flags);
|
||||
if (IS_ERR(s)) {
|
||||
put_filp(file);
|
||||
fput(file);
|
||||
return ERR_CAST(s);
|
||||
}
|
||||
while (!(error = link_path_walk(s, nd)) &&
|
||||
|
@ -3547,20 +3536,20 @@ static struct file *path_openat(struct nameidata *nd,
|
|||
}
|
||||
terminate_walk(nd);
|
||||
out2:
|
||||
if (!(opened & FILE_OPENED)) {
|
||||
BUG_ON(!error);
|
||||
put_filp(file);
|
||||
if (likely(!error)) {
|
||||
if (likely(opened & FILE_OPENED))
|
||||
return file;
|
||||
WARN_ON(1);
|
||||
error = -EINVAL;
|
||||
}
|
||||
if (unlikely(error)) {
|
||||
if (error == -EOPENSTALE) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
error = -ECHILD;
|
||||
else
|
||||
error = -ESTALE;
|
||||
}
|
||||
file = ERR_PTR(error);
|
||||
fput(file);
|
||||
if (error == -EOPENSTALE) {
|
||||
if (flags & LOOKUP_RCU)
|
||||
error = -ECHILD;
|
||||
else
|
||||
error = -ESTALE;
|
||||
}
|
||||
return file;
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||
|
|
92
fs/open.c
92
fs/open.c
|
@ -724,27 +724,13 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
|
|||
return ksys_fchown(fd, user, group);
|
||||
}
|
||||
|
||||
int open_check_o_direct(struct file *f)
|
||||
{
|
||||
/* 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)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_dentry_open(struct file *f,
|
||||
struct inode *inode,
|
||||
int (*open)(struct inode *, struct file *),
|
||||
const struct cred *cred)
|
||||
int (*open)(struct inode *, struct file *))
|
||||
{
|
||||
static const struct file_operations empty_fops = {};
|
||||
int error;
|
||||
|
||||
f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
|
||||
FMODE_PREAD | FMODE_PWRITE;
|
||||
|
||||
path_get(&f->f_path);
|
||||
f->f_inode = inode;
|
||||
f->f_mapping = inode->i_mapping;
|
||||
|
@ -753,7 +739,7 @@ static int do_dentry_open(struct file *f,
|
|||
f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
|
||||
|
||||
if (unlikely(f->f_flags & O_PATH)) {
|
||||
f->f_mode = FMODE_PATH;
|
||||
f->f_mode = FMODE_PATH | FMODE_OPENED;
|
||||
f->f_op = &empty_fops;
|
||||
return 0;
|
||||
}
|
||||
|
@ -780,7 +766,7 @@ static int do_dentry_open(struct file *f,
|
|||
goto cleanup_all;
|
||||
}
|
||||
|
||||
error = security_file_open(f, cred);
|
||||
error = security_file_open(f);
|
||||
if (error)
|
||||
goto cleanup_all;
|
||||
|
||||
|
@ -788,6 +774,8 @@ static int do_dentry_open(struct file *f,
|
|||
if (error)
|
||||
goto cleanup_all;
|
||||
|
||||
/* normally all 3 are set; ->open() can clear them if needed */
|
||||
f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
|
||||
if (!open)
|
||||
open = f->f_op->open;
|
||||
if (open) {
|
||||
|
@ -795,6 +783,7 @@ static int do_dentry_open(struct file *f,
|
|||
if (error)
|
||||
goto cleanup_all;
|
||||
}
|
||||
f->f_mode |= FMODE_OPENED;
|
||||
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
||||
i_readcount_inc(inode);
|
||||
if ((f->f_mode & FMODE_READ) &&
|
||||
|
@ -809,9 +798,16 @@ static int do_dentry_open(struct file *f,
|
|||
|
||||
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)
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup_all:
|
||||
if (WARN_ON_ONCE(error > 0))
|
||||
error = -EINVAL;
|
||||
fops_put(f->f_op);
|
||||
if (f->f_mode & FMODE_WRITER) {
|
||||
put_write_access(inode);
|
||||
|
@ -854,8 +850,7 @@ int finish_open(struct file *file, struct dentry *dentry,
|
|||
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
|
||||
|
||||
file->f_path.dentry = dentry;
|
||||
error = do_dentry_open(file, d_backing_inode(dentry), open,
|
||||
current_cred());
|
||||
error = do_dentry_open(file, d_backing_inode(dentry), open);
|
||||
if (!error)
|
||||
*opened |= FILE_OPENED;
|
||||
|
||||
|
@ -896,8 +891,7 @@ EXPORT_SYMBOL(file_path);
|
|||
* @file: newly allocated file with f_flag initialized
|
||||
* @cred: credentials to use
|
||||
*/
|
||||
int vfs_open(const struct path *path, struct file *file,
|
||||
const struct cred *cred)
|
||||
int vfs_open(const struct path *path, struct file *file)
|
||||
{
|
||||
struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags, 0);
|
||||
|
||||
|
@ -905,7 +899,7 @@ int vfs_open(const struct path *path, struct file *file,
|
|||
return PTR_ERR(dentry);
|
||||
|
||||
file->f_path = *path;
|
||||
return do_dentry_open(file, d_backing_inode(dentry), NULL, cred);
|
||||
return do_dentry_open(file, d_backing_inode(dentry), NULL);
|
||||
}
|
||||
|
||||
struct file *dentry_open(const struct path *path, int flags,
|
||||
|
@ -919,19 +913,11 @@ struct file *dentry_open(const struct path *path, int flags,
|
|||
/* We must always pass in a valid mount pointer. */
|
||||
BUG_ON(!path->mnt);
|
||||
|
||||
f = get_empty_filp();
|
||||
f = alloc_empty_file(flags, cred);
|
||||
if (!IS_ERR(f)) {
|
||||
f->f_flags = flags;
|
||||
error = vfs_open(path, f, 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);
|
||||
error = vfs_open(path, f);
|
||||
if (error) {
|
||||
fput(f);
|
||||
f = ERR_PTR(error);
|
||||
}
|
||||
}
|
||||
|
@ -939,6 +925,24 @@ struct file *dentry_open(const struct path *path, int flags,
|
|||
}
|
||||
EXPORT_SYMBOL(dentry_open);
|
||||
|
||||
struct file *open_with_fake_path(const struct path *path, int flags,
|
||||
struct inode *inode, const struct cred *cred)
|
||||
{
|
||||
struct file *f = alloc_empty_file(flags, cred);
|
||||
if (!IS_ERR(f)) {
|
||||
int error;
|
||||
|
||||
f->f_path = *path;
|
||||
error = do_dentry_open(f, inode, NULL);
|
||||
if (error) {
|
||||
fput(f);
|
||||
f = ERR_PTR(error);
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
EXPORT_SYMBOL(open_with_fake_path);
|
||||
|
||||
static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
|
||||
{
|
||||
int lookup_flags = 0;
|
||||
|
@ -1063,26 +1067,6 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
|
|||
}
|
||||
EXPORT_SYMBOL(file_open_root);
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(filp_clone_open);
|
||||
|
||||
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
|
||||
{
|
||||
struct open_flags op;
|
||||
|
|
15
fs/pipe.c
15
fs/pipe.c
|
@ -760,29 +760,28 @@ int create_pipe_files(struct file **res, int flags)
|
|||
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops);
|
||||
f = alloc_file(&path, O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)),
|
||||
&pipefifo_fops);
|
||||
if (IS_ERR(f)) {
|
||||
err = PTR_ERR(f);
|
||||
goto err_dentry;
|
||||
}
|
||||
|
||||
f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
|
||||
f->private_data = inode->i_pipe;
|
||||
|
||||
res[0] = alloc_file(&path, FMODE_READ, &pipefifo_fops);
|
||||
res[0] = alloc_file(&path, O_RDONLY | (flags & O_NONBLOCK),
|
||||
&pipefifo_fops);
|
||||
if (IS_ERR(res[0])) {
|
||||
err = PTR_ERR(res[0]);
|
||||
goto err_file;
|
||||
put_pipe_info(inode, inode->i_pipe);
|
||||
fput(f);
|
||||
return PTR_ERR(res[0]);
|
||||
}
|
||||
|
||||
path_get(&path);
|
||||
res[0]->private_data = inode->i_pipe;
|
||||
res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
|
||||
res[1] = f;
|
||||
return 0;
|
||||
|
||||
err_file:
|
||||
put_filp(f);
|
||||
err_dentry:
|
||||
free_pipe_info(inode->i_pipe);
|
||||
path_put(&path);
|
||||
|
|
|
@ -564,11 +564,20 @@ static int proc_seq_open(struct inode *inode, struct file *file)
|
|||
return seq_open(file, de->seq_ops);
|
||||
}
|
||||
|
||||
static int proc_seq_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct proc_dir_entry *de = PDE(inode);
|
||||
|
||||
if (de->state_size)
|
||||
return seq_release_private(inode, file);
|
||||
return seq_release(inode, file);
|
||||
}
|
||||
|
||||
static const struct file_operations proc_seq_fops = {
|
||||
.open = proc_seq_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.release = proc_seq_release,
|
||||
};
|
||||
|
||||
struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
|
||||
|
|
|
@ -18,7 +18,7 @@ struct file_operations;
|
|||
struct vfsmount;
|
||||
struct dentry;
|
||||
struct path;
|
||||
extern struct file *alloc_file(const struct path *, fmode_t mode,
|
||||
extern struct file *alloc_file(const struct path *, int flags,
|
||||
const struct file_operations *fop);
|
||||
|
||||
static inline void fput_light(struct file *file, int fput_needed)
|
||||
|
@ -78,7 +78,6 @@ extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
|
|||
extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
|
||||
extern void set_close_on_exec(unsigned int fd, int flag);
|
||||
extern bool get_close_on_exec(unsigned int fd);
|
||||
extern void put_filp(struct file *);
|
||||
extern int get_unused_fd_flags(unsigned flags);
|
||||
extern void put_unused_fd(unsigned int fd);
|
||||
|
||||
|
|
|
@ -148,6 +148,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
|
|||
/* Has write method(s) */
|
||||
#define FMODE_CAN_WRITE ((__force fmode_t)0x40000)
|
||||
|
||||
#define FMODE_OPENED ((__force fmode_t)0x80000)
|
||||
|
||||
/* File was opened by fanotify and shouldn't generate fanotify events */
|
||||
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
|
||||
|
||||
|
@ -2422,6 +2424,12 @@ extern struct file *filp_open(const char *, int, umode_t);
|
|||
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
|
||||
const char *, int, umode_t);
|
||||
extern struct file * dentry_open(const struct path *, int, const struct cred *);
|
||||
extern struct file * open_with_fake_path(const struct path *, int,
|
||||
struct inode*, const struct cred *);
|
||||
static inline struct file *file_clone_open(struct file *file)
|
||||
{
|
||||
return dentry_open(&file->f_path, file->f_flags, file->f_cred);
|
||||
}
|
||||
extern int filp_close(struct file *, fl_owner_t id);
|
||||
|
||||
extern struct filename *getname_flags(const char __user *, int, int *);
|
||||
|
|
|
@ -1569,7 +1569,7 @@ union security_list_options {
|
|||
int (*file_send_sigiotask)(struct task_struct *tsk,
|
||||
struct fown_struct *fown, int sig);
|
||||
int (*file_receive)(struct file *file);
|
||||
int (*file_open)(struct file *file, const struct cred *cred);
|
||||
int (*file_open)(struct file *file);
|
||||
|
||||
int (*task_alloc)(struct task_struct *task, unsigned long clone_flags);
|
||||
void (*task_free)(struct task_struct *task);
|
||||
|
|
|
@ -309,7 +309,7 @@ void security_file_set_fowner(struct file *file);
|
|||
int security_file_send_sigiotask(struct task_struct *tsk,
|
||||
struct fown_struct *fown, int sig);
|
||||
int security_file_receive(struct file *file);
|
||||
int security_file_open(struct file *file, const struct cred *cred);
|
||||
int security_file_open(struct file *file);
|
||||
int security_task_alloc(struct task_struct *task, unsigned long clone_flags);
|
||||
void security_task_free(struct task_struct *task);
|
||||
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
|
||||
|
@ -858,8 +858,7 @@ static inline int security_file_receive(struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_file_open(struct file *file,
|
||||
const struct cred *cred)
|
||||
static inline int security_file_open(struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1362,7 +1362,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
|||
struct ipc_namespace *ns;
|
||||
struct shm_file_data *sfd;
|
||||
struct path path;
|
||||
fmode_t f_mode;
|
||||
int f_flags;
|
||||
unsigned long populate = 0;
|
||||
|
||||
err = -EINVAL;
|
||||
|
@ -1395,11 +1395,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
|||
if (shmflg & SHM_RDONLY) {
|
||||
prot = PROT_READ;
|
||||
acc_mode = S_IRUGO;
|
||||
f_mode = FMODE_READ;
|
||||
f_flags = O_RDONLY;
|
||||
} else {
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
acc_mode = S_IRUGO | S_IWUGO;
|
||||
f_mode = FMODE_READ | FMODE_WRITE;
|
||||
f_flags = O_RDWR;
|
||||
}
|
||||
if (shmflg & SHM_EXEC) {
|
||||
prot |= PROT_EXEC;
|
||||
|
@ -1449,7 +1449,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
|||
goto out_nattch;
|
||||
}
|
||||
|
||||
file = alloc_file(&path, f_mode,
|
||||
file = alloc_file(&path, f_flags,
|
||||
is_file_hugepages(shp->shm_file) ?
|
||||
&shm_file_operations_huge :
|
||||
&shm_file_operations);
|
||||
|
|
|
@ -326,7 +326,7 @@ SYSCALL_DEFINE2(memfd_create,
|
|||
goto err_fd;
|
||||
}
|
||||
file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
|
||||
file->f_flags |= O_RDWR | O_LARGEFILE;
|
||||
file->f_flags |= O_LARGEFILE;
|
||||
|
||||
if (flags & MFD_ALLOW_SEALING) {
|
||||
file_seals = memfd_file_seals_ptr(file);
|
||||
|
|
|
@ -3942,8 +3942,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
|
|||
if (IS_ERR(res))
|
||||
goto put_path;
|
||||
|
||||
res = alloc_file(&path, FMODE_WRITE | FMODE_READ,
|
||||
&shmem_file_operations);
|
||||
res = alloc_file(&path, O_RDWR, &shmem_file_operations);
|
||||
if (IS_ERR(res))
|
||||
goto put_path;
|
||||
|
||||
|
|
|
@ -411,7 +411,7 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
|
|||
|
||||
d_instantiate(path.dentry, SOCK_INODE(sock));
|
||||
|
||||
file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
|
||||
file = alloc_file(&path, O_RDWR | (flags & O_NONBLOCK),
|
||||
&socket_file_ops);
|
||||
if (IS_ERR(file)) {
|
||||
/* drop dentry, keep inode for a bit */
|
||||
|
@ -423,7 +423,6 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
|
|||
}
|
||||
|
||||
sock->file = file;
|
||||
file->f_flags = O_RDWR | (flags & O_NONBLOCK);
|
||||
file->private_data = sock;
|
||||
return file;
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ static int apparmor_inode_getattr(const struct path *path)
|
|||
return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR);
|
||||
}
|
||||
|
||||
static int apparmor_file_open(struct file *file, const struct cred *cred)
|
||||
static int apparmor_file_open(struct file *file)
|
||||
{
|
||||
struct aa_file_ctx *fctx = file_ctx(file);
|
||||
struct aa_label *label;
|
||||
|
@ -414,7 +414,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred)
|
|||
return 0;
|
||||
}
|
||||
|
||||
label = aa_get_newest_cred_label(cred);
|
||||
label = aa_get_newest_cred_label(file->f_cred);
|
||||
if (!unconfined(label)) {
|
||||
struct inode *inode = file_inode(file);
|
||||
struct path_cond cond = { inode->i_uid, inode->i_mode };
|
||||
|
|
|
@ -970,11 +970,11 @@ int security_file_receive(struct file *file)
|
|||
return call_int_hook(file_receive, 0, file);
|
||||
}
|
||||
|
||||
int security_file_open(struct file *file, const struct cred *cred)
|
||||
int security_file_open(struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = call_int_hook(file_open, 0, file, cred);
|
||||
ret = call_int_hook(file_open, 0, file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -3862,7 +3862,7 @@ static int selinux_file_receive(struct file *file)
|
|||
return file_has_perm(cred, file, file_to_av(file));
|
||||
}
|
||||
|
||||
static int selinux_file_open(struct file *file, const struct cred *cred)
|
||||
static int selinux_file_open(struct file *file)
|
||||
{
|
||||
struct file_security_struct *fsec;
|
||||
struct inode_security_struct *isec;
|
||||
|
@ -3886,7 +3886,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
|
|||
* new inode label or new policy.
|
||||
* This check is not redundant - do not remove.
|
||||
*/
|
||||
return file_path_has_perm(cred, file, open_file_to_av(file));
|
||||
return file_path_has_perm(file->f_cred, file, open_file_to_av(file));
|
||||
}
|
||||
|
||||
/* task security operations */
|
||||
|
|
|
@ -1927,9 +1927,9 @@ static int smack_file_receive(struct file *file)
|
|||
*
|
||||
* Returns 0
|
||||
*/
|
||||
static int smack_file_open(struct file *file, const struct cred *cred)
|
||||
static int smack_file_open(struct file *file)
|
||||
{
|
||||
struct task_smack *tsp = cred->security;
|
||||
struct task_smack *tsp = file->f_cred->security;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct smk_audit_info ad;
|
||||
int rc;
|
||||
|
@ -1937,7 +1937,7 @@ static int smack_file_open(struct file *file, const struct cred *cred)
|
|||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
||||
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||
rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
|
||||
rc = smk_bu_credfile(cred, file, MAY_READ, rc);
|
||||
rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
|
|||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*/
|
||||
static int tomoyo_file_open(struct file *f, const struct cred *cred)
|
||||
static int tomoyo_file_open(struct file *f)
|
||||
{
|
||||
int flags = f->f_flags;
|
||||
/* Don't check read permission here if called from do_execve(). */
|
||||
|
|
Loading…
Reference in New Issue