aboutsummaryrefslogtreecommitdiff
path: root/sys/vm/vm_unix.c
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2018-06-04 19:35:15 +0000
committerMark Johnston <markj@FreeBSD.org>2018-06-04 19:35:15 +0000
commit9f9c9b22ecfd9e87cbe9e1becf946faeb5fbcac6 (patch)
tree24c82053b6f8c91479e5436ee9b61f6a8e6a75ea /sys/vm/vm_unix.c
parentede2f7731def0fbe8529ab825b19fddb75adfee5 (diff)
downloadsrc-9f9c9b22ecfd9e87cbe9e1becf946faeb5fbcac6.tar.gz
src-9f9c9b22ecfd9e87cbe9e1becf946faeb5fbcac6.zip
Reimplement brk() and sbrk() to avoid the use of _end.
Previously, libc.so would initialize its notion of the break address using _end, a special symbol emitted by the static linker following the bss section. Compatibility issues between lld and ld.bfd could cause the wrong definition of _end (libc.so's definition rather than that of the executable) to be used, breaking the brk()/sbrk() interface. Avoid this problem and future interoperability issues by simply not relying on _end. Instead, modify the break() system call to return the kernel's view of the current break address, and have libc initialize its state using an extra syscall upon the first use of the interface. As a side effect, this appears to fix brk()/sbrk() usage in executables run with rtld direct exec, since the kernel and libc.so no longer maintain separate views of the process' break address. PR: 228574 Reviewed by: kib (previous version) MFC after: 2 months Differential Revision: https://reviews.freebsd.org/D15663
Notes
Notes: svn path=/head/; revision=334626
Diffstat (limited to 'sys/vm/vm_unix.c')
-rw-r--r--sys/vm/vm_unix.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index b53e6fb6614e..936223629231 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -102,13 +102,16 @@ sys_obreak(struct thread *td, struct obreak_args *uap)
}
} else if (new < base) {
/*
- * This is simply an invalid value. If someone wants to
- * do fancy address space manipulations, mmap and munmap
- * can do most of what the user would want.
+ * Simply return the current break address without
+ * modifying any state. This is an ad-hoc interface
+ * used by libc to determine the initial break address,
+ * avoiding a dependency on magic features in the system
+ * linker.
*/
- error = EINVAL;
+ new = old;
goto done;
}
+
if (new > old) {
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
if (ptoa(pmap_wired_count(map->pmap)) +
@@ -225,6 +228,9 @@ done:
(void) vm_map_wire(map, old, new,
VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
+ if (error == 0)
+ td->td_retval[0] = new;
+
return (error);
#else /* defined(__aarch64__) || defined(__riscv__) */
return (ENOSYS);