Split kern_break from sys_break and use it in linuxulator

Previously the linuxulator's linux_brk invoked the FreeBSD sys_break
syscall implementation directly.  Instead, move the bulk of the existing
implementation to kern_break, and call that from both sys_break and
linux_brk.

This also addresses a minor bug in linux_brk in that we now return the
actual (rounded up) break address, rather than the requested value.

Reviewed by:	brooks (earlier version)
Sponsored by:	Turing Robotic Industries
Differential Revision:	https://reviews.freebsd.org/D16019
This commit is contained in:
Ed Maste 2018-06-27 14:45:13 +00:00
parent d207040226
commit e8a1ec3e05
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=335702
3 changed files with 26 additions and 15 deletions

View File

@ -232,22 +232,18 @@ int
linux_brk(struct thread *td, struct linux_brk_args *args)
{
struct vmspace *vm = td->td_proc->p_vmspace;
vm_offset_t new, old;
struct break_args /* {
char * nsize;
} */ tmp;
uintptr_t new, old;
#ifdef DEBUG
if (ldebug(brk))
printf(ARGS(brk, "%p"), (void *)(uintptr_t)args->dsend);
#endif
old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
new = (vm_offset_t)args->dsend;
tmp.nsize = (char *)new;
if (((caddr_t)new > vm->vm_daddr) && !sys_break(td, &tmp))
td->td_retval[0] = (long)new;
old = (uintptr_t)vm->vm_daddr + ctob(vm->vm_dsize);
new = (uintptr_t)args->dsend;
if ((caddr_t)new > vm->vm_daddr && !kern_break(td, &new))
td->td_retval[0] = (register_t)new;
else
td->td_retval[0] = (long)old;
td->td_retval[0] = (register_t)old;
return (0);
}

View File

@ -76,6 +76,7 @@ int kern_adjtime(struct thread *td, struct timeval *delta,
int kern_alternate_path(struct thread *td, const char *prefix, const char *path,
enum uio_seg pathseg, char **pathbuf, int create, int dirfd);
int kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa);
int kern_break(struct thread *td, uintptr_t *addr);
int kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds,
size_t ncmds);
int kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights);

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
@ -69,6 +70,22 @@ int
sys_break(struct thread *td, struct break_args *uap)
{
#if !defined(__aarch64__) && !defined(__riscv__)
uintptr_t addr;
int error;
addr = (uintptr_t)uap->nsize;
error = kern_break(td, &addr);
if (error == 0)
td->td_retval[0] = addr;
return (error);
#else /* defined(__aarch64__) || defined(__riscv__) */
return (ENOSYS);
#endif /* defined(__aarch64__) || defined(__riscv__) */
}
int
kern_break(struct thread *td, uintptr_t *addr)
{
struct vmspace *vm = td->td_proc->p_vmspace;
vm_map_t map = &vm->vm_map;
vm_offset_t new, old, base;
@ -82,7 +99,7 @@ sys_break(struct thread *td, struct break_args *uap)
vmemlim = lim_cur(td, RLIMIT_VMEM);
do_map_wirefuture = FALSE;
new = round_page((vm_offset_t)uap->nsize);
new = round_page(*addr);
vm_map_lock(map);
base = round_page((vm_offset_t) vm->vm_daddr);
@ -226,12 +243,9 @@ sys_break(struct thread *td, struct break_args *uap)
VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
if (error == 0)
td->td_retval[0] = new;
*addr = new;
return (error);
#else /* defined(__aarch64__) || defined(__riscv__) */
return (ENOSYS);
#endif /* defined(__aarch64__) || defined(__riscv__) */
}
#ifdef COMPAT_FREEBSD11