From: Hugh Dickins When handling rlimit != RLIM_INFINITY, generic_write_checks tests file position against 0xFFFFFFFFULL, and casts it to a u32. This code is carried forward from 2.4.4, and the 2.4-ac tree contains an apparently obvious fix to one part of it (should set count to 0 not to a negative). But when you think it through, it all turns out to be bogus. On a 32-bit architecture: limit is a 32-bit unsigned long, we've already handled *pos < 0 and *pos >= limit, so *pos here has no way of being > 0xFFFFFFFFULL, and thus casting it to u32 won't truncate it. And on a 64-bit architecture: limit is a 64-bit unsigned long, but this code is disallowing file position beyond the 32 bits; or if there's some userspace compatibility issue, with limit having to fit into 32 bits, the 32-bit architecture argument applies and they're still irrelevant. So just remove the 0xFFFFFFFFULL test; and in place of the u32, cast to typeof(limit) so it's right even if rlimits get wider. And there's no way we'd want to send SIGXFSZ below the limit: remove send_sig comment. There's a similarly suspicious u32 cast a little further down, when checking MAX_NON_LFS. Given its definition, that does no harm on any arch: but it's better changed to unsigned long, the type of MAX_NON_LFS. mm/filemap.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diff -puN mm/filemap.c~file-limit-checking-cleanup mm/filemap.c --- 25/mm/filemap.c~file-limit-checking-cleanup 2003-04-02 22:51:02.000000000 -0800 +++ 25-akpm/mm/filemap.c 2003-04-02 22:51:02.000000000 -0800 @@ -1509,9 +1509,8 @@ inline int generic_write_checks(struct i send_sig(SIGXFSZ, current, 0); return -EFBIG; } - if (*pos > 0xFFFFFFFFULL || *count > limit-(u32)*pos) { - /* send_sig(SIGXFSZ, current, 0); */ - *count = limit - (u32)*pos; + if (*count > limit - (typeof(limit))*pos) { + *count = limit - (typeof(limit))*pos; } } } @@ -1525,9 +1524,8 @@ inline int generic_write_checks(struct i send_sig(SIGXFSZ, current, 0); return -EFBIG; } - if (*count > MAX_NON_LFS - (u32)*pos) { - /* send_sig(SIGXFSZ, current, 0); */ - *count = MAX_NON_LFS - (u32)*pos; + if (*count > MAX_NON_LFS - (unsigned long)*pos) { + *count = MAX_NON_LFS - (unsigned long)*pos; } } _