diff options
| author | John Engel <jhe@us.ibm.com> | 2004-09-22 04:23:06 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-09-22 04:23:06 -0700 |
| commit | 4e14dc19475df6edcb1abe4cf28502432496eaeb (patch) | |
| tree | 5ebff80a697c5c234755230940403d37d5dc6990 | |
| parent | 44bc377da933ee4021a3589db72079c538db1e57 (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.c | 18 |
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)); |
