diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-06-26 20:26:03 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2009-06-26 20:26:03 +0000 |
commit | ee9cfe88dbce11c2d46d5eab24ecbc2cffe18bc1 (patch) | |
tree | 3b961099ace235c305786b852691feaf001e7eac | |
parent | 7eaacdbd20a0e84c37af9f76beb17a25a798a812 (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.c | 9 |
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 */ |