From bfde52da67b17e680ca5da34f553788ce1cbf7ef Mon Sep 17 00:00:00 2001 From: delphij Date: Wed, 31 May 2017 05:10:03 +0000 Subject: [PATCH] MFC r315272, r315370 r315272: Implement INHERIT_ZERO for minherit(2). INHERIT_ZERO is an OpenBSD feature. When a page is marked as such, it would be zeroed upon fork(). This would be used in new arc4random(3) functions. PR: 182610 Reviewed by: kib (earlier version) Differential Revision: https://reviews.freebsd.org/D427 r315370: The adj_free and max_free values of new_entry will be calculated and assigned by subsequent vm_map_entry_link(), therefore, remove the pointless copying. Submitted by: alc --- lib/libc/sys/minherit.2 | 14 +++++++++++++- sys/sys/mman.h | 1 + sys/vm/vm.h | 1 + sys/vm/vm_map.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/libc/sys/minherit.2 b/lib/libc/sys/minherit.2 index dc85d09fd28..f2d437d4f14 100644 --- a/lib/libc/sys/minherit.2 +++ b/lib/libc/sys/minherit.2 @@ -29,7 +29,7 @@ .\" .\" @(#)minherit.2 8.1 (Berkeley) 6/9/93 .\" -.Dd October 30, 2007 +.Dd March 15, 2017 .Dt MINHERIT 2 .Os .Sh NAME @@ -91,6 +91,11 @@ it will no longer be shared in the parent after the parent forks and there is no way to get the previous shared-backing-store mapping without unmapping and remapping the address space in the parent. +.It Dv INHERIT_ZERO +This option causes the address space in question to be mapped as new +anonymous pages, +which would be initialized to all zero bytes, +in the child process. .El .Sh RETURN VALUES .Rv -std minherit @@ -130,6 +135,13 @@ system call first appeared in .Ox and then in .Fx 2.2 . +.Pp +The +.Dv INHERIT_ZERO +support first appeared in +.Ox 5.6 +and then in +.Fx 12.0 . .Sh BUGS Once you set inheritance to .Dv MAP_PRIVATE diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 1fce960746e..414de02d422 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -43,6 +43,7 @@ #define INHERIT_SHARE 0 #define INHERIT_COPY 1 #define INHERIT_NONE 2 +#define INHERIT_ZERO 3 #endif /* diff --git a/sys/vm/vm.h b/sys/vm/vm.h index 1df51fed209..68bb4d13368 100644 --- a/sys/vm/vm.h +++ b/sys/vm/vm.h @@ -68,6 +68,7 @@ typedef char vm_inherit_t; /* inheritance codes */ #define VM_INHERIT_SHARE ((vm_inherit_t) 0) #define VM_INHERIT_COPY ((vm_inherit_t) 1) #define VM_INHERIT_NONE ((vm_inherit_t) 2) +#define VM_INHERIT_ZERO ((vm_inherit_t) 3) #define VM_INHERIT_DEFAULT VM_INHERIT_COPY typedef u_char vm_prot_t; /* protection codes */ diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 2296fb101e7..2ef89bd8fd5 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2294,6 +2294,7 @@ vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, case VM_INHERIT_NONE: case VM_INHERIT_COPY: case VM_INHERIT_SHARE: + case VM_INHERIT_ZERO: break; default: return (KERN_INVALID_ARGUMENT); @@ -3452,6 +3453,34 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) vm_map_copy_entry(old_map, new_map, old_entry, new_entry, fork_charge); break; + + case VM_INHERIT_ZERO: + /* + * Create a new anonymous mapping entry modelled from + * the old one. + */ + new_entry = vm_map_entry_create(new_map); + memset(new_entry, 0, sizeof(*new_entry)); + + new_entry->start = old_entry->start; + new_entry->end = old_entry->end; + new_entry->avail_ssize = old_entry->avail_ssize; + new_entry->eflags = old_entry->eflags & + ~(MAP_ENTRY_USER_WIRED | MAP_ENTRY_IN_TRANSITION | + MAP_ENTRY_VN_WRITECNT); + new_entry->protection = old_entry->protection; + new_entry->max_protection = old_entry->max_protection; + new_entry->inheritance = VM_INHERIT_ZERO; + + vm_map_entry_link(new_map, new_map->header.prev, + new_entry); + vmspace_map_entry_forked(vm1, vm2, new_entry); + + new_entry->cred = curthread->td_ucred; + crhold(new_entry->cred); + *fork_charge += (new_entry->end - new_entry->start); + + break; } old_entry = old_entry->next; } -- 2.45.0