summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2009-06-26 20:26:03 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2009-06-26 20:26:03 +0000
commitee9cfe88dbce11c2d46d5eab24ecbc2cffe18bc1 (patch)
tree3b961099ace235c305786b852691feaf001e7eac
parent7eaacdbd20a0e84c37af9f76beb17a25a798a812 (diff)
Fix a use after free in the pagedaemon.
specifically, if we free a RELEASED anon, then we will first of all remove the page from the anon, free the anon, then get the next page relative to the anon page, then call uvm_pagefree(). The problem is that while we zero out anon->an_page, we do not zero out pg->uanon. Now, uvm_pagefree() if pg->uanon is not NULL zeroes out some variables in the struct for us. One of the backed out commits added more zeroing there which would have exacerbated this use after free under heavy paging (which was where we saw bugs). Fix this by zeroing out pg->uanon. I have looked for other similar cases, but have not found any as of yet. been in snaps a while, "please do commit that" deraadt@
-rw-r--r--sys/uvm/uvm_pdaemon.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c
index d62b66f5999..e16ae26ea3b 100644
--- a/sys/uvm/uvm_pdaemon.c
+++ b/sys/uvm/uvm_pdaemon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_pdaemon.c,v 1.50 2009/06/17 00:13:59 oga Exp $ */
+/* $OpenBSD: uvm_pdaemon.c,v 1.51 2009/06/26 20:26:02 oga Exp $ */
/* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */
/*
@@ -823,8 +823,13 @@ uvmpd_scan_inactive(struct pglist *pglst)
/* released during I/O? */
if (p->pg_flags & PG_RELEASED) {
if (anon) {
- /* remove page so we can get nextpg */
+ /*
+ * remove page so we can get nextpg,
+ * also zero out anon so we don't use
+ * it after the free.
+ */
anon->an_page = NULL;
+ p->uanon = NULL;
simple_unlock(&anon->an_lock);
uvm_anfree(anon); /* kills anon */