85 changes: 58 additions & 27 deletions fs/file_table.c
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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:
Expand All @@ -152,35 +154,72 @@ 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;

file->f_path = *path;
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
*/
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions fs/fuse/dir.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand All @@ -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;
Expand Down
32 changes: 15 additions & 17 deletions fs/gfs2/inode.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -822,22 +822,21 @@ 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);
}

/**
* __gfs2_lookup - Look up a filename in a directory and return its inode
* @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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand All @@ -1229,28 +1228,27 @@ 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);

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;
Expand All @@ -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);
}

/*
Expand Down
54 changes: 16 additions & 38 deletions fs/hugetlbfs/inode.c
Expand Up @@ -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.
Expand All @@ -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()) {
Expand All @@ -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 */

return file;
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;

out_inode:
iput(inode);
out_dentry:
path_put(&path);
out_shm_unlock:
out:
if (*user) {
user_shm_unlock(size, *user);
*user = NULL;
Expand Down
5 changes: 2 additions & 3 deletions fs/internal.h
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
225 changes: 84 additions & 141 deletions fs/namei.c

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions fs/nfs/dir.c
Expand Up @@ -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))
Expand All @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs4_fs.h
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs4proc.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/nfsd/vfs.c
Expand Up @@ -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;
Expand Down
88 changes: 24 additions & 64 deletions fs/open.c
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -780,21 +766,24 @@ 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;

error = break_lease(locks_inode(f), f->f_flags);
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) {
error = open(inode, 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) &&
Expand All @@ -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);
Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand All @@ -896,16 +885,15 @@ 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);

if (IS_ERR(dentry))
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,
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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;
Expand Down
43 changes: 11 additions & 32 deletions fs/pipe.c
Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions include/linux/file.h
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);

Expand Down
17 changes: 9 additions & 8 deletions include/linux/fs.h
Expand Up @@ -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)

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2420,21 +2423,19 @@ 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 *);
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 */
Expand Down
4 changes: 2 additions & 2 deletions include/linux/ima.h
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/lsm_hooks.h
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions include/linux/security.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
45 changes: 21 additions & 24 deletions ipc/shm.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1447,46 +1446,44 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
goto out_unlock;
}

path = shp->shm_file->f_path;
path_get(&path);
/*
* 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
* file extends beyond that of the shm segment. It's not usually
* possible, but it can happen during remap_file_pages() emulation as
* that unmaps the memory, then does ->mmap() via file reference only.
* 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.
*/
base = get_file(shp->shm_file);
shp->shm_nattch++;
size = i_size_read(d_inode(path.dentry));
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) {
path_put(&path);
fput(base);
goto out_nattch;
}

file = alloc_file(&path, f_mode,
is_file_hugepages(shp->shm_file) ?
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);
path_put(&path);
fput(base);
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
* file extends beyond that of the shm segment. It's not usually
* possible, but it can happen during remap_file_pages() emulation as
* that unmaps the memory, then does ->mmap() via file reference only.
* 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);
sfd->file = base;
sfd->vm_ops = NULL;
file->private_data = sfd;

err = security_mmap_file(file, prot, flags);
if (err)
Expand Down
2 changes: 1 addition & 1 deletion mm/memfd.c
Expand Up @@ -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);
Expand Down
49 changes: 11 additions & 38 deletions mm/shmem.c
Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down
29 changes: 5 additions & 24 deletions net/socket.c
Expand Up @@ -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);

d_instantiate(path.dentry, SOCK_INODE(sock));
if (!dname)
dname = sock->sk ? sock->sk->sk_prot_creator->name : "";

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;
}
Expand Down
4 changes: 2 additions & 2 deletions security/apparmor/lsm.c
Expand Up @@ -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;
Expand All @@ -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 };
Expand Down
4 changes: 2 additions & 2 deletions security/integrity/ima/ima.h
Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions security/integrity/ima/ima_appraise.c
Expand Up @@ -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";
Expand All @@ -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) ||
Expand Down
16 changes: 8 additions & 8 deletions security/integrity/ima/ima_main.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

/**
Expand All @@ -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);

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions security/security.c
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions security/selinux/hooks.c
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
6 changes: 3 additions & 3 deletions security/smack/smack_lsm.c
Expand Up @@ -1927,17 +1927,17 @@ 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;

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;
}
Expand Down
2 changes: 1 addition & 1 deletion security/tomoyo/tomoyo.c
Expand Up @@ -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(). */
Expand Down