mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
Merge branch 'work.open3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs open-related updates from Al Viro: - "do we need fput() or put_filp()" rules are gone - it's always fput() now. We keep track of that state where it belongs - in ->f_mode. - int *opened mess killed - in finish_open(), in ->atomic_open() instances and in fs/namei.c code around do_last()/lookup_open()/atomic_open(). - alloc_file() wrappers with saner calling conventions are introduced (alloc_file_clone() and alloc_file_pseudo()); callers converted, with much simplification. - while we are at it, saner calling conventions for path_init() and link_path_walk(), simplifying things inside fs/namei.c (both on open-related paths and elsewhere). * 'work.open3' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (40 commits) few more cleanups of link_path_walk() callers allow link_path_walk() to take ERR_PTR() make path_init() unconditionally paired with terminate_walk() document alloc_file() changes make alloc_file() static do_shmat(): grab shp->shm_file earlier, switch to alloc_file_clone() new helper: alloc_file_clone() create_pipe_files(): switch the first allocation to alloc_file_pseudo() anon_inode_getfile(): switch to alloc_file_pseudo() hugetlb_file_setup(): switch to alloc_file_pseudo() ocxlflash_getfile(): switch to alloc_file_pseudo() cxl_getfile(): switch to alloc_file_pseudo() ... and switch shmem_file_setup() to alloc_file_pseudo() __shmem_file_setup(): reorder allocations new wrapper: alloc_file_pseudo() kill FILE_{CREATED,OPENED} switch atomic_open() and lookup_open() to returning 0 in all success cases document ->atomic_open() changes ->atomic_open(): return 0 in all success cases get rid of 'opened' in path_openat() and the helpers downstream ...
This commit is contained in:
commit
a66b4cd1e7
@ -64,7 +64,7 @@ prototypes:
|
||||
void (*update_time)(struct inode *, struct timespec *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *,
|
||||
struct file *, unsigned open_flag,
|
||||
umode_t create_mode, int *opened);
|
||||
umode_t create_mode);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
|
||||
locking rules:
|
||||
|
@ -602,3 +602,23 @@ in your dentry operations instead.
|
||||
dentry separately, and it now has request_mask and query_flags arguments
|
||||
to specify the fields and sync type requested by statx. Filesystems not
|
||||
supporting any statx-specific features may ignore the new arguments.
|
||||
--
|
||||
[mandatory]
|
||||
->atomic_open() calling conventions have changed. Gone is int *opened,
|
||||
along with FILE_OPENED/FILE_CREATED. In place of those we have
|
||||
FMODE_OPENED/FMODE_CREATED, set in file->f_mode. Additionally, return
|
||||
value for 'called finish_no_open(), open it yourself' case has become
|
||||
0, not 1. Since finish_no_open() itself is returning 0 now, that part
|
||||
does not need any changes in ->atomic_open() instances.
|
||||
--
|
||||
[mandatory]
|
||||
alloc_file() has become static now; two wrappers are to be used instead.
|
||||
alloc_file_pseudo(inode, vfsmount, name, flags, ops) is for the cases
|
||||
when dentry needs to be created; that's the majority of old alloc_file()
|
||||
users. Calling conventions: on success a reference to new struct file
|
||||
is returned and callers reference to inode is subsumed by that. On
|
||||
failure, ERR_PTR() is returned and no caller's references are affected,
|
||||
so the caller needs to drop the inode reference it held.
|
||||
alloc_file_clone(file, flags, ops) does not affect any caller's references.
|
||||
On success you get a new struct file sharing the mount/dentry with the
|
||||
original, on failure - ERR_PTR().
|
||||
|
@ -386,7 +386,7 @@ struct inode_operations {
|
||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||
void (*update_time)(struct inode *, struct timespec *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||
unsigned open_flag, umode_t create_mode, int *opened);
|
||||
unsigned open_flag, umode_t create_mode);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
};
|
||||
|
||||
@ -496,13 +496,15 @@ otherwise noted.
|
||||
|
||||
atomic_open: called on the last component of an open. Using this optional
|
||||
method the filesystem can look up, possibly create and open the file in
|
||||
one atomic operation. If it cannot perform this (e.g. the file type
|
||||
turned out to be wrong) it may signal this by returning 1 instead of
|
||||
usual 0 or -ve . This method is only called if the last component is
|
||||
negative or needs lookup. Cached positive dentries are still handled by
|
||||
f_op->open(). If the file was created, the FILE_CREATED flag should be
|
||||
set in "opened". In case of O_EXCL the method must only succeed if the
|
||||
file didn't exist and hence FILE_CREATED shall always be set on success.
|
||||
one atomic operation. If it wants to leave actual opening to the
|
||||
caller (e.g. if the file turned out to be a symlink, device, or just
|
||||
something filesystem won't do atomic open for), it may signal this by
|
||||
returning finish_no_open(file, dentry). This method is only called if
|
||||
the last component is negative or needs lookup. Cached positive dentries
|
||||
are still handled by f_op->open(). If the file was created,
|
||||
FMODE_CREATED flag should be set in file->f_mode. In case of O_EXCL
|
||||
the method must only succeed if the file didn't exist and hence FMODE_CREATED
|
||||
shall always be set on success.
|
||||
|
||||
tmpfile: called in the end of O_TMPFILE open(). Optional, equivalent to
|
||||
atomically creating, opening and unlinking a file in given directory.
|
||||
|
@ -553,7 +553,7 @@ 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");
|
||||
lessee_file = filp_clone_open(lessor_file);
|
||||
lessee_file = file_clone_open(lessor_file);
|
||||
if (IS_ERR(lessee_file)) {
|
||||
ret = PTR_ERR(lessee_file);
|
||||
goto out_lessee;
|
||||
|
@ -67,10 +67,8 @@ static struct file *cxl_getfile(const char *name,
|
||||
const struct file_operations *fops,
|
||||
void *priv, int flags)
|
||||
{
|
||||
struct qstr this;
|
||||
struct path path;
|
||||
struct file *file;
|
||||
struct inode *inode = NULL;
|
||||
struct inode *inode;
|
||||
int rc;
|
||||
|
||||
/* strongly inspired by anon_inode_getfile() */
|
||||
@ -91,23 +89,11 @@ static struct file *cxl_getfile(const char *name,
|
||||
goto err_fs;
|
||||
}
|
||||
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
this.name = name;
|
||||
this.len = strlen(name);
|
||||
this.hash = 0;
|
||||
path.dentry = d_alloc_pseudo(cxl_vfs_mount->mnt_sb, &this);
|
||||
if (!path.dentry)
|
||||
file = alloc_file_pseudo(inode, cxl_vfs_mount, name,
|
||||
flags & (O_ACCMODE | O_NONBLOCK), fops);
|
||||
if (IS_ERR(file))
|
||||
goto err_inode;
|
||||
|
||||
path.mnt = mntget(cxl_vfs_mount);
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
if (IS_ERR(file)) {
|
||||
path_put(&path);
|
||||
goto err_fs;
|
||||
}
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
@ -88,10 +88,8 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
|
||||
const struct file_operations *fops,
|
||||
void *priv, int flags)
|
||||
{
|
||||
struct qstr this;
|
||||
struct path path;
|
||||
struct file *file;
|
||||
struct inode *inode = NULL;
|
||||
struct inode *inode;
|
||||
int rc;
|
||||
|
||||
if (fops->owner && !try_module_get(fops->owner)) {
|
||||
@ -116,29 +114,15 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
|
||||
goto err3;
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
this.len = strlen(name);
|
||||
this.hash = 0;
|
||||
path.dentry = d_alloc_pseudo(ocxlflash_vfs_mount->mnt_sb, &this);
|
||||
if (!path.dentry) {
|
||||
dev_err(dev, "%s: d_alloc_pseudo failed\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto err4;
|
||||
}
|
||||
|
||||
path.mnt = mntget(ocxlflash_vfs_mount);
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
file = alloc_file_pseudo(inode, ocxlflash_vfs_mount, name,
|
||||
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);
|
||||
path_put(&path);
|
||||
goto err3;
|
||||
goto err4;
|
||||
}
|
||||
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
out:
|
||||
return file;
|
||||
|
@ -859,8 +859,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
|
||||
static int
|
||||
v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned flags, umode_t mode,
|
||||
int *opened)
|
||||
struct file *file, unsigned flags, umode_t mode)
|
||||
{
|
||||
int err;
|
||||
u32 perm;
|
||||
@ -917,7 +916,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
v9inode->writeback_fid = (void *) inode_fid;
|
||||
}
|
||||
mutex_unlock(&v9inode->v_mutex);
|
||||
err = finish_open(file, dentry, generic_file_open, opened);
|
||||
err = finish_open(file, dentry, generic_file_open);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
@ -925,7 +924,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
|
||||
v9fs_cache_inode_set_cookie(d_inode(dentry), file);
|
||||
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
out:
|
||||
dput(res);
|
||||
return err;
|
||||
|
@ -241,8 +241,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
|
||||
|
||||
static int
|
||||
v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned flags, umode_t omode,
|
||||
int *opened)
|
||||
struct file *file, unsigned flags, umode_t omode)
|
||||
{
|
||||
int err = 0;
|
||||
kgid_t gid;
|
||||
@ -352,13 +351,13 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
mutex_unlock(&v9inode->v_mutex);
|
||||
/* Since we are opening a file, assign the open fid to the file */
|
||||
err = finish_open(file, dentry, generic_file_open, opened);
|
||||
err = finish_open(file, dentry, generic_file_open);
|
||||
if (err)
|
||||
goto err_clunk_old_fid;
|
||||
file->private_data = ofid;
|
||||
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
|
||||
v9fs_cache_inode_set_cookie(inode, file);
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
out:
|
||||
v9fs_put_acl(dacl, pacl);
|
||||
dput(res);
|
||||
|
24
fs/aio.c
24
fs/aio.c
@ -202,9 +202,7 @@ static const struct address_space_operations aio_ctx_aops;
|
||||
|
||||
static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
|
||||
{
|
||||
struct qstr this = QSTR_INIT("[aio]", 5);
|
||||
struct file *file;
|
||||
struct path path;
|
||||
struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
|
||||
if (IS_ERR(inode))
|
||||
return ERR_CAST(inode);
|
||||
@ -213,31 +211,17 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
|
||||
inode->i_mapping->private_data = ctx;
|
||||
inode->i_size = PAGE_SIZE * nr_pages;
|
||||
|
||||
path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
|
||||
if (!path.dentry) {
|
||||
file = alloc_file_pseudo(inode, aio_mnt, "[aio]",
|
||||
O_RDWR, &aio_ring_fops);
|
||||
if (IS_ERR(file))
|
||||
iput(inode);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
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)) {
|
||||
path_put(&path);
|
||||
return file;
|
||||
}
|
||||
|
||||
file->f_flags = O_RDWR;
|
||||
return file;
|
||||
}
|
||||
|
||||
static struct dentry *aio_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
static const struct dentry_operations ops = {
|
||||
.d_dname = simple_dname,
|
||||
};
|
||||
struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops,
|
||||
struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, NULL,
|
||||
AIO_RING_MAGIC);
|
||||
|
||||
if (!IS_ERR(root))
|
||||
|
@ -71,8 +71,6 @@ struct file *anon_inode_getfile(const char *name,
|
||||
const struct file_operations *fops,
|
||||
void *priv, int flags)
|
||||
{
|
||||
struct qstr this;
|
||||
struct path path;
|
||||
struct file *file;
|
||||
|
||||
if (IS_ERR(anon_inode_inode))
|
||||
@ -81,40 +79,24 @@ struct file *anon_inode_getfile(const char *name,
|
||||
if (fops->owner && !try_module_get(fops->owner))
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
/*
|
||||
* Link the inode to a directory entry by creating a unique name
|
||||
* using the inode sequence number.
|
||||
*/
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
this.name = name;
|
||||
this.len = strlen(name);
|
||||
this.hash = 0;
|
||||
path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
|
||||
if (!path.dentry)
|
||||
goto err_module;
|
||||
|
||||
path.mnt = mntget(anon_inode_mnt);
|
||||
/*
|
||||
* We know the anon_inode inode count is always greater than zero,
|
||||
* so ihold() is safe.
|
||||
*/
|
||||
ihold(anon_inode_inode);
|
||||
|
||||
d_instantiate(path.dentry, anon_inode_inode);
|
||||
|
||||
file = alloc_file(&path, OPEN_FMODE(flags), fops);
|
||||
file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
|
||||
flags & (O_ACCMODE | O_NONBLOCK), fops);
|
||||
if (IS_ERR(file))
|
||||
goto err_dput;
|
||||
goto err;
|
||||
|
||||
file->f_mapping = anon_inode_inode->i_mapping;
|
||||
|
||||
file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
|
||||
file->private_data = priv;
|
||||
|
||||
return file;
|
||||
|
||||
err_dput:
|
||||
path_put(&path);
|
||||
err_module:
|
||||
err:
|
||||
iput(anon_inode_inode);
|
||||
module_put(fops->owner);
|
||||
return file;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ static int bad_inode_update_time(struct inode *inode, struct timespec64 *time,
|
||||
|
||||
static int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry,
|
||||
struct file *file, unsigned int open_flag,
|
||||
umode_t create_mode, int *opened)
|
||||
umode_t create_mode)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -429,8 +429,7 @@ int ceph_open(struct inode *inode, struct file *file)
|
||||
* file or symlink, return 1 so the VFS can retry.
|
||||
*/
|
||||
int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned flags, umode_t mode,
|
||||
int *opened)
|
||||
struct file *file, unsigned flags, umode_t mode)
|
||||
{
|
||||
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
|
||||
struct ceph_mds_client *mdsc = fsc->mdsc;
|
||||
@ -507,9 +506,9 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
dout("atomic_open finish_open on dn %p\n", dn);
|
||||
if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
|
||||
ceph_init_inode_acls(d_inode(dentry), &acls);
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
}
|
||||
err = finish_open(file, dentry, ceph_open, opened);
|
||||
err = finish_open(file, dentry, ceph_open);
|
||||
}
|
||||
out_req:
|
||||
if (!req->r_err && req->r_target_inode)
|
||||
|
@ -1025,8 +1025,7 @@ extern const struct file_operations ceph_file_fops;
|
||||
extern int ceph_renew_caps(struct inode *inode);
|
||||
extern int ceph_open(struct inode *inode, struct file *file);
|
||||
extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned flags, umode_t mode,
|
||||
int *opened);
|
||||
struct file *file, unsigned flags, umode_t mode);
|
||||
extern int ceph_release(struct inode *inode, struct file *filp);
|
||||
extern void ceph_fill_inline_data(struct inode *inode, struct page *locked_page,
|
||||
char *data, size_t len);
|
||||
|
@ -65,8 +65,7 @@ extern struct inode *cifs_root_iget(struct super_block *);
|
||||
extern int cifs_create(struct inode *, struct dentry *, umode_t,
|
||||
bool excl);
|
||||
extern int cifs_atomic_open(struct inode *, struct dentry *,
|
||||
struct file *, unsigned, umode_t,
|
||||
int *);
|
||||
struct file *, unsigned, umode_t);
|
||||
extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
|
||||
unsigned int);
|
||||
extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
|
||||
|
@ -465,8 +465,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
||||
|
||||
int
|
||||
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
struct file *file, unsigned oflags, umode_t mode,
|
||||
int *opened)
|
||||
struct file *file, unsigned oflags, umode_t mode)
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
@ -539,9 +538,9 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
|
||||
}
|
||||
|
||||
if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
|
||||
rc = finish_open(file, direntry, generic_file_open, opened);
|
||||
rc = finish_open(file, direntry, generic_file_open);
|
||||
if (rc) {
|
||||
if (server->ops->close)
|
||||
server->ops->close(xid, tcon, &fid);
|
||||
|
@ -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 @@ struct file *get_empty_filp(void)
|
||||
* 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,
|
||||
static 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,19 +170,56 @@ 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;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_file);
|
||||
|
||||
struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
|
||||
const char *name, int flags,
|
||||
const struct file_operations *fops)
|
||||
{
|
||||
static const struct dentry_operations anon_ops = {
|
||||
.d_dname = simple_dname
|
||||
};
|
||||
struct qstr this = QSTR_INIT(name, strlen(name));
|
||||
struct path path;
|
||||
struct file *file;
|
||||
|
||||
path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
|
||||
if (!path.dentry)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!mnt->mnt_sb->s_d_op)
|
||||
d_set_d_op(path.dentry, &anon_ops);
|
||||
path.mnt = mntget(mnt);
|
||||
d_instantiate(path.dentry, inode);
|
||||
file = alloc_file(&path, flags, fops);
|
||||
if (IS_ERR(file)) {
|
||||
ihold(inode);
|
||||
path_put(&path);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
EXPORT_SYMBOL(alloc_file_pseudo);
|
||||
|
||||
struct file *alloc_file_clone(struct file *base, int flags,
|
||||
const struct file_operations *fops)
|
||||
{
|
||||
struct file *f = alloc_file(&base->f_path, flags, fops);
|
||||
if (!IS_ERR(f)) {
|
||||
path_get(&f->f_path);
|
||||
f->f_mapping = base->f_mapping;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/* the real guts of fput() - releasing the last reference to file
|
||||
*/
|
||||
@ -190,6 +229,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 +249,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 +261,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 +339,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,
|
||||
|
@ -399,7 +399,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
|
||||
*/
|
||||
static int fuse_create_open(struct inode *dir, struct dentry *entry,
|
||||
struct file *file, unsigned flags,
|
||||
umode_t mode, int *opened)
|
||||
umode_t mode)
|
||||
{
|
||||
int err;
|
||||
struct inode *inode;
|
||||
@ -469,7 +469,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
|
||||
d_instantiate(entry, inode);
|
||||
fuse_change_entry_timeout(entry, &outentry);
|
||||
fuse_invalidate_attr(dir);
|
||||
err = finish_open(file, entry, generic_file_open, opened);
|
||||
err = finish_open(file, entry, generic_file_open);
|
||||
if (err) {
|
||||
fuse_sync_release(ff, flags);
|
||||
} else {
|
||||
@ -489,7 +489,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
|
||||
static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
|
||||
static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
|
||||
struct file *file, unsigned flags,
|
||||
umode_t mode, int *opened)
|
||||
umode_t mode)
|
||||
{
|
||||
int err;
|
||||
struct fuse_conn *fc = get_fuse_conn(dir);
|
||||
@ -508,12 +508,12 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
|
||||
goto no_open;
|
||||
|
||||
/* Only creates */
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
|
||||
if (fc->no_create)
|
||||
goto mknod;
|
||||
|
||||
err = fuse_create_open(dir, entry, file, flags, mode, opened);
|
||||
err = fuse_create_open(dir, entry, file, flags, mode);
|
||||
if (err == -ENOSYS) {
|
||||
fc->no_create = 1;
|
||||
goto mknod;
|
||||
|
@ -580,7 +580,7 @@ static int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
|
||||
static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file,
|
||||
umode_t mode, dev_t dev, const char *symname,
|
||||
unsigned int size, int excl, int *opened)
|
||||
unsigned int size, int excl)
|
||||
{
|
||||
const struct qstr *name = &dentry->d_name;
|
||||
struct posix_acl *default_acl, *acl;
|
||||
@ -626,7 +626,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
error = 0;
|
||||
if (file) {
|
||||
if (S_ISREG(inode->i_mode))
|
||||
error = finish_open(file, dentry, gfs2_open_common, opened);
|
||||
error = finish_open(file, dentry, gfs2_open_common);
|
||||
else
|
||||
error = finish_no_open(file, NULL);
|
||||
}
|
||||
@ -767,8 +767,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
mark_inode_dirty(inode);
|
||||
d_instantiate(dentry, inode);
|
||||
if (file) {
|
||||
*opened |= FILE_CREATED;
|
||||
error = finish_open(file, dentry, gfs2_open_common, opened);
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
error = finish_open(file, dentry, gfs2_open_common);
|
||||
}
|
||||
gfs2_glock_dq_uninit(ghs);
|
||||
gfs2_glock_dq_uninit(ghs + 1);
|
||||
@ -822,7 +822,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
|
||||
static int gfs2_create(struct inode *dir, struct dentry *dentry,
|
||||
umode_t mode, bool excl)
|
||||
{
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl, NULL);
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFREG | mode, 0, NULL, 0, excl);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -830,14 +830,13 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
|
||||
* @dir: The directory inode
|
||||
* @dentry: The dentry of the new inode
|
||||
* @file: File to be opened
|
||||
* @opened: atomic_open flags
|
||||
*
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
|
||||
static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, int *opened)
|
||||
struct file *file)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct dentry *d;
|
||||
@ -866,7 +865,7 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
|
||||
return d;
|
||||
}
|
||||
if (file && S_ISREG(inode->i_mode))
|
||||
error = finish_open(file, dentry, gfs2_open_common, opened);
|
||||
error = finish_open(file, dentry, gfs2_open_common);
|
||||
|
||||
gfs2_glock_dq_uninit(&gh);
|
||||
if (error) {
|
||||
@ -879,7 +878,7 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry,
|
||||
static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
|
||||
unsigned flags)
|
||||
{
|
||||
return __gfs2_lookup(dir, dentry, NULL, NULL);
|
||||
return __gfs2_lookup(dir, dentry, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1189,7 +1188,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
|
||||
if (size >= gfs2_max_stuffed_size(GFS2_I(dir)))
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0, NULL);
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1204,7 +1203,7 @@ static int gfs2_symlink(struct inode *dir, struct dentry *dentry,
|
||||
static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
unsigned dsize = gfs2_max_stuffed_size(GFS2_I(dir));
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0, NULL);
|
||||
return gfs2_create_inode(dir, dentry, NULL, S_IFDIR | mode, 0, NULL, dsize, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1219,7 +1218,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
dev_t dev)
|
||||
{
|
||||
return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0, NULL);
|
||||
return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1229,14 +1228,13 @@ static int gfs2_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
|
||||
* @file: The proposed new struct file
|
||||
* @flags: open flags
|
||||
* @mode: File mode
|
||||
* @opened: Flag to say whether the file has been opened or not
|
||||
*
|
||||
* Returns: error code or 0 for success
|
||||
*/
|
||||
|
||||
static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned flags,
|
||||
umode_t mode, int *opened)
|
||||
umode_t mode)
|
||||
{
|
||||
struct dentry *d;
|
||||
bool excl = !!(flags & O_EXCL);
|
||||
@ -1244,13 +1242,13 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
if (!d_in_lookup(dentry))
|
||||
goto skip_lookup;
|
||||
|
||||
d = __gfs2_lookup(dir, dentry, file, opened);
|
||||
d = __gfs2_lookup(dir, dentry, file);
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
if (d != NULL)
|
||||
dentry = d;
|
||||
if (d_really_is_positive(dentry)) {
|
||||
if (!(*opened & FILE_OPENED))
|
||||
if (!(file->f_mode & FMODE_OPENED))
|
||||
return finish_no_open(file, d);
|
||||
dput(d);
|
||||
return 0;
|
||||
@ -1262,7 +1260,7 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
if (!(flags & O_CREAT))
|
||||
return -ENOENT;
|
||||
|
||||
return gfs2_create_inode(dir, dentry, file, S_IFREG | mode, 0, NULL, 0, excl, opened);
|
||||
return gfs2_create_inode(dir, dentry, file, S_IFREG | mode, 0, NULL, 0, excl);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1310,10 +1310,6 @@ static int get_hstate_idx(int page_size_log)
|
||||
return h - hstates;
|
||||
}
|
||||
|
||||
static const struct dentry_operations anon_ops = {
|
||||
.d_dname = simple_dname
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that size should be aligned to proper hugepage size in caller side,
|
||||
* otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
|
||||
@ -1322,19 +1318,18 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
|
||||
vm_flags_t acctflag, struct user_struct **user,
|
||||
int creat_flags, int page_size_log)
|
||||
{
|
||||
struct file *file = ERR_PTR(-ENOMEM);
|
||||
struct inode *inode;
|
||||
struct path path;
|
||||
struct super_block *sb;
|
||||
struct qstr quick_string;
|
||||
struct vfsmount *mnt;
|
||||
int hstate_idx;
|
||||
struct file *file;
|
||||
|
||||
hstate_idx = get_hstate_idx(page_size_log);
|
||||
if (hstate_idx < 0)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
*user = NULL;
|
||||
if (!hugetlbfs_vfsmount[hstate_idx])
|
||||
mnt = hugetlbfs_vfsmount[hstate_idx];
|
||||
if (!mnt)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (creat_flags == HUGETLB_SHMFS_INODE && !can_do_hugetlb_shm()) {
|
||||
@ -1350,45 +1345,28 @@ struct file *hugetlb_file_setup(const char *name, size_t size,
|
||||
}
|
||||
}
|
||||
|
||||
sb = hugetlbfs_vfsmount[hstate_idx]->mnt_sb;
|
||||
quick_string.name = name;
|
||||
quick_string.len = strlen(quick_string.name);
|
||||
quick_string.hash = 0;
|
||||
path.dentry = d_alloc_pseudo(sb, &quick_string);
|
||||
if (!path.dentry)
|
||||
goto out_shm_unlock;
|
||||
|
||||
d_set_d_op(path.dentry, &anon_ops);
|
||||
path.mnt = mntget(hugetlbfs_vfsmount[hstate_idx]);
|
||||
file = ERR_PTR(-ENOSPC);
|
||||
inode = hugetlbfs_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0);
|
||||
inode = hugetlbfs_get_inode(mnt->mnt_sb, NULL, S_IFREG | S_IRWXUGO, 0);
|
||||
if (!inode)
|
||||
goto out_dentry;
|
||||
goto out;
|
||||
if (creat_flags == HUGETLB_SHMFS_INODE)
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
if (hugetlb_reserve_pages(inode, 0,
|
||||
size >> huge_page_shift(hstate_inode(inode)), NULL,
|
||||
acctflag))
|
||||
goto out_inode;
|
||||
|
||||
d_instantiate(path.dentry, inode);
|
||||
inode->i_size = size;
|
||||
clear_nlink(inode);
|
||||
|
||||
file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
|
||||
&hugetlbfs_file_operations);
|
||||
if (IS_ERR(file))
|
||||
goto out_dentry; /* inode is already attached */
|
||||
if (hugetlb_reserve_pages(inode, 0,
|
||||
size >> huge_page_shift(hstate_inode(inode)), NULL,
|
||||
acctflag))
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
else
|
||||
file = alloc_file_pseudo(inode, mnt, name, O_RDWR,
|
||||
&hugetlbfs_file_operations);
|
||||
if (!IS_ERR(file))
|
||||
return file;
|
||||
|
||||
return file;
|
||||
|
||||
out_inode:
|
||||
iput(inode);
|
||||
out_dentry:
|
||||
path_put(&path);
|
||||
out_shm_unlock:
|
||||
out:
|
||||
if (*user) {
|
||||
user_shm_unlock(size, *user);
|
||||
*user = NULL;
|
||||
|
@ -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,8 +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 int vfs_open(const struct path *, struct file *);
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
|
225
fs/namei.c
225
fs/namei.c
@ -2028,6 +2028,8 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (IS_ERR(name))
|
||||
return PTR_ERR(name);
|
||||
while (*name=='/')
|
||||
name++;
|
||||
if (!*name)
|
||||
@ -2125,12 +2127,15 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
||||
}
|
||||
}
|
||||
|
||||
/* must be paired with terminate_walk() */
|
||||
static const char *path_init(struct nameidata *nd, unsigned flags)
|
||||
{
|
||||
const char *s = nd->name->name;
|
||||
|
||||
if (!*s)
|
||||
flags &= ~LOOKUP_RCU;
|
||||
if (flags & LOOKUP_RCU)
|
||||
rcu_read_lock();
|
||||
|
||||
nd->last_type = LAST_ROOT; /* if there are only slashes... */
|
||||
nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
|
||||
@ -2143,7 +2148,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
|
||||
nd->path = nd->root;
|
||||
nd->inode = inode;
|
||||
if (flags & LOOKUP_RCU) {
|
||||
rcu_read_lock();
|
||||
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
||||
nd->root_seq = nd->seq;
|
||||
nd->m_seq = read_seqbegin(&mount_lock);
|
||||
@ -2159,21 +2163,15 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
|
||||
|
||||
nd->m_seq = read_seqbegin(&mount_lock);
|
||||
if (*s == '/') {
|
||||
if (flags & LOOKUP_RCU)
|
||||
rcu_read_lock();
|
||||
set_root(nd);
|
||||
if (likely(!nd_jump_root(nd)))
|
||||
return s;
|
||||
nd->root.mnt = NULL;
|
||||
rcu_read_unlock();
|
||||
return ERR_PTR(-ECHILD);
|
||||
} else if (nd->dfd == AT_FDCWD) {
|
||||
if (flags & LOOKUP_RCU) {
|
||||
struct fs_struct *fs = current->fs;
|
||||
unsigned seq;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
do {
|
||||
seq = read_seqcount_begin(&fs->seq);
|
||||
nd->path = fs->pwd;
|
||||
@ -2195,16 +2193,13 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
|
||||
|
||||
dentry = f.file->f_path.dentry;
|
||||
|
||||
if (*s) {
|
||||
if (!d_can_lookup(dentry)) {
|
||||
fdput(f);
|
||||
return ERR_PTR(-ENOTDIR);
|
||||
}
|
||||
if (*s && unlikely(!d_can_lookup(dentry))) {
|
||||
fdput(f);
|
||||
return ERR_PTR(-ENOTDIR);
|
||||
}
|
||||
|
||||
nd->path = f.file->f_path;
|
||||
if (flags & LOOKUP_RCU) {
|
||||
rcu_read_lock();
|
||||
nd->inode = nd->path.dentry->d_inode;
|
||||
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
|
||||
} else {
|
||||
@ -2272,24 +2267,15 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
|
||||
const char *s = path_init(nd, flags);
|
||||
int err;
|
||||
|
||||
if (IS_ERR(s))
|
||||
return PTR_ERR(s);
|
||||
|
||||
if (unlikely(flags & LOOKUP_DOWN)) {
|
||||
if (unlikely(flags & LOOKUP_DOWN) && !IS_ERR(s)) {
|
||||
err = handle_lookup_down(nd);
|
||||
if (unlikely(err < 0)) {
|
||||
terminate_walk(nd);
|
||||
return err;
|
||||
}
|
||||
if (unlikely(err < 0))
|
||||
s = ERR_PTR(err);
|
||||
}
|
||||
|
||||
while (!(err = link_path_walk(s, nd))
|
||||
&& ((err = lookup_last(nd)) > 0)) {
|
||||
s = trailing_symlink(nd);
|
||||
if (IS_ERR(s)) {
|
||||
err = PTR_ERR(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
err = complete_walk(nd);
|
||||
@ -2336,10 +2322,7 @@ static int path_parentat(struct nameidata *nd, unsigned flags,
|
||||
struct path *parent)
|
||||
{
|
||||
const char *s = path_init(nd, flags);
|
||||
int err;
|
||||
if (IS_ERR(s))
|
||||
return PTR_ERR(s);
|
||||
err = link_path_walk(s, nd);
|
||||
int err = link_path_walk(s, nd);
|
||||
if (!err)
|
||||
err = complete_walk(nd);
|
||||
if (!err) {
|
||||
@ -2666,15 +2649,10 @@ path_mountpoint(struct nameidata *nd, unsigned flags, struct path *path)
|
||||
{
|
||||
const char *s = path_init(nd, flags);
|
||||
int err;
|
||||
if (IS_ERR(s))
|
||||
return PTR_ERR(s);
|
||||
|
||||
while (!(err = link_path_walk(s, nd)) &&
|
||||
(err = mountpoint_last(nd)) > 0) {
|
||||
s = trailing_symlink(nd);
|
||||
if (IS_ERR(s)) {
|
||||
err = PTR_ERR(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
*path = nd->path;
|
||||
@ -3027,17 +3005,16 @@ static int may_o_create(const struct path *dir, struct dentry *dentry, umode_t m
|
||||
* Returns 0 if successful. The file will have been created and attached to
|
||||
* @file by the filesystem calling finish_open().
|
||||
*
|
||||
* Returns 1 if the file was looked up only or didn't need creating. The
|
||||
* caller will need to perform the open themselves. @path will have been
|
||||
* updated to point to the new dentry. This may be negative.
|
||||
* If the file was looked up only or didn't need creating, FMODE_OPENED won't
|
||||
* be set. The caller will need to perform the open themselves. @path will
|
||||
* have been updated to point to the new dentry. This may be negative.
|
||||
*
|
||||
* Returns an error code otherwise.
|
||||
*/
|
||||
static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
||||
struct path *path, struct file *file,
|
||||
const struct open_flags *op,
|
||||
int open_flag, umode_t mode,
|
||||
int *opened)
|
||||
int open_flag, umode_t mode)
|
||||
{
|
||||
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
|
||||
struct inode *dir = nd->path.dentry->d_inode;
|
||||
@ -3052,39 +3029,38 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
||||
file->f_path.dentry = DENTRY_NOT_SET;
|
||||
file->f_path.mnt = nd->path.mnt;
|
||||
error = dir->i_op->atomic_open(dir, dentry, file,
|
||||
open_to_namei_flags(open_flag),
|
||||
mode, opened);
|
||||
open_to_namei_flags(open_flag), mode);
|
||||
d_lookup_done(dentry);
|
||||
if (!error) {
|
||||
/*
|
||||
* We didn't have the inode before the open, so check open
|
||||
* permission here.
|
||||
*/
|
||||
int acc_mode = op->acc_mode;
|
||||
if (*opened & FILE_CREATED) {
|
||||
WARN_ON(!(open_flag & O_CREAT));
|
||||
fsnotify_create(dir, dentry);
|
||||
acc_mode = 0;
|
||||
}
|
||||
error = may_open(&file->f_path, acc_mode, open_flag);
|
||||
if (WARN_ON(error > 0))
|
||||
error = -EINVAL;
|
||||
} else if (error > 0) {
|
||||
if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
|
||||
if (file->f_mode & FMODE_OPENED) {
|
||||
/*
|
||||
* We didn't have the inode before the open, so check open
|
||||
* permission here.
|
||||
*/
|
||||
int acc_mode = op->acc_mode;
|
||||
if (file->f_mode & FMODE_CREATED) {
|
||||
WARN_ON(!(open_flag & O_CREAT));
|
||||
fsnotify_create(dir, dentry);
|
||||
acc_mode = 0;
|
||||
}
|
||||
error = may_open(&file->f_path, acc_mode, open_flag);
|
||||
if (WARN_ON(error > 0))
|
||||
error = -EINVAL;
|
||||
} else if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
|
||||
error = -EIO;
|
||||
} else {
|
||||
if (file->f_path.dentry) {
|
||||
dput(dentry);
|
||||
dentry = file->f_path.dentry;
|
||||
}
|
||||
if (*opened & FILE_CREATED)
|
||||
if (file->f_mode & FMODE_CREATED)
|
||||
fsnotify_create(dir, dentry);
|
||||
if (unlikely(d_is_negative(dentry))) {
|
||||
error = -ENOENT;
|
||||
} else {
|
||||
path->dentry = dentry;
|
||||
path->mnt = nd->path.mnt;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3095,25 +3071,22 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
|
||||
/*
|
||||
* Look up and maybe create and open the last component.
|
||||
*
|
||||
* Must be called with i_mutex held on parent.
|
||||
* Must be called with parent locked (exclusive in O_CREAT case).
|
||||
*
|
||||
* Returns 0 if the file was successfully atomically created (if necessary) and
|
||||
* opened. In this case the file will be returned attached to @file.
|
||||
* Returns 0 on success, that is, if
|
||||
* the file was successfully atomically created (if necessary) and opened, or
|
||||
* the file was not completely opened at this time, though lookups and
|
||||
* creations were performed.
|
||||
* These case are distinguished by presence of FMODE_OPENED on file->f_mode.
|
||||
* In the latter case dentry returned in @path might be negative if O_CREAT
|
||||
* hadn't been specified.
|
||||
*
|
||||
* Returns 1 if the file was not completely opened at this time, though lookups
|
||||
* and creations will have been performed and the dentry returned in @path will
|
||||
* be positive upon return if O_CREAT was specified. If O_CREAT wasn't
|
||||
* specified then a negative dentry may be returned.
|
||||
*
|
||||
* An error code is returned otherwise.
|
||||
*
|
||||
* FILE_CREATE will be set in @*opened if the dentry was created and will be
|
||||
* cleared otherwise prior to returning.
|
||||
* An error code is returned on failure.
|
||||
*/
|
||||
static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
struct file *file,
|
||||
const struct open_flags *op,
|
||||
bool got_write, int *opened)
|
||||
bool got_write)
|
||||
{
|
||||
struct dentry *dir = nd->path.dentry;
|
||||
struct inode *dir_inode = dir->d_inode;
|
||||
@ -3126,7 +3099,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
if (unlikely(IS_DEADDIR(dir_inode)))
|
||||
return -ENOENT;
|
||||
|
||||
*opened &= ~FILE_CREATED;
|
||||
file->f_mode &= ~FMODE_CREATED;
|
||||
dentry = d_lookup(dir, &nd->last);
|
||||
for (;;) {
|
||||
if (!dentry) {
|
||||
@ -3188,7 +3161,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
|
||||
if (dir_inode->i_op->atomic_open) {
|
||||
error = atomic_open(nd, dentry, path, file, op, open_flag,
|
||||
mode, opened);
|
||||
mode);
|
||||
if (unlikely(error == -ENOENT) && create_error)
|
||||
error = create_error;
|
||||
return error;
|
||||
@ -3211,7 +3184,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
|
||||
/* Negative dentry, just create the file */
|
||||
if (!dentry->d_inode && (open_flag & O_CREAT)) {
|
||||
*opened |= FILE_CREATED;
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
|
||||
if (!dir_inode->i_op->create) {
|
||||
error = -EACCES;
|
||||
@ -3230,7 +3203,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
out_no_open:
|
||||
path->dentry = dentry;
|
||||
path->mnt = nd->path.mnt;
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
out_dput:
|
||||
dput(dentry);
|
||||
@ -3241,8 +3214,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
||||
* Handle the last step of open()
|
||||
*/
|
||||
static int do_last(struct nameidata *nd,
|
||||
struct file *file, const struct open_flags *op,
|
||||
int *opened)
|
||||
struct file *file, const struct open_flags *op)
|
||||
{
|
||||
struct dentry *dir = nd->path.dentry;
|
||||
int open_flag = op->open_flag;
|
||||
@ -3308,17 +3280,17 @@ static int do_last(struct nameidata *nd,
|
||||
inode_lock(dir->d_inode);
|
||||
else
|
||||
inode_lock_shared(dir->d_inode);
|
||||
error = lookup_open(nd, &path, file, op, got_write, opened);
|
||||
error = lookup_open(nd, &path, file, op, got_write);
|
||||
if (open_flag & O_CREAT)
|
||||
inode_unlock(dir->d_inode);
|
||||
else
|
||||
inode_unlock_shared(dir->d_inode);
|
||||
|
||||
if (error <= 0) {
|
||||
if (error)
|
||||
goto out;
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if ((*opened & FILE_CREATED) ||
|
||||
if (file->f_mode & FMODE_OPENED) {
|
||||
if ((file->f_mode & FMODE_CREATED) ||
|
||||
!S_ISREG(file_inode(file)->i_mode))
|
||||
will_truncate = false;
|
||||
|
||||
@ -3326,7 +3298,7 @@ static int do_last(struct nameidata *nd,
|
||||
goto opened;
|
||||
}
|
||||
|
||||
if (*opened & FILE_CREATED) {
|
||||
if (file->f_mode & FMODE_CREATED) {
|
||||
/* Don't check for write permission, don't truncate */
|
||||
open_flag &= ~O_TRUNC;
|
||||
will_truncate = false;
|
||||
@ -3395,20 +3367,15 @@ static int do_last(struct nameidata *nd,
|
||||
error = may_open(&nd->path, acc_mode, open_flag);
|
||||
if (error)
|
||||
goto out;
|
||||
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
|
||||
error = vfs_open(&nd->path, file, current_cred());
|
||||
BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
|
||||
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);
|
||||
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;
|
||||
@ -3458,7 +3425,7 @@ EXPORT_SYMBOL(vfs_tmpfile);
|
||||
|
||||
static int do_tmpfile(struct nameidata *nd, unsigned flags,
|
||||
const struct open_flags *op,
|
||||
struct file *file, int *opened)
|
||||
struct file *file)
|
||||
{
|
||||
struct dentry *child;
|
||||
struct path path;
|
||||
@ -3480,12 +3447,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
|
||||
if (error)
|
||||
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);
|
||||
error = finish_open(file, child, NULL);
|
||||
out2:
|
||||
mnt_drop_write(path.mnt);
|
||||
out:
|
||||
@ -3499,7 +3461,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;
|
||||
@ -3508,59 +3470,40 @@ static int do_o_path(struct nameidata *nd, unsigned flags, struct file *file)
|
||||
static struct file *path_openat(struct nameidata *nd,
|
||||
const struct open_flags *op, unsigned flags)
|
||||
{
|
||||
const char *s;
|
||||
struct file *file;
|
||||
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;
|
||||
}
|
||||
|
||||
if (unlikely(file->f_flags & O_PATH)) {
|
||||
error = do_tmpfile(nd, flags, op, file);
|
||||
} else if (unlikely(file->f_flags & O_PATH)) {
|
||||
error = do_o_path(nd, flags, file);
|
||||
if (!error)
|
||||
opened |= FILE_OPENED;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
s = path_init(nd, flags);
|
||||
if (IS_ERR(s)) {
|
||||
put_filp(file);
|
||||
return ERR_CAST(s);
|
||||
}
|
||||
while (!(error = link_path_walk(s, nd)) &&
|
||||
(error = do_last(nd, file, op, &opened)) > 0) {
|
||||
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
|
||||
s = trailing_symlink(nd);
|
||||
if (IS_ERR(s)) {
|
||||
error = PTR_ERR(s);
|
||||
break;
|
||||
} else {
|
||||
const char *s = path_init(nd, flags);
|
||||
while (!(error = link_path_walk(s, nd)) &&
|
||||
(error = do_last(nd, file, op)) > 0) {
|
||||
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
|
||||
s = trailing_symlink(nd);
|
||||
}
|
||||
terminate_walk(nd);
|
||||
}
|
||||
terminate_walk(nd);
|
||||
out2:
|
||||
if (!(opened & FILE_OPENED)) {
|
||||
BUG_ON(!error);
|
||||
put_filp(file);
|
||||
if (likely(!error)) {
|
||||
if (likely(file->f_mode & FMODE_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,
|
||||
|
14
fs/nfs/dir.c
14
fs/nfs/dir.c
@ -1434,12 +1434,11 @@ static int do_open(struct inode *inode, struct file *filp)
|
||||
|
||||
static int nfs_finish_open(struct nfs_open_context *ctx,
|
||||
struct dentry *dentry,
|
||||
struct file *file, unsigned open_flags,
|
||||
int *opened)
|
||||
struct file *file, unsigned open_flags)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = finish_open(file, dentry, do_open, opened);
|
||||
err = finish_open(file, dentry, do_open);
|
||||
if (err)
|
||||
goto out;
|
||||
if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
||||
@ -1452,7 +1451,7 @@ static int nfs_finish_open(struct nfs_open_context *ctx,
|
||||
|
||||
int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct file *file, unsigned open_flags,
|
||||
umode_t mode, int *opened)
|
||||
umode_t mode)
|
||||
{
|
||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
|
||||
struct nfs_open_context *ctx;
|
||||
@ -1461,6 +1460,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode;
|
||||
unsigned int lookup_flags = 0;
|
||||
bool switched = false;
|
||||
int created = 0;
|
||||
int err;
|
||||
|
||||
/* Expect a negative dentry */
|
||||
@ -1521,7 +1521,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
goto out;
|
||||
|
||||
trace_nfs_atomic_open_enter(dir, ctx, open_flags);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened);
|
||||
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, &created);
|
||||
if (created)
|
||||
file->f_mode |= FMODE_CREATED;
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
|
||||
@ -1546,7 +1548,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened);
|
||||
err = nfs_finish_open(ctx, ctx->dentry, file, open_flags);
|
||||
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
|
||||
put_nfs_open_context(ctx);
|
||||
out:
|
||||
|
@ -258,7 +258,7 @@ extern const struct dentry_operations nfs4_dentry_operations;
|
||||
|
||||
/* dir.c */
|
||||
int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
|
||||
unsigned, umode_t, int *);
|
||||
unsigned, umode_t);
|
||||
|
||||
/* super.c */
|
||||
extern struct file_system_type nfs4_fs_type;
|
||||
|
@ -2951,7 +2951,7 @@ static int _nfs4_do_open(struct inode *dir,
|
||||
}
|
||||
}
|
||||
if (opened && opendata->file_created)
|
||||
*opened |= FILE_CREATED;
|
||||
*opened = 1;
|
||||
|
||||
if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) {
|
||||
*ctx_th = opendata->f_attr.mdsthreshold;
|
||||
|
@ -763,7 +763,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
|
||||
goto out_nfserr;
|
||||
}
|
||||
|
||||
host_err = ima_file_check(file, may_flags, 0);
|
||||
host_err = ima_file_check(file, may_flags);
|
||||
if (host_err) {
|
||||
fput(file);
|
||||
goto out_nfserr;
|
||||
|
88
fs/open.c
88
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);
|
||||
@ -847,19 +843,12 @@ static int do_dentry_open(struct file *f,
|
||||
* Returns zero on success or -errno if the open failed.
|
||||
*/
|
||||
int finish_open(struct file *file, struct dentry *dentry,
|
||||
int (*open)(struct inode *, struct file *),
|
||||
int *opened)
|
||||
int (*open)(struct inode *, struct file *))
|
||||
{
|
||||
int error;
|
||||
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
|
||||
BUG_ON(file->f_mode & FMODE_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());
|
||||
if (!error)
|
||||
*opened |= FILE_OPENED;
|
||||
|
||||
return error;
|
||||
return do_dentry_open(file, d_backing_inode(dentry), open);
|
||||
}
|
||||
EXPORT_SYMBOL(finish_open);
|
||||
|
||||
@ -874,13 +863,13 @@ EXPORT_SYMBOL(finish_open);
|
||||
* NB: unlike finish_open() this function does consume the dentry reference and
|
||||
* the caller need not dput() it.
|
||||
*
|
||||
* Returns "1" which must be the return value of ->atomic_open() after having
|
||||
* Returns "0" which must be the return value of ->atomic_open() after having
|
||||
* called this function.
|
||||
*/
|
||||
int finish_no_open(struct file *file, struct dentry *dentry)
|
||||
{
|
||||
file->f_path.dentry = dentry;
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(finish_no_open);
|
||||
|
||||
@ -896,8 +885,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 +893,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 +907,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);
|
||||
}
|
||||
}
|
||||
@ -1063,26 +1043,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;
|
||||
|
43
fs/pipe.c
43
fs/pipe.c
@ -741,54 +741,33 @@ static struct inode * get_pipe_inode(void)
|
||||
|
||||
int create_pipe_files(struct file **res, int flags)
|
||||
{
|
||||
int err;
|
||||
struct inode *inode = get_pipe_inode();
|
||||
struct file *f;
|
||||
struct path path;
|
||||
|
||||
if (!inode)
|
||||
return -ENFILE;
|
||||
|
||||
err = -ENOMEM;
|
||||
path.dentry = d_alloc_pseudo(pipe_mnt->mnt_sb, &empty_name);
|
||||
if (!path.dentry)
|
||||
goto err_inode;
|
||||
path.mnt = mntget(pipe_mnt);
|
||||
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
||||
f = alloc_file(&path, FMODE_WRITE, &pipefifo_fops);
|
||||
f = alloc_file_pseudo(inode, pipe_mnt, "",
|
||||
O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT)),
|
||||
&pipefifo_fops);
|
||||
if (IS_ERR(f)) {
|
||||
err = PTR_ERR(f);
|
||||
goto err_dentry;
|
||||
free_pipe_info(inode->i_pipe);
|
||||
iput(inode);
|
||||
return PTR_ERR(f);
|
||||
}
|
||||
|
||||
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_clone(f, 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);
|
||||
return err;
|
||||
|
||||
err_inode:
|
||||
free_pipe_info(inode->i_pipe);
|
||||
iput(inode);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __do_pipe_flags(int *fd, struct file **files, int flags)
|
||||
|
@ -17,9 +17,12 @@ extern void fput(struct file *);
|
||||
struct file_operations;
|
||||
struct vfsmount;
|
||||
struct dentry;
|
||||
struct inode;
|
||||
struct path;
|
||||
extern struct file *alloc_file(const struct path *, fmode_t mode,
|
||||
const struct file_operations *fop);
|
||||
extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
|
||||
const char *, int flags, const struct file_operations *);
|
||||
extern struct file *alloc_file_clone(struct file *, int flags,
|
||||
const struct file_operations *);
|
||||
|
||||
static inline void fput_light(struct file *file, int fput_needed)
|
||||
{
|
||||
@ -78,7 +81,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,9 @@ 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)
|
||||
#define FMODE_CREATED ((__force fmode_t)0x100000)
|
||||
|
||||
/* File was opened by fanotify and shouldn't generate fanotify events */
|
||||
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
|
||||
|
||||
@ -1776,7 +1779,7 @@ struct inode_operations {
|
||||
int (*update_time)(struct inode *, struct timespec64 *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *,
|
||||
struct file *, unsigned open_flag,
|
||||
umode_t create_mode, int *opened);
|
||||
umode_t create_mode);
|
||||
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
|
||||
int (*set_acl)(struct inode *, struct posix_acl *, int);
|
||||
} ____cacheline_aligned;
|
||||
@ -2420,7 +2423,10 @@ 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 *filp_clone_open(struct file *);
|
||||
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 *);
|
||||
@ -2428,13 +2434,8 @@ extern struct filename *getname(const char __user *);
|
||||
extern struct filename *getname_kernel(const char *);
|
||||
extern void putname(struct filename *name);
|
||||
|
||||
enum {
|
||||
FILE_CREATED = 1,
|
||||
FILE_OPENED = 2
|
||||
};
|
||||
extern int finish_open(struct file *file, struct dentry *dentry,
|
||||
int (*open)(struct inode *, struct file *),
|
||||
int *opened);
|
||||
int (*open)(struct inode *, struct file *));
|
||||
extern int finish_no_open(struct file *file, struct dentry *dentry);
|
||||
|
||||
/* fs/ioctl.c */
|
||||
|
@ -16,7 +16,7 @@ struct linux_binprm;
|
||||
|
||||
#ifdef CONFIG_IMA
|
||||
extern int ima_bprm_check(struct linux_binprm *bprm);
|
||||
extern int ima_file_check(struct file *file, int mask, int opened);
|
||||
extern int ima_file_check(struct file *file, int mask);
|
||||
extern void ima_file_free(struct file *file);
|
||||
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
||||
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
|
||||
@ -34,7 +34,7 @@ static inline int ima_bprm_check(struct linux_binprm *bprm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ima_file_check(struct file *file, int mask, int opened)
|
||||
static inline int ima_file_check(struct file *file, int mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
67
ipc/shm.c
67
ipc/shm.c
@ -1366,15 +1366,14 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
||||
struct shmid_kernel *shp;
|
||||
unsigned long addr = (unsigned long)shmaddr;
|
||||
unsigned long size;
|
||||
struct file *file;
|
||||
struct file *file, *base;
|
||||
int err;
|
||||
unsigned long flags = MAP_SHARED;
|
||||
unsigned long prot;
|
||||
int acc_mode;
|
||||
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;
|
||||
@ -1407,11 +1406,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;
|
||||
@ -1447,35 +1446,6 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
path = shp->shm_file->f_path;
|
||||
path_get(&path);
|
||||
shp->shm_nattch++;
|
||||
size = i_size_read(d_inode(path.dentry));
|
||||
ipc_unlock_object(&shp->shm_perm);
|
||||
rcu_read_unlock();
|
||||
|
||||
err = -ENOMEM;
|
||||
sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
|
||||
if (!sfd) {
|
||||
path_put(&path);
|
||||
goto out_nattch;
|
||||
}
|
||||
|
||||
file = alloc_file(&path, f_mode,
|
||||
is_file_hugepages(shp->shm_file) ?
|
||||
&shm_file_operations_huge :
|
||||
&shm_file_operations);
|
||||
err = PTR_ERR(file);
|
||||
if (IS_ERR(file)) {
|
||||
kfree(sfd);
|
||||
path_put(&path);
|
||||
goto out_nattch;
|
||||
}
|
||||
|
||||
file->private_data = sfd;
|
||||
file->f_mapping = shp->shm_file->f_mapping;
|
||||
sfd->id = shp->shm_perm.id;
|
||||
sfd->ns = get_ipc_ns(ns);
|
||||
/*
|
||||
* We need to take a reference to the real shm file to prevent the
|
||||
* pointer from becoming stale in cases where the lifetime of the outer
|
||||
@ -1485,8 +1455,35 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
|
||||
* We'll deny the ->mmap() if the shm segment was since removed, but to
|
||||
* detect shm ID reuse we need to compare the file pointers.
|
||||
*/
|
||||
sfd->file = get_file(shp->shm_file);
|
||||
base = get_file(shp->shm_file);
|
||||
shp->shm_nattch++;
|
||||
size = i_size_read(file_inode(base));
|
||||
ipc_unlock_object(&shp->shm_perm);
|
||||
rcu_read_unlock();
|
||||
|
||||
err = -ENOMEM;
|
||||
sfd = kzalloc(sizeof(*sfd), GFP_KERNEL);
|
||||
if (!sfd) {
|
||||
fput(base);
|
||||
goto out_nattch;
|
||||
}
|
||||
|
||||
file = alloc_file_clone(base, f_flags,
|
||||
is_file_hugepages(base) ?
|
||||
&shm_file_operations_huge :
|
||||
&shm_file_operations);
|
||||
err = PTR_ERR(file);
|
||||
if (IS_ERR(file)) {
|
||||
kfree(sfd);
|
||||
fput(base);
|
||||
goto out_nattch;
|
||||
}
|
||||
|
||||
sfd->id = shp->shm_perm.id;
|
||||
sfd->ns = get_ipc_ns(ns);
|
||||
sfd->file = base;
|
||||
sfd->vm_ops = NULL;
|
||||
file->private_data = sfd;
|
||||
|
||||
err = security_mmap_file(file, prot, flags);
|
||||
if (err)
|
||||
|
@ -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);
|
||||
|
49
mm/shmem.c
49
mm/shmem.c
@ -3897,18 +3897,11 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range);
|
||||
|
||||
/* common code */
|
||||
|
||||
static const struct dentry_operations anon_ops = {
|
||||
.d_dname = simple_dname
|
||||
};
|
||||
|
||||
static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, loff_t size,
|
||||
unsigned long flags, unsigned int i_flags)
|
||||
{
|
||||
struct file *res;
|
||||
struct inode *inode;
|
||||
struct path path;
|
||||
struct super_block *sb;
|
||||
struct qstr this;
|
||||
struct file *res;
|
||||
|
||||
if (IS_ERR(mnt))
|
||||
return ERR_CAST(mnt);
|
||||
@ -3919,41 +3912,21 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
|
||||
if (shmem_acct_size(flags, size))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
res = ERR_PTR(-ENOMEM);
|
||||
this.name = name;
|
||||
this.len = strlen(name);
|
||||
this.hash = 0; /* will go */
|
||||
sb = mnt->mnt_sb;
|
||||
path.mnt = mntget(mnt);
|
||||
path.dentry = d_alloc_pseudo(sb, &this);
|
||||
if (!path.dentry)
|
||||
goto put_memory;
|
||||
d_set_d_op(path.dentry, &anon_ops);
|
||||
|
||||
res = ERR_PTR(-ENOSPC);
|
||||
inode = shmem_get_inode(sb, NULL, S_IFREG | 0777, 0, flags);
|
||||
if (!inode)
|
||||
goto put_memory;
|
||||
|
||||
inode = shmem_get_inode(mnt->mnt_sb, NULL, S_IFREG | S_IRWXUGO, 0,
|
||||
flags);
|
||||
if (unlikely(!inode)) {
|
||||
shmem_unacct_size(flags, size);
|
||||
return ERR_PTR(-ENOSPC);
|
||||
}
|
||||
inode->i_flags |= i_flags;
|
||||
d_instantiate(path.dentry, inode);
|
||||
inode->i_size = size;
|
||||
clear_nlink(inode); /* It is unlinked */
|
||||
res = ERR_PTR(ramfs_nommu_expand_for_mapping(inode, size));
|
||||
if (!IS_ERR(res))
|
||||
res = alloc_file_pseudo(inode, mnt, name, O_RDWR,
|
||||
&shmem_file_operations);
|
||||
if (IS_ERR(res))
|
||||
goto put_path;
|
||||
|
||||
res = alloc_file(&path, FMODE_WRITE | FMODE_READ,
|
||||
&shmem_file_operations);
|
||||
if (IS_ERR(res))
|
||||
goto put_path;
|
||||
|
||||
return res;
|
||||
|
||||
put_memory:
|
||||
shmem_unacct_size(flags, size);
|
||||
put_path:
|
||||
path_put(&path);
|
||||
iput(inode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
29
net/socket.c
29
net/socket.c
@ -388,39 +388,20 @@ static struct file_system_type sock_fs_type = {
|
||||
|
||||
struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
|
||||
{
|
||||
struct qstr name = { .name = "" };
|
||||
struct path path;
|
||||
struct file *file;
|
||||
|
||||
if (dname) {
|
||||
name.name = dname;
|
||||
name.len = strlen(name.name);
|
||||
} else if (sock->sk) {
|
||||
name.name = sock->sk->sk_prot_creator->name;
|
||||
name.len = strlen(name.name);
|
||||
}
|
||||
path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
|
||||
if (unlikely(!path.dentry)) {
|
||||
sock_release(sock);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
path.mnt = mntget(sock_mnt);
|
||||
if (!dname)
|
||||
dname = sock->sk ? sock->sk->sk_prot_creator->name : "";
|
||||
|
||||
d_instantiate(path.dentry, SOCK_INODE(sock));
|
||||
|
||||
file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
|
||||
&socket_file_ops);
|
||||
file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
|
||||
O_RDWR | (flags & O_NONBLOCK),
|
||||
&socket_file_ops);
|
||||
if (IS_ERR(file)) {
|
||||
/* drop dentry, keep inode for a bit */
|
||||
ihold(d_inode(path.dentry));
|
||||
path_put(&path);
|
||||
/* ... and now kill it properly */
|
||||
sock_release(sock);
|
||||
return file;
|
||||
}
|
||||
|
||||
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 };
|
||||
|
@ -238,7 +238,7 @@ int ima_appraise_measurement(enum ima_hooks func,
|
||||
struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, int opened);
|
||||
int xattr_len);
|
||||
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
|
||||
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
|
||||
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
|
||||
@ -254,7 +254,7 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
|
||||
struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, int opened)
|
||||
int xattr_len)
|
||||
{
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ int ima_appraise_measurement(enum ima_hooks func,
|
||||
struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, int opened)
|
||||
int xattr_len)
|
||||
{
|
||||
static const char op[] = "appraise_data";
|
||||
const char *cause = "unknown";
|
||||
@ -231,7 +231,7 @@ int ima_appraise_measurement(enum ima_hooks func,
|
||||
cause = iint->flags & IMA_DIGSIG_REQUIRED ?
|
||||
"IMA-signature-required" : "missing-hash";
|
||||
status = INTEGRITY_NOLABEL;
|
||||
if (opened & FILE_CREATED)
|
||||
if (file->f_mode & FMODE_CREATED)
|
||||
iint->flags |= IMA_NEW_FILE;
|
||||
if ((iint->flags & IMA_NEW_FILE) &&
|
||||
(!(iint->flags & IMA_DIGSIG_REQUIRED) ||
|
||||
|
@ -168,7 +168,7 @@ void ima_file_free(struct file *file)
|
||||
|
||||
static int process_measurement(struct file *file, const struct cred *cred,
|
||||
u32 secid, char *buf, loff_t size, int mask,
|
||||
enum ima_hooks func, int opened)
|
||||
enum ima_hooks func)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
struct integrity_iint_cache *iint = NULL;
|
||||
@ -294,7 +294,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
||||
if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
|
||||
inode_lock(inode);
|
||||
rc = ima_appraise_measurement(func, iint, file, pathname,
|
||||
xattr_value, xattr_len, opened);
|
||||
xattr_value, xattr_len);
|
||||
inode_unlock(inode);
|
||||
}
|
||||
if (action & IMA_AUDIT)
|
||||
@ -338,7 +338,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
|
||||
if (file && (prot & PROT_EXEC)) {
|
||||
security_task_getsecid(current, &secid);
|
||||
return process_measurement(file, current_cred(), secid, NULL,
|
||||
0, MAY_EXEC, MMAP_CHECK, 0);
|
||||
0, MAY_EXEC, MMAP_CHECK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -364,13 +364,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
|
||||
|
||||
security_task_getsecid(current, &secid);
|
||||
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
|
||||
MAY_EXEC, BPRM_CHECK, 0);
|
||||
MAY_EXEC, BPRM_CHECK);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
security_cred_getsecid(bprm->cred, &secid);
|
||||
return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
|
||||
MAY_EXEC, CREDS_CHECK, 0);
|
||||
MAY_EXEC, CREDS_CHECK);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,14 +383,14 @@ int ima_bprm_check(struct linux_binprm *bprm)
|
||||
* On success return 0. On integrity appraisal error, assuming the file
|
||||
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
||||
*/
|
||||
int ima_file_check(struct file *file, int mask, int opened)
|
||||
int ima_file_check(struct file *file, int mask)
|
||||
{
|
||||
u32 secid;
|
||||
|
||||
security_task_getsecid(current, &secid);
|
||||
return process_measurement(file, current_cred(), secid, NULL, 0,
|
||||
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
|
||||
MAY_APPEND), FILE_CHECK, opened);
|
||||
MAY_APPEND), FILE_CHECK);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ima_file_check);
|
||||
|
||||
@ -493,7 +493,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
||||
func = read_idmap[read_id] ?: FILE_CHECK;
|
||||
security_task_getsecid(current, &secid);
|
||||
return process_measurement(file, current_cred(), secid, buf, size,
|
||||
MAY_READ, func, 0);
|
||||
MAY_READ, func);
|
||||
}
|
||||
|
||||
static int __init init_ima(void)
|
||||
|
@ -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
Block a user