diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2019-09-20 13:09:26 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 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"}, | 
