summaryrefslogtreecommitdiff
path: root/kernel/vm.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2022-10-04 11:52:57 -0400
committerRobert Morris <[email protected]>2022-10-04 11:52:57 -0400
commitd2b2dff7490f2c4b8e91f79940fc46f0361c216c (patch)
tree2db70a0e68469411a5b2cb007e8ec65f67790439 /kernel/vm.c
parent989e8f2f1f5bd68731472874bed19fab48a202af (diff)
downloadxv6-labs-d2b2dff7490f2c4b8e91f79940fc46f0361c216c.tar.gz
xv6-labs-d2b2dff7490f2c4b8e91f79940fc46f0361c216c.tar.bz2
xv6-labs-d2b2dff7490f2c4b8e91f79940fc46f0361c216c.zip
fix copyout() to refuse to write a read-only page
Diffstat (limited to 'kernel/vm.c')
-rw-r--r--kernel/vm.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/kernel/vm.c b/kernel/vm.c
index 9f69783..486945e 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -352,12 +352,17 @@ int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{
uint64 n, va0, pa0;
+ pte_t *pte;
while(len > 0){
va0 = PGROUNDDOWN(dstva);
- pa0 = walkaddr(pagetable, va0);
- if(pa0 == 0)
+ if(va0 >= MAXVA)
+ return -1;
+ pte = walk(pagetable, va0, 0);
+ if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ||
+ (*pte & PTE_W) == 0)
return -1;
+ pa0 = PTE2PA(*pte);
n = PGSIZE - (dstva - va0);
if(n > len)
n = len;