summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Engel <jhe@us.ibm.com>2004-09-22 04:23:06 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-09-22 04:23:06 -0700
commit4e14dc19475df6edcb1abe4cf28502432496eaeb (patch)
tree5ebff80a697c5c234755230940403d37d5dc6990
parent44bc377da933ee4021a3589db72079c538db1e57 (diff)
[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: John Engel <jhe@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/compat.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/compat.c b/fs/compat.c
index f5a63275d90a..7257be91b4bd 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -528,8 +528,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs(old_fs);
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) ||
- ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+ ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
ret = -EOVERFLOW;
if (ret == 0)
ret = put_compat_flock(&f, compat_ptr(arg));
@@ -549,8 +556,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
(unsigned long)&f);
set_fs(old_fs);
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) ||
- ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+ ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
ret = -EOVERFLOW;
if (ret == 0)
ret = put_compat_flock64(&f, compat_ptr(arg));