[PATCH RFC 01/24] filelock: push the S_ISREG check down to ->setlease handlers
From: Jeff Layton <jlayton@kernel.org>
Date: 2024-03-15 16:53:10
Also in:
linux-cifs, linux-fsdevel, linux-nfs, linux-unionfs, lkml, netfs
Subsystem:
common internet file system client (cifs and smb3), file locking (flock() and fcntl()/lockf()), filesystems (vfs and infrastructure), nfs, sunrpc, and lockd clients, the rest · Maintainers:
Steve French, Jeff Layton, Chuck Lever, Alexander Viro, Christian Brauner, Trond Myklebust, Anna Schumaker, Linus Torvalds
When nfsd starts requesting directory delegations, setlease handlers may
see requests for leases on directories. Push the !S_ISREG check down
into the non-trivial setlease handlers, so we can selectively enable
them where they're supported.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/locks.c | 5 +++--
fs/nfs/nfs4file.c | 2 ++
fs/smb/client/cifsfs.c | 3 +++
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/fs/locks.c b/fs/locks.c
index 90c8746874de..cb4b35d26162 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1925,6 +1925,9 @@ static int generic_delete_lease(struct file *filp, void *owner)
int generic_setlease(struct file *filp, int arg, struct file_lease **flp,
void **priv)
{
+ if (!S_ISREG(file_inode(filp)->i_mode))
+ return -EINVAL;
+
switch (arg) {
case F_UNLCK:
return generic_delete_lease(filp, *priv);@@ -2014,8 +2017,6 @@ vfs_setlease(struct file *filp, int arg, struct file_lease **lease, void **priv)
if ((!vfsuid_eq_kuid(vfsuid, current_fsuid())) && !capable(CAP_LEASE))
return -EACCES;
- if (!S_ISREG(inode->i_mode))
- return -EINVAL;
error = security_file_lock(filp, arg);
if (error)
return error;
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 1cd9652f3c28..b7630a437ad2 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -442,6 +442,8 @@ void nfs42_ssc_unregister_ops(void)
static int nfs4_setlease(struct file *file, int arg, struct file_lease **lease,
void **priv)
{
+ if (!S_ISREG(file_inode(file)->i_mode))
+ return -EINVAL;
return nfs4_proc_setlease(file, arg, lease, priv);
}
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index fb368b191eef..81a96fbfa3ed 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -1094,6 +1094,9 @@ cifs_setlease(struct file *file, int arg, struct file_lease **lease, void **priv
struct inode *inode = file_inode(file);
struct cifsFileInfo *cfile = file->private_data;
+ if (!S_ISREG(inode->i_mode))
+ return -EINVAL;
+
/* Check if file is oplocked if this is request for new lease */
if (arg == F_UNLCK ||
((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
--
2.44.0