* rewrite file locking compat syscalls
@ 2017-05-15 20:33 Christoph Hellwig
2017-05-15 20:33 ` [PATCH 1/2] fs/locks: pass kernel struct flock to fcntl_getlk/setlk Christoph Hellwig
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Christoph Hellwig @ 2017-05-15 20:33 UTC (permalink / raw)
To: jlayton, bfields; +Cc: linux-fsdevel
Export proper lowlevel helper and use them from the compat code instead
of playing set_fs games.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] fs/locks: pass kernel struct flock to fcntl_getlk/setlk
2017-05-15 20:33 rewrite file locking compat syscalls Christoph Hellwig
@ 2017-05-15 20:33 ` Christoph Hellwig
2017-05-15 20:33 ` [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64 Christoph Hellwig
2017-05-16 10:08 ` rewrite file locking compat syscalls Jeff Layton
2 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2017-05-15 20:33 UTC (permalink / raw)
To: jlayton, bfields; +Cc: linux-fsdevel
This will make it easier to implement a sane compat fcntl syscall.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/fcntl.c | 26 ++++++++++++++----
fs/locks.c | 77 +++++++++++++++---------------------------------------
include/linux/fs.h | 8 +++---
3 files changed, 46 insertions(+), 65 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index f4e7267d117f..671ac43c65df 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -246,6 +246,8 @@ static int f_getowner_uids(struct file *filp, unsigned long arg)
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
struct file *filp)
{
+ void __user *argp = (void __user *)arg;
+ struct flock flock;
long err = -EINVAL;
switch (cmd) {
@@ -273,7 +275,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
case F_OFD_GETLK:
#endif
case F_GETLK:
- err = fcntl_getlk(filp, cmd, (struct flock __user *) arg);
+ if (copy_from_user(&flock, argp, sizeof(flock)))
+ return -EFAULT;
+ err = fcntl_getlk(filp, cmd, &flock);
+ if (!err && copy_to_user(argp, &flock, sizeof(flock)))
+ return -EFAULT;
break;
#if BITS_PER_LONG != 32
/* 32-bit arches must use fcntl64() */
@@ -283,7 +289,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
/* Fallthrough */
case F_SETLK:
case F_SETLKW:
- err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg);
+ if (copy_from_user(&flock, argp, sizeof(flock)))
+ return -EFAULT;
+ err = fcntl_setlk(fd, filp, cmd, &flock);
break;
case F_GETOWN:
/*
@@ -384,6 +392,7 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
unsigned long, arg)
{
struct fd f = fdget_raw(fd);
+ struct flock64 flock;
long err = -EBADF;
if (!f.file)
@@ -401,14 +410,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
switch (cmd) {
case F_GETLK64:
case F_OFD_GETLK:
- err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg);
+ err = -EFAULT;
+ if (copy_from_user(&flock, argp, sizeof(flock)))
+ break;
+ err = fcntl_getlk64(filp, cmd, &flock);
+ if (!err && copy_to_user(argp, &flock, sizeof(flock)))
+ err = -EFAULT;
break;
case F_SETLK64:
case F_SETLKW64:
case F_OFD_SETLK:
case F_OFD_SETLKW:
- err = fcntl_setlk64(fd, f.file, cmd,
- (struct flock64 __user *) arg);
+ err = -EFAULT;
+ if (copy_from_user(&flock, argp, sizeof(flock)))
+ break;
+ err = fcntl_setlk64(fd, f.file, cmd, &flock);
break;
default:
err = do_fcntl(fd, cmd, arg, f.file);
diff --git a/fs/locks.c b/fs/locks.c
index af2031a1fcff..054f6fb7641e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2086,26 +2086,22 @@ static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
/* Report the first existing lock that would conflict with l.
* This implements the F_GETLK command of fcntl().
*/
-int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
+int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock)
{
struct file_lock file_lock;
- struct flock flock;
int error;
- error = -EFAULT;
- if (copy_from_user(&flock, l, sizeof(flock)))
- goto out;
error = -EINVAL;
- if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
+ if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK)
goto out;
- error = flock_to_posix_lock(filp, &file_lock, &flock);
+ error = flock_to_posix_lock(filp, &file_lock, flock);
if (error)
goto out;
if (cmd == F_OFD_GETLK) {
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_GETLK;
@@ -2117,15 +2113,12 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
if (error)
goto out;
- flock.l_type = file_lock.fl_type;
+ flock->l_type = file_lock.fl_type;
if (file_lock.fl_type != F_UNLCK) {
- error = posix_lock_to_flock(&flock, &file_lock);
+ error = posix_lock_to_flock(flock, &file_lock);
if (error)
goto rel_priv;
}
- error = -EFAULT;
- if (!copy_to_user(l, &flock, sizeof(flock)))
- error = 0;
rel_priv:
locks_release_private(&file_lock);
out:
@@ -2218,26 +2211,16 @@ check_fmode_for_setlk(struct file_lock *fl)
* This implements both the F_SETLK and F_SETLKW commands of fcntl().
*/
int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
- struct flock __user *l)
+ struct flock *flock)
{
struct file_lock *file_lock = locks_alloc_lock();
- struct flock flock;
- struct inode *inode;
+ struct inode *inode = locks_inode(filp);
struct file *f;
int error;
if (file_lock == NULL)
return -ENOLCK;
- inode = locks_inode(filp);
-
- /*
- * This might block, so we do it before checking the inode.
- */
- error = -EFAULT;
- if (copy_from_user(&flock, l, sizeof(flock)))
- goto out;
-
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
*/
@@ -2246,7 +2229,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
goto out;
}
- error = flock_to_posix_lock(filp, file_lock, &flock);
+ error = flock_to_posix_lock(filp, file_lock, flock);
if (error)
goto out;
@@ -2261,7 +2244,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
switch (cmd) {
case F_OFD_SETLK:
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_SETLK;
@@ -2270,7 +2253,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
break;
case F_OFD_SETLKW:
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_SETLKW;
@@ -2315,26 +2298,22 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
/* Report the first existing lock that would conflict with l.
* This implements the F_GETLK command of fcntl().
*/
-int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
+int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock)
{
struct file_lock file_lock;
- struct flock64 flock;
int error;
- error = -EFAULT;
- if (copy_from_user(&flock, l, sizeof(flock)))
- goto out;
error = -EINVAL;
- if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
+ if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK)
goto out;
- error = flock64_to_posix_lock(filp, &file_lock, &flock);
+ error = flock64_to_posix_lock(filp, &file_lock, flock);
if (error)
goto out;
if (cmd == F_OFD_GETLK) {
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_GETLK64;
@@ -2348,11 +2327,7 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
flock.l_type = file_lock.fl_type;
if (file_lock.fl_type != F_UNLCK)
- posix_lock_to_flock64(&flock, &file_lock);
-
- error = -EFAULT;
- if (!copy_to_user(l, &flock, sizeof(flock)))
- error = 0;
+ posix_lock_to_flock64(flock, &file_lock);
locks_release_private(&file_lock);
out:
@@ -2363,26 +2338,16 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
* This implements both the F_SETLK and F_SETLKW commands of fcntl().
*/
int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
- struct flock64 __user *l)
+ struct flock64 *flock)
{
struct file_lock *file_lock = locks_alloc_lock();
- struct flock64 flock;
- struct inode *inode;
+ struct inode *inode = locks_inode(filp);
struct file *f;
int error;
if (file_lock == NULL)
return -ENOLCK;
- /*
- * This might block, so we do it before checking the inode.
- */
- error = -EFAULT;
- if (copy_from_user(&flock, l, sizeof(flock)))
- goto out;
-
- inode = locks_inode(filp);
-
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
*/
@@ -2391,7 +2356,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
goto out;
}
- error = flock64_to_posix_lock(filp, file_lock, &flock);
+ error = flock64_to_posix_lock(filp, file_lock, flock);
if (error)
goto out;
@@ -2406,7 +2371,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
switch (cmd) {
case F_OFD_SETLK:
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_SETLK64;
@@ -2415,7 +2380,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
break;
case F_OFD_SETLKW:
error = -EINVAL;
- if (flock.l_pid != 0)
+ if (flock->l_pid != 0)
goto out;
cmd = F_SETLKW64;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 803e5a9b2654..aa4affb38c39 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1038,14 +1038,14 @@ static inline struct inode *locks_inode(const struct file *f)
}
#ifdef CONFIG_FILE_LOCKING
-extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
+extern int fcntl_getlk(struct file *, unsigned int, struct flock *);
extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
- struct flock __user *);
+ struct flock *);
#if BITS_PER_LONG == 32
-extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *);
+extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 *);
extern int fcntl_setlk64(unsigned int, struct file *, unsigned int,
- struct flock64 __user *);
+ struct flock64 *);
#endif
extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg);
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64
2017-05-15 20:33 rewrite file locking compat syscalls Christoph Hellwig
2017-05-15 20:33 ` [PATCH 1/2] fs/locks: pass kernel struct flock to fcntl_getlk/setlk Christoph Hellwig
@ 2017-05-15 20:33 ` Christoph Hellwig
2017-05-16 10:46 ` Jeff Layton
2017-05-16 10:08 ` rewrite file locking compat syscalls Jeff Layton
2 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2017-05-15 20:33 UTC (permalink / raw)
To: jlayton, bfields; +Cc: linux-fsdevel
Instead write a proper compat syscall that calls common helpers.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/fcntl.c | 118 +++++++++++++++++++++++++++++++++++--------------------------
fs/locks.c | 2 +-
2 files changed, 68 insertions(+), 52 deletions(-)
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 671ac43c65df..9d909b029063 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -505,76 +505,92 @@ convert_fcntl_cmd(unsigned int cmd)
return cmd;
}
+/*
+ * GETLK was successful and we need to return the data, but it needs to fit in
+ * the compat structure.
+ * l_start shouldn't be too big, unless the original start + end is greater than
+ * COMPAT_OFF_T_MAX, in which case the app was asking for trouble, so we return
+ * -EOVERFLOW in that case. l_len could be too big, in which case we just
+ * truncate it, and only allow the app to see that part of the conflicting lock
+ * that might make sense to it anyway
+ */
+static int fixup_compat_flock(struct flock *flock)
+{
+ if (flock.l_start > COMPAT_OFF_T_MAX)
+ return -EOVERFLOW;
+ if (flock.l_len > COMPAT_OFF_T_MAX)
+ flock.l_len = COMPAT_OFF_T_MAX;
+ return 0;
+}
+
COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
compat_ulong_t, arg)
{
- mm_segment_t old_fs;
- struct flock f;
- long ret;
- unsigned int conv_cmd;
+ struct fd f = fdget_raw(fd);
+ struct flock flock;
+ long err = -EBADF;
+
+ if (!f.file)
+ return err;
+
+ if (unlikely(f.file->f_mode & FMODE_PATH)) {
+ if (!check_fcntl_cmd(cmd))
+ goto out_put;
+ }
+
+ err = security_file_fcntl(f.file, cmd, arg);
+ if (err)
+ goto out_put;
switch (cmd) {
case F_GETLK:
+ err = get_compat_flock(&flock, compat_ptr(arg));
+ if (err)
+ break;
+ err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
+ if (err)
+ break;
+ err = fixup_compat_flock(&flock);
+ if (err)
+ return err;
+ err = put_compat_flock(&flock, compat_ptr(arg));
+ break;
+ case F_GETLK64:
+ case F_OFD_GETLK:
+ err = get_compat_flock64(&flock, compat_ptr(arg));
+ if (err)
+ break;
+ err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
+ if (err)
+ break;
+ err = fixup_compat_flock(&flock);
+ if (err)
+ return err;
+ err = put_compat_flock64(&flock, compat_ptr(arg));
+ break;
case F_SETLK:
case F_SETLKW:
- ret = get_compat_flock(&f, compat_ptr(arg));
- if (ret != 0)
+ err = get_compat_flock(&flock, compat_ptr(arg));
+ if (err)
break;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_fcntl(fd, cmd, (unsigned long)&f);
- set_fs(old_fs);
- if (cmd == F_GETLK && ret == 0) {
- /* GETLK was successful and we need to return the data...
- * but it needs to fit in the compat structure.
- * l_start shouldn't be too big, unless the original
- * start + end is greater than COMPAT_OFF_T_MAX, in which
- * case the app was asking for trouble, so we return
- * -EOVERFLOW in that case.
- * l_len could be too big, in which case we just truncate it,
- * and only allow the app to see that part of the conflicting
- * lock that might make sense to it anyway
- */
-
- if (f.l_start > COMPAT_OFF_T_MAX)
- ret = -EOVERFLOW;
- if (f.l_len > COMPAT_OFF_T_MAX)
- f.l_len = COMPAT_OFF_T_MAX;
- if (ret == 0)
- ret = put_compat_flock(&f, compat_ptr(arg));
- }
+ err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
break;
-
- case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
- case F_OFD_GETLK:
case F_OFD_SETLK:
case F_OFD_SETLKW:
- ret = get_compat_flock64(&f, compat_ptr(arg));
- if (ret != 0)
+ err = get_compat_flock64(&flock, compat_ptr(arg));
+ if (err)
break;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- conv_cmd = convert_fcntl_cmd(cmd);
- ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
- set_fs(old_fs);
- if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
- /* need to return lock information - see above for commentary */
- if (f.l_start > COMPAT_LOFF_T_MAX)
- ret = -EOVERFLOW;
- if (f.l_len > COMPAT_LOFF_T_MAX)
- f.l_len = COMPAT_LOFF_T_MAX;
- if (ret == 0)
- ret = put_compat_flock64(&f, compat_ptr(arg));
- }
+ err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
break;
-
default:
- ret = sys_fcntl(fd, cmd, arg);
+ err = do_fcntl(fd, cmd, arg, f.file);
break;
}
- return ret;
+out_put:
+ fdput(f);
+ return err;
}
COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
diff --git a/fs/locks.c b/fs/locks.c
index 054f6fb7641e..8b4e78e4c054 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2325,7 +2325,7 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock)
if (error)
goto out;
- flock.l_type = file_lock.fl_type;
+ flock->l_type = file_lock.fl_type;
if (file_lock.fl_type != F_UNLCK)
posix_lock_to_flock64(flock, &file_lock);
--
2.11.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: rewrite file locking compat syscalls
2017-05-15 20:33 rewrite file locking compat syscalls Christoph Hellwig
2017-05-15 20:33 ` [PATCH 1/2] fs/locks: pass kernel struct flock to fcntl_getlk/setlk Christoph Hellwig
2017-05-15 20:33 ` [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64 Christoph Hellwig
@ 2017-05-16 10:08 ` Jeff Layton
2 siblings, 0 replies; 6+ messages in thread
From: Jeff Layton @ 2017-05-16 10:08 UTC (permalink / raw)
To: Christoph Hellwig, bfields; +Cc: linux-fsdevel
On Mon, 2017-05-15 at 22:33 +0200, Christoph Hellwig wrote:
> Export proper lowlevel helper and use them from the compat code instead
> of playing set_fs games.
>
Looks good -- nice cleanup...and yeah, ISTR that I broke ARM when
merging the OFD lock code because I screwed up the set_fs calls. So, I'm
all for this change.
Christoph, do you want me to plan to merge these for v4.13? If so, I'll
get them into my linux-next branch soon so we can start testing them.
Thanks,
Reviewed-by: Jeff Layton <jlayton@redhat.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64
2017-05-15 20:33 ` [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64 Christoph Hellwig
@ 2017-05-16 10:46 ` Jeff Layton
2017-05-16 11:50 ` Christoph Hellwig
0 siblings, 1 reply; 6+ messages in thread
From: Jeff Layton @ 2017-05-16 10:46 UTC (permalink / raw)
To: Christoph Hellwig, bfields; +Cc: linux-fsdevel
On Mon, 2017-05-15 at 22:33 +0200, Christoph Hellwig wrote:
> Instead write a proper compat syscall that calls common helpers.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> fs/fcntl.c | 118 +++++++++++++++++++++++++++++++++++--------------------------
> fs/locks.c | 2 +-
> 2 files changed, 68 insertions(+), 52 deletions(-)
>
> diff --git a/fs/fcntl.c b/fs/fcntl.c
> index 671ac43c65df..9d909b029063 100644
> --- a/fs/fcntl.c
> +++ b/fs/fcntl.c
> @@ -505,76 +505,92 @@ convert_fcntl_cmd(unsigned int cmd)
> return cmd;
> }
>
> +/*
> + * GETLK was successful and we need to return the data, but it needs to fit in
> + * the compat structure.
> + * l_start shouldn't be too big, unless the original start + end is greater than
> + * COMPAT_OFF_T_MAX, in which case the app was asking for trouble, so we return
> + * -EOVERFLOW in that case. l_len could be too big, in which case we just
> + * truncate it, and only allow the app to see that part of the conflicting lock
> + * that might make sense to it anyway
> + */
> +static int fixup_compat_flock(struct flock *flock)
> +{
> + if (flock.l_start > COMPAT_OFF_T_MAX)
> + return -EOVERFLOW;
> + if (flock.l_len > COMPAT_OFF_T_MAX)
> + flock.l_len = COMPAT_OFF_T_MAX;
> + return 0;
> +}
> +
Erm...build break above though -- flock is a pointer there, so those
should be "flock->...". I'll just squash that fix into the patch unless
you need to send a respin for other reasons.
> COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
> compat_ulong_t, arg)
> {
> - mm_segment_t old_fs;
> - struct flock f;
> - long ret;
> - unsigned int conv_cmd;
> + struct fd f = fdget_raw(fd);
> + struct flock flock;
> + long err = -EBADF;
> +
> + if (!f.file)
> + return err;
> +
> + if (unlikely(f.file->f_mode & FMODE_PATH)) {
> + if (!check_fcntl_cmd(cmd))
> + goto out_put;
> + }
> +
> + err = security_file_fcntl(f.file, cmd, arg);
> + if (err)
> + goto out_put;
>
> switch (cmd) {
> case F_GETLK:
> + err = get_compat_flock(&flock, compat_ptr(arg));
> + if (err)
> + break;
> + err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
> + if (err)
> + break;
> + err = fixup_compat_flock(&flock);
> + if (err)
> + return err;
> + err = put_compat_flock(&flock, compat_ptr(arg));
> + break;
> + case F_GETLK64:
> + case F_OFD_GETLK:
> + err = get_compat_flock64(&flock, compat_ptr(arg));
> + if (err)
> + break;
> + err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
> + if (err)
> + break;
> + err = fixup_compat_flock(&flock);
> + if (err)
> + return err;
> + err = put_compat_flock64(&flock, compat_ptr(arg));
> + break;
> case F_SETLK:
> case F_SETLKW:
> - ret = get_compat_flock(&f, compat_ptr(arg));
> - if (ret != 0)
> + err = get_compat_flock(&flock, compat_ptr(arg));
> + if (err)
> break;
> - old_fs = get_fs();
> - set_fs(KERNEL_DS);
> - ret = sys_fcntl(fd, cmd, (unsigned long)&f);
> - set_fs(old_fs);
> - if (cmd == F_GETLK && ret == 0) {
> - /* GETLK was successful and we need to return the data...
> - * but it needs to fit in the compat structure.
> - * l_start shouldn't be too big, unless the original
> - * start + end is greater than COMPAT_OFF_T_MAX, in which
> - * case the app was asking for trouble, so we return
> - * -EOVERFLOW in that case.
> - * l_len could be too big, in which case we just truncate it,
> - * and only allow the app to see that part of the conflicting
> - * lock that might make sense to it anyway
> - */
> -
> - if (f.l_start > COMPAT_OFF_T_MAX)
> - ret = -EOVERFLOW;
> - if (f.l_len > COMPAT_OFF_T_MAX)
> - f.l_len = COMPAT_OFF_T_MAX;
> - if (ret == 0)
> - ret = put_compat_flock(&f, compat_ptr(arg));
> - }
> + err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
> break;
> -
> - case F_GETLK64:
> case F_SETLK64:
> case F_SETLKW64:
> - case F_OFD_GETLK:
> case F_OFD_SETLK:
> case F_OFD_SETLKW:
> - ret = get_compat_flock64(&f, compat_ptr(arg));
> - if (ret != 0)
> + err = get_compat_flock64(&flock, compat_ptr(arg));
> + if (err)
> break;
> - old_fs = get_fs();
> - set_fs(KERNEL_DS);
> - conv_cmd = convert_fcntl_cmd(cmd);
> - ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
> - set_fs(old_fs);
> - if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
> - /* need to return lock information - see above for commentary */
> - if (f.l_start > COMPAT_LOFF_T_MAX)
> - ret = -EOVERFLOW;
> - if (f.l_len > COMPAT_LOFF_T_MAX)
> - f.l_len = COMPAT_LOFF_T_MAX;
> - if (ret == 0)
> - ret = put_compat_flock64(&f, compat_ptr(arg));
> - }
> + err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
> break;
> -
> default:
> - ret = sys_fcntl(fd, cmd, arg);
> + err = do_fcntl(fd, cmd, arg, f.file);
> break;
> }
> - return ret;
> +out_put:
> + fdput(f);
> + return err;
> }
>
> COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
> diff --git a/fs/locks.c b/fs/locks.c
> index 054f6fb7641e..8b4e78e4c054 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -2325,7 +2325,7 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock)
> if (error)
> goto out;
>
> - flock.l_type = file_lock.fl_type;
> + flock->l_type = file_lock.fl_type;
> if (file_lock.fl_type != F_UNLCK)
> posix_lock_to_flock64(flock, &file_lock);
>
--
Jeff Layton <jlayton@poochiereds.net>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64
2017-05-16 10:46 ` Jeff Layton
@ 2017-05-16 11:50 ` Christoph Hellwig
0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2017-05-16 11:50 UTC (permalink / raw)
To: Jeff Layton; +Cc: bfields, linux-fsdevel
On Tue, May 16, 2017 at 06:46:10AM -0400, Jeff Layton wrote:
> Erm...build break above though -- flock is a pointer there, so those
> should be "flock->...". I'll just squash that fix into the patch unless
> you need to send a respin for other reasons.
Thanks. I did a last minute fixup to factor this into a helper and messed
up..
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-05-16 11:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-15 20:33 rewrite file locking compat syscalls Christoph Hellwig
2017-05-15 20:33 ` [PATCH 1/2] fs/locks: pass kernel struct flock to fcntl_getlk/setlk Christoph Hellwig
2017-05-15 20:33 ` [PATCH 2/2] fs/locks: don't mess with the address limit in compat_fcntl64 Christoph Hellwig
2017-05-16 10:46 ` Jeff Layton
2017-05-16 11:50 ` Christoph Hellwig
2017-05-16 10:08 ` rewrite file locking compat syscalls Jeff Layton
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).