diff options
author | Robert Morris <[email protected]> | 2019-09-20 13:09:26 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-09-20 13:09:26 -0400 |
commit | 7c7ed208221dbd115c7cc88faa0e42150cfa14a2 (patch) | |
tree | f37450d7fc3017c63c6dd50afc68800b3c294bfb | |
parent | e1a37303c89696a110c61a156768ea15cc03a246 (diff) | |
download | xv6-labs-7c7ed208221dbd115c7cc88faa0e42150cfa14a2.tar.gz xv6-labs-7c7ed208221dbd115c7cc88faa0e42150cfa14a2.tar.bz2 xv6-labs-7c7ed208221dbd115c7cc88faa0e42150cfa14a2.zip |
don't leak a file system block if the buf argument to write is invalid
and a usertest
-rw-r--r-- | kernel/fs.c | 9 | ||||
-rw-r--r-- | user/usertests.c | 39 |
2 files changed, 46 insertions, 2 deletions
diff --git a/kernel/fs.c b/kernel/fs.c index 5505408..53586d5 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -505,10 +505,15 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) brelse(bp); } - if(n > 0 && off > ip->size){ - ip->size = off; + if(n > 0){ + if(off > ip->size) + ip->size = off; + // write the i-node back to disk even if the size didn't change + // because the loop above might have called bmap() and added a new + // block to ip->addrs[]. iupdate(ip); } + return n; } diff --git a/user/usertests.c b/user/usertests.c index 608cd3f..daf907b 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -1981,6 +1981,44 @@ sbrkbugs(char *s) exit(0); } +// does write() with an invalid buffer pointer cause +// a block to be allocated for a file that is then +// not freed when the file is deleted? if the kernel +// has this bug, it will panic: balloc: out of blocks. +// assumed_free may need to be raised to be +// more than the number of free blocks. +void +badwrite(char *s) +{ + int assumed_free = 600; + + unlink("junk"); + for(int i = 0; i < assumed_free; i++){ + int fd = open("junk", O_CREATE|O_WRONLY); + if(fd < 0){ + printf("open junk failed\n"); + exit(1); + } + write(fd, (char*)0xffffffffffL, 1); + close(fd); + unlink("junk"); + } + + int fd = open("junk", O_CREATE|O_WRONLY); + if(fd < 0){ + printf("open junk failed\n"); + exit(1); + } + if(write(fd, "x", 1) != 1){ + printf("write failed\n"); + exit(1); + } + close(fd); + unlink("junk"); + + exit(0); +} + // run each test in its own process. run returns 1 if child's exit() // indicates success. int @@ -2020,6 +2058,7 @@ main(int argc, char *argv[]) } tests[] = { {pgbug, "pgbug" }, {sbrkbugs, "sbrkbugs" }, + {badwrite, "badwrite" }, {reparent, "reparent" }, {twochildren, "twochildren"}, {forkfork, "forkfork"}, |