diff --git a/fs/bpf_fs_kfuncs.c b/fs/bpf_fs_kfuncs.c index 1e36a12b88f7..5ace2511fec5 100644 --- a/fs/bpf_fs_kfuncs.c +++ b/fs/bpf_fs_kfuncs.c @@ -79,7 +79,7 @@ __bpf_kfunc void bpf_put_file(struct file *file) * pathname in *buf*, including the NUL termination character. On error, a * negative integer is returned. */ -__bpf_kfunc int bpf_path_d_path(struct path *path, char *buf, size_t buf__sz) +__bpf_kfunc int bpf_path_d_path(const struct path *path, char *buf, size_t buf__sz) { int len; char *ret; diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 69133ec1fac2..f3f79c67add5 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -114,26 +114,21 @@ static int create_link(struct config_item *parent_item, } -static int get_target(const char *symname, struct path *path, - struct config_item **target, struct super_block *sb) +static int get_target(const char *symname, struct config_item **target, + struct super_block *sb) { + struct path path __free(path_put) = {}; int ret; - ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path); - if (!ret) { - if (path->dentry->d_sb == sb) { - *target = configfs_get_config_item(path->dentry); - if (!*target) { - ret = -ENOENT; - path_put(path); - } - } else { - ret = -EPERM; - path_put(path); - } - } - - return ret; + ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path); + if (ret) + return ret; + if (path.dentry->d_sb != sb) + return -EPERM; + *target = configfs_get_config_item(path.dentry); + if (!*target) + return -ENOENT; + return 0; } @@ -141,7 +136,6 @@ int configfs_symlink(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, const char *symname) { int ret; - struct path path; struct configfs_dirent *sd; struct config_item *parent_item; struct config_item *target_item = NULL; @@ -188,7 +182,7 @@ int configfs_symlink(struct mnt_idmap *idmap, struct inode *dir, * AV, a thoroughly annoyed bastard. */ inode_unlock(dir); - ret = get_target(symname, &path, &target_item, dentry->d_sb); + ret = get_target(symname, &target_item, dentry->d_sb); inode_lock(dir); if (ret) goto out_put; @@ -210,7 +204,6 @@ int configfs_symlink(struct mnt_idmap *idmap, struct inode *dir, } config_item_put(target_item); - path_put(&path); out_put: config_item_put(parent_item); diff --git a/fs/file_table.c b/fs/file_table.c index 81c72576e548..b223d873e48b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -54,7 +54,7 @@ struct backing_file { #define backing_file(f) container_of(f, struct backing_file, file) -struct path *backing_file_user_path(const struct file *f) +const struct path *backing_file_user_path(const struct file *f) { return &backing_file(f)->user_path; } @@ -171,7 +171,7 @@ static int init_file(struct file *f, int flags, const struct cred *cred) * the respective member when opening the file. */ mutex_init(&f->f_pos_lock); - memset(&f->f_path, 0, sizeof(f->f_path)); + memset(&f->__f_path, 0, sizeof(f->f_path)); memset(&f->f_ra, 0, sizeof(f->f_ra)); f->f_flags = flags; @@ -319,7 +319,7 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred) static void file_init_path(struct file *file, const struct path *path, const struct file_operations *fop) { - file->f_path = *path; + 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); diff --git a/fs/internal.h b/fs/internal.h index b5c62abefff4..9b2b4d116880 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -53,7 +53,7 @@ extern int finish_clean_context(struct fs_context *fc); * namei.c */ extern int filename_lookup(int dfd, struct filename *name, unsigned flags, - struct path *path, struct path *root); + struct path *path, const struct path *root); int do_rmdir(int dfd, struct filename *name); int do_unlinkat(int dfd, struct filename *name); int may_linkat(struct mnt_idmap *idmap, const struct path *link); diff --git a/fs/namei.c b/fs/namei.c index 507ca0d7878d..7377020a2cba 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2695,7 +2695,7 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path } int filename_lookup(int dfd, struct filename *name, unsigned flags, - struct path *path, struct path *root) + struct path *path, const struct path *root) { int retval; struct nameidata nd; @@ -3651,8 +3651,8 @@ static struct dentry *atomic_open(struct nameidata *nd, struct dentry *dentry, if (nd->flags & LOOKUP_DIRECTORY) open_flag |= O_DIRECTORY; - file->f_path.dentry = DENTRY_NOT_SET; - file->f_path.mnt = nd->path.mnt; + 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); d_lookup_done(dentry); @@ -4020,8 +4020,8 @@ int vfs_tmpfile(struct mnt_idmap *idmap, child = d_alloc(parentpath->dentry, &slash_name); if (unlikely(!child)) return -ENOMEM; - file->f_path.mnt = parentpath->mnt; - file->f_path.dentry = child; + file->__f_path.mnt = parentpath->mnt; + file->__f_path.dentry = child; mode = vfs_prepare_mode(idmap, dir, mode, mode, mode); error = dir->i_op->tmpfile(idmap, dir, file, mode); dput(child); @@ -4256,7 +4256,7 @@ struct dentry *start_creating_path(int dfd, const char *pathname, } EXPORT_SYMBOL(start_creating_path); -void end_creating_path(struct path *path, struct dentry *dentry) +void end_creating_path(const struct path *path, struct dentry *dentry) { if (!IS_ERR(dentry)) dput(dentry); diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index b575f0e6c7c8..2c0455e91571 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -676,7 +676,7 @@ nfs_set_local_verifier(struct inode *inode, } /* Factored out from fs/nfsd/vfs.h:fh_getattr() */ -static int __vfs_getattr(struct path *p, struct kstat *stat, int version) +static int __vfs_getattr(const struct path *p, struct kstat *stat, int version) { u32 request_mask = STATX_BASIC_STATS; diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index cadfc2bae60e..caa695c06efb 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -402,7 +402,7 @@ static struct svc_export *svc_export_update(struct svc_export *new, struct svc_export *old); static struct svc_export *svc_export_lookup(struct svc_export *); -static int check_export(struct path *path, int *flags, unsigned char *uuid) +static int check_export(const struct path *path, int *flags, unsigned char *uuid) { struct inode *inode = d_inode(path->dentry); @@ -1181,7 +1181,7 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, * use exp_get_by_name() or exp_find(). */ struct svc_export * -rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) +rqst_exp_get_by_name(struct svc_rqst *rqstp, const struct path *path) { struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h index b9c0adb3ce09..cb36e6cce829 100644 --- a/fs/nfsd/export.h +++ b/fs/nfsd/export.h @@ -111,7 +111,7 @@ int nfsd_export_init(struct net *); void nfsd_export_shutdown(struct net *); void nfsd_export_flush(struct net *); struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, - struct path *); + const struct path *); struct svc_export * rqst_exp_parent(struct svc_rqst *, struct path *); struct svc_export * rqst_find_fsidzero_export(struct svc_rqst *); diff --git a/fs/nsfs.c b/fs/nsfs.c index e7fd8a790aaa..648dc59bef7f 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -571,7 +571,7 @@ static int nsfs_export_permission(struct handle_to_path_ctx *ctx, return 0; } -static struct file *nsfs_export_open(struct path *path, unsigned int oflags) +static struct file *nsfs_export_open(const struct path *path, unsigned int oflags) { return file_open_root(path, "", oflags, 0); } diff --git a/fs/open.c b/fs/open.c index 4890b13461c7..3d64372ecc67 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1022,8 +1022,8 @@ static int do_dentry_open(struct file *f, put_file_access(f); cleanup_file: path_put(&f->f_path); - f->f_path.mnt = NULL; - f->f_path.dentry = NULL; + f->__f_path.mnt = NULL; + f->__f_path.dentry = NULL; f->f_inode = NULL; return error; } @@ -1050,7 +1050,7 @@ int finish_open(struct file *file, struct dentry *dentry, { BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */ - file->f_path.dentry = dentry; + file->__f_path.dentry = dentry; return do_dentry_open(file, open); } EXPORT_SYMBOL(finish_open); @@ -1073,7 +1073,7 @@ int finish_no_open(struct file *file, struct dentry *dentry) { if (IS_ERR(dentry)) return PTR_ERR(dentry); - file->f_path.dentry = dentry; + file->__f_path.dentry = dentry; return 0; } EXPORT_SYMBOL(finish_no_open); @@ -1093,7 +1093,7 @@ int vfs_open(const struct path *path, struct file *file) { int ret; - file->f_path = *path; + file->__f_path = *path; ret = do_dentry_open(file, NULL); if (!ret) { /* diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 66bd43a99d2e..aac7e34f56c1 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -242,7 +242,7 @@ static int ovl_verify_area(loff_t pos, loff_t pos2, loff_t len, loff_t totlen) return 0; } -static int ovl_sync_file(struct path *path) +static int ovl_sync_file(const struct path *path) { struct file *new_file; int err; diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index f5b8877d5fe2..fc52c796061d 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -120,7 +120,7 @@ static bool ovl_is_real_file(const struct file *realfile, } static struct file *ovl_real_file_path(const struct file *file, - struct path *realpath) + const struct path *realpath) { struct ovl_file *of = file->private_data; struct file *realfile = of->realfile; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 6fd4fbfb0908..c8fd5951fc5e 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -562,11 +562,11 @@ int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d, struct ovl_metacopy *metacopy); bool ovl_is_metacopy_dentry(struct dentry *dentry); char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding); -int ovl_ensure_verity_loaded(struct path *path); +int ovl_ensure_verity_loaded(const struct path *path); int ovl_validate_verity(struct ovl_fs *ofs, - struct path *metapath, - struct path *datapath); -int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src, + const struct path *metapath, + const struct path *datapath); +int ovl_get_verity_digest(struct ovl_fs *ofs, const struct path *src, struct ovl_metacopy *metacopy); int ovl_sync_status(struct ovl_fs *ofs); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 34875c46dbe2..43ee4c7296a7 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -404,7 +404,7 @@ static int ovl_check_namelen(const struct path *path, struct ovl_fs *ofs, return err; } -static int ovl_lower_dir(const char *name, struct path *path, +static int ovl_lower_dir(const char *name, const struct path *path, struct ovl_fs *ofs, int *stack_depth) { int fh_type; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index bec4a39d1b97..f76672f2e686 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -1381,7 +1381,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int pa } /* Call with mounter creds as it may open the file */ -int ovl_ensure_verity_loaded(struct path *datapath) +int ovl_ensure_verity_loaded(const struct path *datapath) { struct inode *inode = d_inode(datapath->dentry); struct file *filp; @@ -1401,8 +1401,8 @@ int ovl_ensure_verity_loaded(struct path *datapath) } int ovl_validate_verity(struct ovl_fs *ofs, - struct path *metapath, - struct path *datapath) + const struct path *metapath, + const struct path *datapath) { struct ovl_metacopy metacopy_data; u8 actual_digest[FS_VERITY_MAX_DIGEST_SIZE]; @@ -1455,7 +1455,7 @@ int ovl_validate_verity(struct ovl_fs *ofs, return 0; } -int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src, +int ovl_get_verity_digest(struct ovl_fs *ofs, const struct path *src, struct ovl_metacopy *metacopy) { int err, digest_size; diff --git a/fs/pidfs.c b/fs/pidfs.c index 44a95cd27377..0ef5b47d796a 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -850,7 +850,7 @@ static int pidfs_export_permission(struct handle_to_path_ctx *ctx, return 0; } -static struct file *pidfs_export_open(struct path *path, unsigned int oflags) +static struct file *pidfs_export_open(const struct path *path, unsigned int oflags) { /* * Clear O_LARGEFILE as open_by_handle_at() forces it and raise diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index c96e5d934ba9..891ed2dc2b73 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -73,7 +73,7 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf, { struct qstr last; struct filename *filename __free(putname) = NULL; - struct path *root_share_path = &share_conf->vfs_path; + const struct path *root_share_path = &share_conf->vfs_path; int err, type; struct dentry *d; @@ -1306,7 +1306,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath, caseless, true); } -void ksmbd_vfs_kern_path_unlock(struct path *path) +void ksmbd_vfs_kern_path_unlock(const struct path *path) { /* While lock is still held, ->d_parent is safe */ inode_unlock(d_inode(path->dentry->d_parent)); @@ -1867,7 +1867,7 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock) } int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, - struct path *path) + const struct path *path) { struct posix_acl_state acl_state; struct posix_acl *acls; @@ -1920,7 +1920,7 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, } int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap, - struct path *path, struct inode *parent_inode) + const struct path *path, struct inode *parent_inode) { struct posix_acl *acls; struct posix_acl_entry *pace; diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h index d47472f3e30b..df6421b4590b 100644 --- a/fs/smb/server/vfs.h +++ b/fs/smb/server/vfs.h @@ -123,7 +123,7 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name, int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, unsigned int flags, struct path *path, bool caseless); -void ksmbd_vfs_kern_path_unlock(struct path *path); +void ksmbd_vfs_kern_path_unlock(const struct path *path); struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work, const char *name, unsigned int flags, @@ -164,8 +164,8 @@ int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, struct dentry *dentry, struct xattr_dos_attrib *da); int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, - struct path *path); + const struct path *path); int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap, - struct path *path, + const struct path *path, struct inode *parent_inode); #endif /* __KSMBD_VFS_H__ */ diff --git a/fs/stat.c b/fs/stat.c index f95c1dc3eaa4..6c79661e1b96 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -293,7 +293,7 @@ static int statx_lookup_flags(int flags) return lookup_flags; } -static int vfs_statx_path(struct path *path, int flags, struct kstat *stat, +static int vfs_statx_path(const struct path *path, int flags, struct kstat *stat, u32 request_mask) { int error = vfs_getattr(path, stat, request_mask, flags); diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 3aac58a520c7..d0cf10d5e0f7 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -276,7 +276,7 @@ struct export_operations { int (*commit_blocks)(struct inode *inode, struct iomap *iomaps, int nr_iomaps, struct iattr *iattr); int (*permission)(struct handle_to_path_ctx *ctx, unsigned int oflags); - struct file * (*open)(struct path *path, unsigned int oflags); + struct file * (*open)(const struct path *path, unsigned int oflags); #define EXPORT_OP_NOWCC (0x1) /* don't collect v3 wcc data */ #define EXPORT_OP_NOSUBTREECHK (0x2) /* no subtree checking */ #define EXPORT_OP_CLOSE_BEFORE_UNLINK (0x4) /* close files before unlink */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 1f4a1c570a2a..540004970ad5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1192,6 +1192,8 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index) * @f_cred: stashed credentials of creator/opener * @f_owner: file owner * @f_path: path of the file + * @__f_path: writable alias for @f_path; *ONLY* for core VFS and only before + * the file gets open * @f_pos_lock: lock protecting file position * @f_pipe: specific to pipes * @f_pos: file position @@ -1217,7 +1219,10 @@ struct file { const struct cred *f_cred; struct fown_struct *f_owner; /* --- cacheline 1 boundary (64 bytes) --- */ - struct path f_path; + union { + const struct path f_path; + struct path __f_path; + }; union { /* regular files (with FMODE_ATOMIC_POS) and directories */ struct mutex f_pos_lock; @@ -2877,7 +2882,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags, const struct cred *cred); struct file *dentry_create(const struct path *path, int flags, umode_t mode, const struct cred *cred); -struct path *backing_file_user_path(const struct file *f); +const struct path *backing_file_user_path(const struct file *f); /* * When mmapping a file on a stackable filesystem (e.g., overlayfs), the file diff --git a/include/linux/namei.h b/include/linux/namei.h index a7800ef04e76..fed86221c69c 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -61,10 +61,10 @@ struct dentry *kern_path_parent(const char *name, struct path *parent); extern struct dentry *start_creating_path(int, const char *, struct path *, unsigned int); extern struct dentry *start_creating_user_path(int, const char __user *, struct path *, unsigned int); -extern void end_creating_path(struct path *, struct dentry *); +extern void end_creating_path(const struct path *, struct dentry *); extern struct dentry *start_removing_path(const char *, struct path *); extern struct dentry *start_removing_user_path_at(int , const char __user *, struct path *); -static inline void end_removing_path(struct path *path , struct dentry *dentry) +static inline void end_removing_path(const struct path *path , struct dentry *dentry) { end_creating_path(path, dentry); } diff --git a/kernel/acct.c b/kernel/acct.c index 6520baa13669..61630110e29d 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -44,19 +44,14 @@ * a struct file opened for write. Fixed. 2/6/2000, AV. */ -#include #include #include #include -#include #include -#include -#include +#include #include -#include #include -#include -#include +#include #include #include @@ -217,84 +212,70 @@ static void close_work(struct work_struct *work) complete(&acct->done); } -static int acct_on(struct filename *pathname) +DEFINE_FREE(fput_sync, struct file *, if (!IS_ERR_OR_NULL(_T)) __fput_sync(_T)) +static int acct_on(const char __user *name) { - struct file *file; - struct vfsmount *mnt, *internal; + /* Difference from BSD - they don't do O_APPEND */ + const int open_flags = O_WRONLY|O_APPEND|O_LARGEFILE; struct pid_namespace *ns = task_active_pid_ns(current); + struct filename *pathname __free(putname) = getname(name); + struct file *original_file __free(fput) = NULL; // in that order + struct path internal __free(path_put) = {}; // in that order + struct file *file __free(fput_sync) = NULL; // in that order struct bsd_acct_struct *acct; + struct vfsmount *mnt; struct fs_pin *old; - int err; + + if (IS_ERR(pathname)) + return PTR_ERR(pathname); + original_file = file_open_name(pathname, open_flags, 0); + if (IS_ERR(original_file)) + return PTR_ERR(original_file); + + mnt = mnt_clone_internal(&original_file->f_path); + if (IS_ERR(mnt)) + return PTR_ERR(mnt); + + internal.mnt = mnt; + internal.dentry = dget(mnt->mnt_root); + + file = dentry_open(&internal, open_flags, current_cred()); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (!S_ISREG(file_inode(file)->i_mode)) + return -EACCES; + + /* Exclude kernel kernel internal filesystems. */ + if (file_inode(file)->i_sb->s_flags & (SB_NOUSER | SB_KERNMOUNT)) + return -EINVAL; + + /* Exclude procfs and sysfs. */ + if (file_inode(file)->i_sb->s_iflags & SB_I_USERNS_VISIBLE) + return -EINVAL; + + if (!(file->f_mode & FMODE_CAN_WRITE)) + return -EIO; acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); if (!acct) return -ENOMEM; - /* Difference from BSD - they don't do O_APPEND */ - file = file_open_name(pathname, O_WRONLY|O_APPEND|O_LARGEFILE, 0); - if (IS_ERR(file)) { - kfree(acct); - return PTR_ERR(file); - } - - if (!S_ISREG(file_inode(file)->i_mode)) { - kfree(acct); - filp_close(file, NULL); - return -EACCES; - } - - /* Exclude kernel kernel internal filesystems. */ - if (file_inode(file)->i_sb->s_flags & (SB_NOUSER | SB_KERNMOUNT)) { - kfree(acct); - filp_close(file, NULL); - return -EINVAL; - } - - /* Exclude procfs and sysfs. */ - if (file_inode(file)->i_sb->s_iflags & SB_I_USERNS_VISIBLE) { - kfree(acct); - filp_close(file, NULL); - return -EINVAL; - } - - if (!(file->f_mode & FMODE_CAN_WRITE)) { - kfree(acct); - filp_close(file, NULL); - return -EIO; - } - internal = mnt_clone_internal(&file->f_path); - if (IS_ERR(internal)) { - kfree(acct); - filp_close(file, NULL); - return PTR_ERR(internal); - } - err = mnt_get_write_access(internal); - if (err) { - mntput(internal); - kfree(acct); - filp_close(file, NULL); - return err; - } - mnt = file->f_path.mnt; - file->f_path.mnt = internal; - atomic_long_set(&acct->count, 1); init_fs_pin(&acct->pin, acct_pin_kill); - acct->file = file; + acct->file = no_free_ptr(file); acct->needcheck = jiffies; acct->ns = ns; mutex_init(&acct->lock); INIT_WORK(&acct->work, close_work); init_completion(&acct->done); mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ - pin_insert(&acct->pin, mnt); + pin_insert(&acct->pin, original_file->f_path.mnt); rcu_read_lock(); old = xchg(&ns->bacct, &acct->pin); mutex_unlock(&acct->lock); pin_kill(old); - mnt_put_write_access(mnt); - mntput(mnt); return 0; } @@ -319,14 +300,9 @@ SYSCALL_DEFINE1(acct, const char __user *, name) return -EPERM; if (name) { - struct filename *tmp = getname(name); - - if (IS_ERR(tmp)) - return PTR_ERR(tmp); mutex_lock(&acct_on_mutex); - error = acct_on(tmp); + error = acct_on(name); mutex_unlock(&acct_on_mutex); - putname(tmp); } else { rcu_read_lock(); pin_kill(task_active_pid_ns(current)->bacct); diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 8f23f5273bab..4f87c16d915a 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -899,7 +899,7 @@ const struct bpf_func_proto bpf_send_signal_thread_proto = { .arg1_type = ARG_ANYTHING, }; -BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz) +BPF_CALL_3(bpf_d_path, const struct path *, path, char *, buf, u32, sz) { struct path copy; long len; diff --git a/security/apparmor/af_unix.c b/security/apparmor/af_unix.c index 9129766d1e9c..ac0f4be791ec 100644 --- a/security/apparmor/af_unix.c +++ b/security/apparmor/af_unix.c @@ -31,7 +31,7 @@ static inline struct sock *aa_unix_sk(struct unix_sock *u) } static int unix_fs_perm(const char *op, u32 mask, const struct cred *subj_cred, - struct aa_label *label, struct path *path) + struct aa_label *label, const struct path *path) { AA_BUG(!label); AA_BUG(!path); @@ -224,7 +224,7 @@ static int profile_create_perm(struct aa_profile *profile, int family, static int profile_sk_perm(struct aa_profile *profile, struct apparmor_audit_data *ad, - u32 request, struct sock *sk, struct path *path) + u32 request, struct sock *sk, const struct path *path) { struct aa_ruleset *rules = profile->label.rules[0]; struct aa_perms *p = NULL; @@ -386,9 +386,9 @@ static int profile_opt_perm(struct aa_profile *profile, u32 request, /* null peer_label is allowed, in which case the peer_sk label is used */ static int profile_peer_perm(struct aa_profile *profile, u32 request, - struct sock *sk, struct path *path, + struct sock *sk, const struct path *path, struct sockaddr_un *peer_addr, - int peer_addrlen, struct path *peer_path, + int peer_addrlen, const struct path *peer_path, struct aa_label *peer_label, struct apparmor_audit_data *ad) { @@ -445,7 +445,7 @@ int aa_unix_create_perm(struct aa_label *label, int family, int type, static int aa_unix_label_sk_perm(const struct cred *subj_cred, struct aa_label *label, const char *op, u32 request, struct sock *sk, - struct path *path) + const struct path *path) { if (!unconfined(label)) { struct aa_profile *profile; @@ -599,9 +599,9 @@ int aa_unix_opt_perm(const char *op, u32 request, struct socket *sock, static int unix_peer_perm(const struct cred *subj_cred, struct aa_label *label, const char *op, u32 request, - struct sock *sk, struct path *path, + struct sock *sk, const struct path *path, struct sockaddr_un *peer_addr, int peer_addrlen, - struct path *peer_path, struct aa_label *peer_label) + const struct path *peer_path, struct aa_label *peer_label) { struct aa_profile *profile; DEFINE_AUDIT_SK(ad, op, subj_cred, sk); diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h index d89eda3fd8a3..2cd9165c7348 100644 --- a/tools/testing/selftests/bpf/bpf_experimental.h +++ b/tools/testing/selftests/bpf/bpf_experimental.h @@ -219,7 +219,7 @@ extern void bpf_put_file(struct file *file) __ksym; * including the NULL termination character, stored in the supplied * buffer. On error, a negative integer is returned. */ -extern int bpf_path_d_path(struct path *path, char *buf, size_t buf__sz) __ksym; +extern int bpf_path_d_path(const struct path *path, char *buf, size_t buf__sz) __ksym; /* This macro must be used to mark the exception callback corresponding to the * main program. For example: