Commit 4e14dc19 authored by John Engel's avatar John Engel Committed by Linus Torvalds

[PATCH] compat_sys_fcntl64: fix for locking near end of file

Here's a patch to fix a bug in compat_sys_fcntl64 in fs/compat.c.  The bug
occurs with a 32 bit app that calls fcntl and checking for a lock near the
end of a file.

    struct flock sflp;
    sflp.l_start = 2147483345;
    sflp.l_len = 302;
    /* 2147483345 + 302 == 2147483647 (this should not overflow 31 bits) */
    /* 2^31 ==             2147483648 */
    fcntl_stat = fcntl(fd, F_GETLK, &sflp);

The patch also contains a fix to handle l_len < 0 which is now defined in
POSIX 1003.1-2001 from the fcntl man page.
Signed-off-by: default avatarJohn Engel <jhe@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 44bc377d
...@@ -528,8 +528,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, ...@@ -528,8 +528,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
ret = sys_fcntl(fd, cmd, (unsigned long)&f); ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs(old_fs); set_fs(old_fs);
if ((cmd == F_GETLK) && (ret == 0)) { if ((cmd == F_GETLK) && (ret == 0)) {
/* POSIX-2001 now defines negative l_len */
if (f.l_len < 0) {
f.l_start += f.l_len;
f.l_len = -f.l_len;
}
if (f.l_start < 0)
return -EINVAL;
if ((f.l_start >= COMPAT_OFF_T_MAX) || if ((f.l_start >= COMPAT_OFF_T_MAX) ||
((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX)) ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
ret = -EOVERFLOW; ret = -EOVERFLOW;
if (ret == 0) if (ret == 0)
ret = put_compat_flock(&f, compat_ptr(arg)); ret = put_compat_flock(&f, compat_ptr(arg));
...@@ -549,8 +556,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd, ...@@ -549,8 +556,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
(unsigned long)&f); (unsigned long)&f);
set_fs(old_fs); set_fs(old_fs);
if ((cmd == F_GETLK64) && (ret == 0)) { if ((cmd == F_GETLK64) && (ret == 0)) {
/* POSIX-2001 now defines negative l_len */
if (f.l_len < 0) {
f.l_start += f.l_len;
f.l_len = -f.l_len;
}
if (f.l_start < 0)
return -EINVAL;
if ((f.l_start >= COMPAT_LOFF_T_MAX) || if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX)) ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
ret = -EOVERFLOW; ret = -EOVERFLOW;
if (ret == 0) if (ret == 0)
ret = put_compat_flock64(&f, compat_ptr(arg)); ret = put_compat_flock64(&f, compat_ptr(arg));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment