From 7c7ed208221dbd115c7cc88faa0e42150cfa14a2 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Fri, 20 Sep 2019 13:09:26 -0400 Subject: [PATCH] don't leak a file system block if the buf argument to write is invalid and a usertest --- kernel/fs.c | 9 +++++++-- 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"},