mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 10:01:39 -05:00
filelock: push the S_ISREG check down to ->setlease handlers
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. FUSE is special: It's the only filesystem that supports atomic_open and allows kernel-internal leases. atomic_open is issued when the VFS doesn't know the state of the dentry being opened. If the file doesn't exist, it may be created, in which case the dir lease should be broken. The existing kernel-internal lease implementation has no provision for this. Ensure that we don't allow directory leases by default going forward by explicitly disabling them there. Reviewed-by: NeilBrown <neil@brown.name> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-4-52f3feebb2f2@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
6976ed2dd0
commit
e6d28ebc17
@@ -2230,6 +2230,7 @@ static const struct file_operations fuse_dir_operations = {
|
||||
.fsync = fuse_dir_fsync,
|
||||
.unlocked_ioctl = fuse_dir_ioctl,
|
||||
.compat_ioctl = fuse_dir_compat_ioctl,
|
||||
.setlease = simple_nosetlease,
|
||||
};
|
||||
|
||||
static const struct inode_operations fuse_common_inode_operations = {
|
||||
|
||||
@@ -1935,6 +1935,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);
|
||||
@@ -2024,8 +2027,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;
|
||||
|
||||
@@ -431,6 +431,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1149,6 +1149,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))) ||
|
||||
|
||||
Reference in New Issue
Block a user