mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 16:53:49 +00:00
sanitize struct filename and lookup flags handling in statx
and friends Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQqUNBr3gm4hGXdBJlZ7Krx/gZQ6wUCZzdpZQAKCRBZ7Krx/gZQ 6whMAQDhlGFV+nGRetwe4t60mVRpxIoc71GLC7b6V8FmyfTI5AEAkAigkJ8KCZDP mfGsN/3PtzoxnIkIqdk7Y7q4/fowyAw= =4DWZ -----END PGP SIGNATURE----- Merge tag 'pull-statx' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs Pull statx updates from Al Viro: "Sanitize struct filename and lookup flags handling in statx and friends" * tag 'pull-statx' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: libfs: kill empty_dir_getattr() fs: Simplify getattr interface function checking AT_GETATTR_NOSEC flag fs/stat.c: switch to CLASS(fd_raw) kill getname_statx_lookup_flags() io_statx_prep(): use getname_uflags()
This commit is contained in:
commit
c6d64479d6
@ -1008,14 +1008,6 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat,
|
|
||||||
u32 request_mask, unsigned int flags)
|
|
||||||
{
|
|
||||||
if (flags & AT_GETATTR_NOSEC)
|
|
||||||
return vfs_getattr_nosec(path, stat, request_mask, flags);
|
|
||||||
return vfs_getattr(path, stat, request_mask, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ecryptfs_getattr(struct mnt_idmap *idmap,
|
static int ecryptfs_getattr(struct mnt_idmap *idmap,
|
||||||
const struct path *path, struct kstat *stat,
|
const struct path *path, struct kstat *stat,
|
||||||
u32 request_mask, unsigned int flags)
|
u32 request_mask, unsigned int flags)
|
||||||
@ -1024,8 +1016,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap,
|
|||||||
struct kstat lower_stat;
|
struct kstat lower_stat;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry),
|
rc = vfs_getattr_nosec(ecryptfs_dentry_to_lower_path(dentry),
|
||||||
&lower_stat, request_mask, flags);
|
&lower_stat, request_mask, flags);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
fsstack_copy_attr_all(d_inode(dentry),
|
fsstack_copy_attr_all(d_inode(dentry),
|
||||||
ecryptfs_inode_to_lower(d_inode(dentry)));
|
ecryptfs_inode_to_lower(d_inode(dentry)));
|
||||||
|
@ -246,7 +246,6 @@ int open_namespace(struct ns_common *ns);
|
|||||||
* fs/stat.c:
|
* fs/stat.c:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int getname_statx_lookup_flags(int flags);
|
|
||||||
int do_statx(int dfd, struct filename *filename, unsigned int flags,
|
int do_statx(int dfd, struct filename *filename, unsigned int flags,
|
||||||
unsigned int mask, struct statx __user *buffer);
|
unsigned int mask, struct statx __user *buffer);
|
||||||
int do_statx_fd(int fd, unsigned int flags, unsigned int mask,
|
int do_statx_fd(int fd, unsigned int flags, unsigned int mask,
|
||||||
|
11
fs/libfs.c
11
fs/libfs.c
@ -1715,15 +1715,6 @@ static struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int empty_dir_getattr(struct mnt_idmap *idmap,
|
|
||||||
const struct path *path, struct kstat *stat,
|
|
||||||
u32 request_mask, unsigned int query_flags)
|
|
||||||
{
|
|
||||||
struct inode *inode = d_inode(path->dentry);
|
|
||||||
generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int empty_dir_setattr(struct mnt_idmap *idmap,
|
static int empty_dir_setattr(struct mnt_idmap *idmap,
|
||||||
struct dentry *dentry, struct iattr *attr)
|
struct dentry *dentry, struct iattr *attr)
|
||||||
{
|
{
|
||||||
@ -1737,9 +1728,7 @@ static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t siz
|
|||||||
|
|
||||||
static const struct inode_operations empty_dir_inode_operations = {
|
static const struct inode_operations empty_dir_inode_operations = {
|
||||||
.lookup = empty_dir_lookup,
|
.lookup = empty_dir_lookup,
|
||||||
.permission = generic_permission,
|
|
||||||
.setattr = empty_dir_setattr,
|
.setattr = empty_dir_setattr,
|
||||||
.getattr = empty_dir_getattr,
|
|
||||||
.listxattr = empty_dir_listxattr,
|
.listxattr = empty_dir_listxattr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|||||||
|
|
||||||
type = ovl_path_real(dentry, &realpath);
|
type = ovl_path_real(dentry, &realpath);
|
||||||
old_cred = ovl_override_creds(dentry->d_sb);
|
old_cred = ovl_override_creds(dentry->d_sb);
|
||||||
err = ovl_do_getattr(&realpath, stat, request_mask, flags);
|
err = vfs_getattr_nosec(&realpath, stat, request_mask, flags);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -195,8 +195,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|||||||
(!is_dir ? STATX_NLINK : 0);
|
(!is_dir ? STATX_NLINK : 0);
|
||||||
|
|
||||||
ovl_path_lower(dentry, &realpath);
|
ovl_path_lower(dentry, &realpath);
|
||||||
err = ovl_do_getattr(&realpath, &lowerstat, lowermask,
|
err = vfs_getattr_nosec(&realpath, &lowerstat, lowermask,
|
||||||
flags);
|
flags);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -248,8 +248,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
|
|||||||
|
|
||||||
ovl_path_lowerdata(dentry, &realpath);
|
ovl_path_lowerdata(dentry, &realpath);
|
||||||
if (realpath.dentry) {
|
if (realpath.dentry) {
|
||||||
err = ovl_do_getattr(&realpath, &lowerdatastat,
|
err = vfs_getattr_nosec(&realpath, &lowerdatastat,
|
||||||
lowermask, flags);
|
lowermask, flags);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
|
@ -412,14 +412,6 @@ static inline bool ovl_open_flags_need_copy_up(int flags)
|
|||||||
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
|
return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ovl_do_getattr(const struct path *path, struct kstat *stat,
|
|
||||||
u32 request_mask, unsigned int flags)
|
|
||||||
{
|
|
||||||
if (flags & AT_GETATTR_NOSEC)
|
|
||||||
return vfs_getattr_nosec(path, stat, request_mask, flags);
|
|
||||||
return vfs_getattr(path, stat, request_mask, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
int ovl_get_write_access(struct dentry *dentry);
|
int ovl_get_write_access(struct dentry *dentry);
|
||||||
void ovl_put_write_access(struct dentry *dentry);
|
void ovl_put_write_access(struct dentry *dentry);
|
||||||
|
24
fs/stat.c
24
fs/stat.c
@ -207,7 +207,7 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
|
|||||||
if (inode->i_op->getattr)
|
if (inode->i_op->getattr)
|
||||||
return inode->i_op->getattr(idmap, path, stat,
|
return inode->i_op->getattr(idmap, path, stat,
|
||||||
request_mask,
|
request_mask,
|
||||||
query_flags | AT_GETATTR_NOSEC);
|
query_flags);
|
||||||
|
|
||||||
generic_fillattr(idmap, request_mask, inode, stat);
|
generic_fillattr(idmap, request_mask, inode, stat);
|
||||||
return 0;
|
return 0;
|
||||||
@ -240,9 +240,6 @@ int vfs_getattr(const struct path *path, struct kstat *stat,
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(query_flags & AT_GETATTR_NOSEC))
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
retval = security_inode_getattr(path);
|
retval = security_inode_getattr(path);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
@ -262,18 +259,13 @@ EXPORT_SYMBOL(vfs_getattr);
|
|||||||
*/
|
*/
|
||||||
int vfs_fstat(int fd, struct kstat *stat)
|
int vfs_fstat(int fd, struct kstat *stat)
|
||||||
{
|
{
|
||||||
struct fd f;
|
CLASS(fd_raw, f)(fd);
|
||||||
int error;
|
if (fd_empty(f))
|
||||||
|
|
||||||
f = fdget_raw(fd);
|
|
||||||
if (!fd_file(f))
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
error = vfs_getattr(&fd_file(f)->f_path, stat, STATX_BASIC_STATS, 0);
|
return vfs_getattr(&fd_file(f)->f_path, stat, STATX_BASIC_STATS, 0);
|
||||||
fdput(f);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getname_statx_lookup_flags(int flags)
|
static int statx_lookup_flags(int flags)
|
||||||
{
|
{
|
||||||
int lookup_flags = 0;
|
int lookup_flags = 0;
|
||||||
|
|
||||||
@ -281,8 +273,6 @@ int getname_statx_lookup_flags(int flags)
|
|||||||
lookup_flags |= LOOKUP_FOLLOW;
|
lookup_flags |= LOOKUP_FOLLOW;
|
||||||
if (!(flags & AT_NO_AUTOMOUNT))
|
if (!(flags & AT_NO_AUTOMOUNT))
|
||||||
lookup_flags |= LOOKUP_AUTOMOUNT;
|
lookup_flags |= LOOKUP_AUTOMOUNT;
|
||||||
if (flags & AT_EMPTY_PATH)
|
|
||||||
lookup_flags |= LOOKUP_EMPTY;
|
|
||||||
|
|
||||||
return lookup_flags;
|
return lookup_flags;
|
||||||
}
|
}
|
||||||
@ -319,7 +309,7 @@ static int vfs_statx_fd(int fd, int flags, struct kstat *stat,
|
|||||||
u32 request_mask)
|
u32 request_mask)
|
||||||
{
|
{
|
||||||
CLASS(fd_raw, f)(fd);
|
CLASS(fd_raw, f)(fd);
|
||||||
if (!fd_file(f))
|
if (fd_empty(f))
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
return vfs_statx_path(&fd_file(f)->f_path, flags, stat, request_mask);
|
return vfs_statx_path(&fd_file(f)->f_path, flags, stat, request_mask);
|
||||||
}
|
}
|
||||||
@ -343,7 +333,7 @@ static int vfs_statx(int dfd, struct filename *filename, int flags,
|
|||||||
struct kstat *stat, u32 request_mask)
|
struct kstat *stat, u32 request_mask)
|
||||||
{
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
unsigned int lookup_flags = getname_statx_lookup_flags(flags);
|
unsigned int lookup_flags = statx_lookup_flags(flags);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
|
if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
|
||||||
|
@ -154,8 +154,4 @@
|
|||||||
usable with open_by_handle_at(2). */
|
usable with open_by_handle_at(2). */
|
||||||
#define AT_HANDLE_MNT_ID_UNIQUE 0x001 /* Return the u64 unique mount ID. */
|
#define AT_HANDLE_MNT_ID_UNIQUE 0x001 /* Return the u64 unique mount ID. */
|
||||||
|
|
||||||
#if defined(__KERNEL__)
|
|
||||||
#define AT_GETATTR_NOSEC 0x80000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _UAPI_LINUX_FCNTL_H */
|
#endif /* _UAPI_LINUX_FCNTL_H */
|
||||||
|
@ -36,8 +36,7 @@ int io_statx_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
|
|||||||
sx->buffer = u64_to_user_ptr(READ_ONCE(sqe->addr2));
|
sx->buffer = u64_to_user_ptr(READ_ONCE(sqe->addr2));
|
||||||
sx->flags = READ_ONCE(sqe->statx_flags);
|
sx->flags = READ_ONCE(sqe->statx_flags);
|
||||||
|
|
||||||
sx->filename = getname_flags(path,
|
sx->filename = getname_uflags(path, sx->flags);
|
||||||
getname_statx_lookup_flags(sx->flags));
|
|
||||||
|
|
||||||
if (IS_ERR(sx->filename)) {
|
if (IS_ERR(sx->filename)) {
|
||||||
int ret = PTR_ERR(sx->filename);
|
int ret = PTR_ERR(sx->filename);
|
||||||
|
Loading…
Reference in New Issue
Block a user