From: John Engel 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 Signed-off-by: Andrew Morton --- 25-akpm/fs/compat.c | 18 ++++++++++++++++-- 1 files changed, 16 insertions(+), 2 deletions(-) diff -puN fs/compat.c~compat_sys_fcntl64-fix-for-locking-near-end-of-file fs/compat.c --- 25/fs/compat.c~compat_sys_fcntl64-fix-for-locking-near-end-of-file 2004-09-20 10:30:04.844226624 -0700 +++ 25-akpm/fs/compat.c 2004-09-20 10:30:04.849225864 -0700 @@ -528,8 +528,15 @@ asmlinkage long compat_sys_fcntl64(unsig 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(unsig (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)); _