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)
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D427
This commit is contained in:
delphij 2017-03-14 17:10:42 +00:00
parent 15ee298d2f
commit 6c1ff20b8d
4 changed files with 46 additions and 1 deletions

View File

@ -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

View File

@ -43,6 +43,7 @@
#define INHERIT_SHARE 0
#define INHERIT_COPY 1
#define INHERIT_NONE 2
#define INHERIT_ZERO 3
#endif
/*

View File

@ -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 */

View File

@ -2285,6 +2285,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);
@ -3443,6 +3444,36 @@ 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->adj_free = old_entry->adj_free;
new_entry->max_free = old_entry->max_free;
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;
}