diff options
author | delphij <delphij@FreeBSD.org> | 2017-05-31 05:11:28 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2017-05-31 05:11:28 +0000 |
commit | 6486680e0a2c03d2e15ea709c3f72a9e5eac9753 (patch) | |
tree | 172a7824b227f814599d72ba5302e896968273d9 | |
parent | aaa7bcdbf6d0aa0cfbaca2123632feee92eab69b (diff) | |
download | FreeBSD-src-6486680e0a2c03d2e15ea709c3f72a9e5eac9753.zip FreeBSD-src-6486680e0a2c03d2e15ea709c3f72a9e5eac9753.tar.gz |
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
-rw-r--r-- | lib/libc/sys/minherit.2 | 14 | ||||
-rw-r--r-- | sys/sys/mman.h | 1 | ||||
-rw-r--r-- | sys/vm/vm.h | 1 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 29 |
4 files changed, 44 insertions, 1 deletions
diff --git a/lib/libc/sys/minherit.2 b/lib/libc/sys/minherit.2 index dc85d09..f2d437d 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 a13e3d1..497fd6f 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 d87495d..0eb7568 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 99bda8c..7897db6 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -2240,6 +2240,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); @@ -3398,6 +3399,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; } |