]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] file limit checking simplification
authorAndrew Morton <akpm@digeo.com>
Thu, 3 Apr 2003 00:26:51 +0000 (16:26 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Thu, 3 Apr 2003 00:26:51 +0000 (16:26 -0800)
From: Hugh Dickins <hugh@veritas.com>

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

index 32847b7283bdeba0f3389f27d3a7d9cb1e255393..3edc0628638a15c9e7f7e9be5e423938575b0e1c 100644 (file)
@@ -1509,9 +1509,8 @@ inline int generic_write_checks(struct inode *inode,
                                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 inode *inode,
                        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;
                }
        }