In case we don't support a specific file lock (that being determined by looking at fl_flags or fl_type), return an appropriate error back to userspace. Also, do some cleanup in cifs_lock() and its friends. Signed-off-by: Paulo Alcantara <palcantara@xxxxxxx> --- fs/cifs/file.c | 105 ++++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8d41ca7bfcf1..259167f32580 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1303,51 +1303,55 @@ cifs_push_locks(struct cifsFileInfo *cfile) return rc; } -static void -cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock, - bool *wait_flag, struct TCP_Server_Info *server) +static int cifs_read_flock(struct file_lock *flock, __u32 *type, bool *lock, + bool *wait_flag, struct TCP_Server_Info *server) { + unsigned int flags = FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | + FL_LEASE | FL_CLOSE; + + if (flock->fl_flags & ~flags) { + cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags); + return -EOPNOTSUPP; + } + +#ifdef CONFIG_CIFS_DEBUG2 if (flock->fl_flags & FL_POSIX) cifs_dbg(FYI, "Posix\n"); if (flock->fl_flags & FL_FLOCK) cifs_dbg(FYI, "Flock\n"); - if (flock->fl_flags & FL_SLEEP) { - cifs_dbg(FYI, "Blocking lock\n"); - *wait_flag = true; - } if (flock->fl_flags & FL_ACCESS) cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n"); if (flock->fl_flags & FL_LEASE) cifs_dbg(FYI, "Lease on file - not implemented yet\n"); - if (flock->fl_flags & - (~(FL_POSIX | FL_FLOCK | FL_SLEEP | - FL_ACCESS | FL_LEASE | FL_CLOSE))) - cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags); +#endif + if (flock->fl_flags & FL_SLEEP) { + cifs_dbg(FYI, "Blocking lock\n"); + *wait_flag = true; + } + + cifs_dbg(FYI, "Lock type: 0x%02x\n", flock->fl_type); *type = server->vals->large_lock_type; - if (flock->fl_type == F_WRLCK) { - cifs_dbg(FYI, "F_WRLCK\n"); - *type |= server->vals->exclusive_lock_type; - *lock = 1; - } else if (flock->fl_type == F_UNLCK) { - cifs_dbg(FYI, "F_UNLCK\n"); - *type |= server->vals->unlock_lock_type; - *unlock = 1; - /* Check if unlock includes more than one lock range */ - } else if (flock->fl_type == F_RDLCK) { - cifs_dbg(FYI, "F_RDLCK\n"); + + switch (flock->fl_type) { + case F_RDLCK: + case F_SHLCK: *type |= server->vals->shared_lock_type; - *lock = 1; - } else if (flock->fl_type == F_EXLCK) { - cifs_dbg(FYI, "F_EXLCK\n"); + break; + case F_WRLCK: + case F_EXLCK: *type |= server->vals->exclusive_lock_type; - *lock = 1; - } else if (flock->fl_type == F_SHLCK) { - cifs_dbg(FYI, "F_SHLCK\n"); - *type |= server->vals->shared_lock_type; - *lock = 1; - } else - cifs_dbg(FYI, "Unknown type of lock\n"); + break; + case F_UNLCK: + *type |= server->vals->unlock_lock_type; + break; + default: + cifs_dbg(FYI, "Unknown lock type\n"); + return -EINVAL; + } + + *lock = !(*type & server->vals->unlock_lock_type); + return 0; } static int @@ -1547,10 +1551,9 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, return rc; } -static int -cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, - bool wait_flag, bool posix_lck, int lock, int unlock, - unsigned int xid) +static int cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, + bool wait_flag, bool posix_lck, bool lock, + unsigned int xid) { int rc = 0; __u64 length = 1 + flock->fl_end - flock->fl_start; @@ -1571,7 +1574,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, else posix_lock_type = CIFS_WRLCK; - if (unlock == 1) + if (!lock) posix_lock_type = CIFS_UNLCK; rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, @@ -1619,8 +1622,9 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, } cifs_lock_add(cfile, lock); - } else if (unlock) + } else { rc = server->ops->mand_unlock_range(cfile, flock, xid); + } out: if (flock->fl_flags & FL_POSIX && !rc) @@ -1631,7 +1635,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, int cifs_lock(struct file *file, int cmd, struct file_lock *flock) { int rc, xid; - int lock = 0, unlock = 0; + bool lock = false; bool wait_flag = false; bool posix_lck = false; struct cifs_sb_info *cifs_sb; @@ -1651,8 +1655,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) cfile = (struct cifsFileInfo *)file->private_data; tcon = tlink_tcon(cfile->tlink); - cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, - tcon->ses->server); + rc = cifs_read_flock(flock, &type, &lock, &wait_flag, + tcon->ses->server); + if (rc) + goto out; cifs_sb = CIFS_FILE_SB(file); netfid = cfile->fid.netfid; @@ -1668,21 +1674,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock) */ if (IS_GETLK(cmd)) { rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid); - free_xid(xid); - return rc; - } - - if (!lock && !unlock) { - /* - * if no lock or unlock then nothing to do since we do not - * know what it is - */ - free_xid(xid); - return -EOPNOTSUPP; + } else { + rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, + xid); } - rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock, - xid); +out: free_xid(xid); return rc; } -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html