From 675060882480c21915629750a5a504d9da445ba3 Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Thu, 24 Sep 2020 13:18:54 -0400 Subject: [PATCH] When either_copyin/out fails, return an error from write/read Add a test to check that read/write return an error --- kernel/fs.c | 2 ++ user/usertests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/kernel/fs.c b/kernel/fs.c index ec68cd7..848b2c9 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -468,6 +468,7 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) m = min(n - tot, BSIZE - off%BSIZE); if(either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) { brelse(bp); + tot = -1; break; } brelse(bp); @@ -495,6 +496,7 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) m = min(n - tot, BSIZE - off%BSIZE); if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) { brelse(bp); + n = -1; break; } log_write(bp); diff --git a/user/usertests.c b/user/usertests.c index 004c948..7300574 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -233,6 +233,53 @@ copyinstr3(char *s) } } +// See if the kernel refuses to read/write user memory that the +// application doesn't have anymore, because it returned it. +void +rwsbrk() +{ + int fd, n; + + uint64 a = (uint64) sbrk(8192); + + if(a == 0xffffffffffffffffLL) { + printf("sbrk(rwsbrk) failed\n"); + exit(1); + } + + if ((uint64) sbrk(-8192) == 0xffffffffffffffffLL) { + printf("sbrk(rwsbrk) shrink failed\n"); + exit(1); + } + + fd = open("rwsbrk", O_CREATE|O_WRONLY); + if(fd < 0){ + printf("open(rwsbrk) failed\n"); + exit(1); + } + n = write(fd, (void*)(a+4096), 1024); + if(n >= 0){ + printf("write(fd, %p, 1024) returned %d, not -1\n", a+4096, n); + exit(1); + } + close(fd); + unlink("rwsbrk"); + + fd = open("README", O_RDONLY); + if(fd < 0){ + printf("open(rwsbrk) failed\n"); + exit(1); + } + n = read(fd, (void*)(a+4096), 10); + if(n >= 0){ + printf("read(fd, %p, 10) returned %d, not -1\n", a+4096, n); + exit(1); + } + close(fd); + + exit(0); +} + // test O_TRUNC. void truncate1(char *s) @@ -2644,6 +2691,7 @@ main(int argc, char *argv[]) {copyinstr1, "copyinstr1"}, {copyinstr2, "copyinstr2"}, {copyinstr3, "copyinstr3"}, + {rwsbrk, "rwsbrk" }, {truncate1, "truncate1"}, {truncate2, "truncate2"}, {truncate3, "truncate3"},