sync with OpenBSD -current
This commit is contained in:
parent
34a3d7e18a
commit
ee68147dcd
30 changed files with 722 additions and 211 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: exec_elf.c,v 1.183 2023/07/12 19:34:14 jasper Exp $ */
|
||||
/* $OpenBSD: exec_elf.c,v 1.184 2024/01/16 19:05:01 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Per Fogelstrom
|
||||
|
@ -81,6 +81,7 @@
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/pledge.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
@ -97,6 +98,8 @@ void elf_load_psection(struct exec_vmcmd_set *, struct vnode *,
|
|||
Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int);
|
||||
int elf_os_pt_note_name(Elf_Note *);
|
||||
int elf_os_pt_note(struct proc *, struct exec_package *, Elf_Ehdr *, int *);
|
||||
int elf_read_pintable(struct proc *p, struct vnode *vp, Elf_Phdr *pp,
|
||||
u_int **pinp, int is_ldso, size_t len);
|
||||
|
||||
/* round up and down to page boundaries. */
|
||||
#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
|
||||
|
@ -265,6 +268,74 @@ elf_read_from(struct proc *p, struct vnode *vp, u_long off, void *buf,
|
|||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* rebase the pin offsets inside a base,len window for the text segment only.
|
||||
*/
|
||||
void
|
||||
elf_adjustpins(vaddr_t *basep, size_t *lenp, u_int *pins, int npins, u_int offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Adjust offsets, base, len */
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (pins[i] == -1 || pins[i] == 0)
|
||||
continue;
|
||||
pins[i] -= offset;
|
||||
}
|
||||
*basep += offset;
|
||||
*lenp -= offset;
|
||||
}
|
||||
|
||||
int
|
||||
elf_read_pintable(struct proc *p, struct vnode *vp, Elf_Phdr *pp,
|
||||
u_int **pinp, int is_ldso, size_t len)
|
||||
{
|
||||
struct pinsyscalls {
|
||||
u_int offset;
|
||||
u_int sysno;
|
||||
} *syscalls = NULL;
|
||||
int i, nsyscalls = 0, npins = 0;
|
||||
u_int *pins = NULL;
|
||||
|
||||
if (pp->p_filesz > SYS_MAXSYSCALL * 2 * sizeof(*syscalls) ||
|
||||
pp->p_filesz % sizeof(*syscalls) != 0)
|
||||
goto bad;
|
||||
nsyscalls = pp->p_filesz / sizeof(*syscalls);
|
||||
syscalls = malloc(pp->p_filesz, M_PINSYSCALL, M_WAITOK);
|
||||
if (elf_read_from(p, vp, pp->p_offset, syscalls,
|
||||
pp->p_filesz) != 0)
|
||||
goto bad;
|
||||
|
||||
/* Validate, and calculate pintable size */
|
||||
for (i = 0; i < nsyscalls; i++) {
|
||||
if (syscalls[i].sysno <= 0 ||
|
||||
syscalls[i].sysno >= SYS_MAXSYSCALL ||
|
||||
syscalls[i].offset > len)
|
||||
goto bad;
|
||||
npins = MAX(npins, syscalls[i].sysno);
|
||||
}
|
||||
if (is_ldso)
|
||||
npins = MAX(npins, SYS_kbind); /* XXX see ld.so/loader.c */
|
||||
npins++;
|
||||
|
||||
/* Fill pintable: 0 = invalid, -1 = allowed, else offset from base */
|
||||
pins = mallocarray(npins, sizeof(u_int), M_PINSYSCALL, M_WAITOK|M_ZERO);
|
||||
for (i = 0; i < nsyscalls; i++) {
|
||||
if (pins[syscalls[i].sysno])
|
||||
pins[syscalls[i].sysno] = -1; /* duplicated */
|
||||
else
|
||||
pins[syscalls[i].sysno] = syscalls[i].offset;
|
||||
}
|
||||
if (is_ldso)
|
||||
pins[SYS_kbind] = -1; /* XXX see ld.so/loader.c */
|
||||
*pinp = pins;
|
||||
pins = NULL;
|
||||
bad:
|
||||
free(syscalls, M_PINSYSCALL, nsyscalls * sizeof(*syscalls));
|
||||
free(pins, M_PINSYSCALL, npins * sizeof(u_int));
|
||||
return npins;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a file (interpreter/library) pointed to by path [stolen from
|
||||
* coff_load_shlib()]. Made slightly generic so it might be used externally.
|
||||
|
@ -276,7 +347,7 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp,
|
|||
int error, i;
|
||||
struct nameidata nd;
|
||||
Elf_Ehdr eh;
|
||||
Elf_Phdr *ph = NULL;
|
||||
Elf_Phdr *ph = NULL, *syscall_ph = NULL;
|
||||
u_long phsize = 0;
|
||||
Elf_Addr addr;
|
||||
struct vnode *vp;
|
||||
|
@ -290,6 +361,7 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp,
|
|||
int file_align;
|
||||
int loop;
|
||||
size_t randomizequota = ELF_RANDOMIZE_LIMIT;
|
||||
vaddr_t text_start = -1, text_end = 0;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
|
||||
nd.ni_pledge = PLEDGE_RPATH;
|
||||
|
@ -432,6 +504,12 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp,
|
|||
epp->ep_entry += pos;
|
||||
ap->arg_interp = pos;
|
||||
}
|
||||
if (prot & PROT_EXEC) {
|
||||
if (addr < text_start)
|
||||
text_start = addr;
|
||||
if (addr+size >= text_end)
|
||||
text_end = addr + size;
|
||||
}
|
||||
addr += size;
|
||||
break;
|
||||
|
||||
|
@ -461,12 +539,34 @@ elf_load_file(struct proc *p, char *path, struct exec_package *epp,
|
|||
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable,
|
||||
ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0);
|
||||
break;
|
||||
|
||||
case PT_OPENBSD_SYSCALLS:
|
||||
syscall_ph = &ph[i];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (syscall_ph) {
|
||||
struct process *pr = p->p_p;
|
||||
vaddr_t base = pos;
|
||||
size_t len = text_end;
|
||||
u_int *pins;
|
||||
int npins;
|
||||
|
||||
npins = elf_read_pintable(p, nd.ni_vp, syscall_ph,
|
||||
&pins, 1, len);
|
||||
if (npins) {
|
||||
elf_adjustpins(&base, &len, pins, npins,
|
||||
text_start);
|
||||
pr->ps_pin.pn_start = base;
|
||||
pr->ps_pin.pn_end = base + len;
|
||||
pr->ps_pin.pn_pins = pins;
|
||||
pr->ps_pin.pn_npins = npins;
|
||||
pr->ps_flags |= PS_PIN;
|
||||
}
|
||||
}
|
||||
|
||||
vn_marktext(nd.ni_vp);
|
||||
|
||||
bad1:
|
||||
|
@ -491,8 +591,8 @@ int
|
|||
exec_elf_makecmds(struct proc *p, struct exec_package *epp)
|
||||
{
|
||||
Elf_Ehdr *eh = epp->ep_hdr;
|
||||
Elf_Phdr *ph, *pp, *base_ph = NULL;
|
||||
Elf_Addr phdr = 0, exe_base = 0;
|
||||
Elf_Phdr *ph, *pp, *base_ph = NULL, *syscall_ph = NULL;
|
||||
Elf_Addr phdr = 0, exe_base = 0, exe_end = 0;
|
||||
int error, i, has_phdr = 0, names = 0, textrel = 0;
|
||||
char *interp = NULL;
|
||||
u_long phsize;
|
||||
|
@ -633,11 +733,13 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp)
|
|||
|
||||
/*
|
||||
* Permit system calls in main-text static binaries.
|
||||
* Also block the ld.so syscall-grant
|
||||
* static binaries may not call msyscall() or
|
||||
* pinsyscalls()
|
||||
*/
|
||||
if (interp == NULL) {
|
||||
syscall = VMCMD_SYSCALL;
|
||||
p->p_vmspace->vm_map.flags |= VM_MAP_SYSCALL_ONCE;
|
||||
p->p_vmspace->vm_map.flags |= VM_MAP_PINSYSCALL_ONCE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -696,6 +798,9 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp)
|
|||
epp->ep_tsize = addr+size -
|
||||
epp->ep_taddr;
|
||||
}
|
||||
if (interp == NULL)
|
||||
exe_end = epp->ep_taddr +
|
||||
epp->ep_tsize; /* end of TEXT */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -735,7 +840,10 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp)
|
|||
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable,
|
||||
ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0, 0);
|
||||
break;
|
||||
|
||||
case PT_OPENBSD_SYSCALLS:
|
||||
if (interp == NULL)
|
||||
syscall_ph = &ph[i];
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Not fatal, we don't need to understand everything
|
||||
|
@ -745,6 +853,25 @@ exec_elf_makecmds(struct proc *p, struct exec_package *epp)
|
|||
}
|
||||
}
|
||||
|
||||
if (syscall_ph) {
|
||||
vaddr_t base = exe_base;
|
||||
size_t len = exe_end - exe_base;
|
||||
u_int *pins;
|
||||
int npins;
|
||||
|
||||
npins = elf_read_pintable(p, epp->ep_vp, syscall_ph,
|
||||
&pins, 0, len);
|
||||
if (npins) {
|
||||
elf_adjustpins(&base, &len, pins, npins,
|
||||
epp->ep_taddr - exe_base);
|
||||
epp->ep_pinstart = base;
|
||||
epp->ep_pinend = base + len;
|
||||
epp->ep_pins = pins;
|
||||
epp->ep_npins = npins;
|
||||
p->p_p->ps_flags |= PS_PIN;
|
||||
}
|
||||
}
|
||||
|
||||
phdr += exe_base;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: kern_exec.c,v 1.252 2023/10/30 07:13:10 claudio Exp $ */
|
||||
/* $OpenBSD: kern_exec.c,v 1.253 2024/01/16 19:05:01 deraadt Exp $ */
|
||||
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
|
||||
|
||||
/*-
|
||||
|
@ -314,6 +314,8 @@ sys_execve(struct proc *p, void *v, register_t *retval)
|
|||
VMCMDSET_INIT(&pack.ep_vmcmds);
|
||||
pack.ep_vap = &attr;
|
||||
pack.ep_flags = 0;
|
||||
pack.ep_pins = NULL;
|
||||
pack.ep_npins = 0;
|
||||
|
||||
/* see if we can run it. */
|
||||
if ((error = check_exec(p, &pack)) != 0) {
|
||||
|
@ -514,6 +516,30 @@ sys_execve(struct proc *p, void *v, register_t *retval)
|
|||
if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo)))
|
||||
goto exec_abort;
|
||||
|
||||
free(pr->ps_pin.pn_pins, M_PINSYSCALL,
|
||||
pr->ps_pin.pn_npins * sizeof(u_int));
|
||||
if (pack.ep_npins) {
|
||||
pr->ps_pin.pn_start = pack.ep_pinstart;
|
||||
pr->ps_pin.pn_end = pack.ep_pinend;
|
||||
pr->ps_pin.pn_pins = pack.ep_pins;
|
||||
pack.ep_pins = NULL;
|
||||
pr->ps_pin.pn_npins = pack.ep_npins;
|
||||
pr->ps_flags |= PS_PIN;
|
||||
} else {
|
||||
pr->ps_pin.pn_start = pr->ps_pin.pn_end = 0;
|
||||
pr->ps_pin.pn_pins = NULL;
|
||||
pr->ps_pin.pn_npins = 0;
|
||||
pr->ps_flags &= ~PS_PIN;
|
||||
}
|
||||
if (pr->ps_libcpin.pn_pins) {
|
||||
free(pr->ps_libcpin.pn_pins, M_PINSYSCALL,
|
||||
pr->ps_libcpin.pn_npins * sizeof(u_int));
|
||||
pr->ps_libcpin.pn_start = pr->ps_libcpin.pn_end = 0;
|
||||
pr->ps_libcpin.pn_pins = NULL;
|
||||
pr->ps_libcpin.pn_npins = 0;
|
||||
pr->ps_flags &= ~PS_LIBCPIN;
|
||||
}
|
||||
|
||||
stopprofclock(pr); /* stop profiling */
|
||||
fdcloseexec(p); /* handle close on exec */
|
||||
execsigs(p); /* reset caught signals */
|
||||
|
@ -752,6 +778,7 @@ bad:
|
|||
if (pack.ep_interp != NULL)
|
||||
pool_put(&namei_pool, pack.ep_interp);
|
||||
free(pack.ep_args, M_TEMP, sizeof *pack.ep_args);
|
||||
free(pack.ep_pins, M_PINSYSCALL, pack.ep_npins * sizeof(u_int));
|
||||
/* close and put the exec'd file */
|
||||
vn_close(pack.ep_vp, FREAD, cred, p);
|
||||
pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: kern_exit.c,v 1.218 2024/01/15 15:47:37 mvs Exp $ */
|
||||
/* $OpenBSD: kern_exit.c,v 1.219 2024/01/16 19:05:01 deraadt Exp $ */
|
||||
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -217,6 +217,11 @@ exit1(struct proc *p, int xexit, int xsig, int flags)
|
|||
|
||||
unveil_destroy(pr);
|
||||
|
||||
free(pr->ps_pin.pn_pins, M_PINSYSCALL,
|
||||
pr->ps_pin.pn_npins * sizeof(u_int));
|
||||
free(pr->ps_libcpin.pn_pins, M_PINSYSCALL,
|
||||
pr->ps_libcpin.pn_npins * sizeof(u_int));
|
||||
|
||||
/*
|
||||
* If parent has the SAS_NOCLDWAIT flag set, we're not
|
||||
* going to become a zombie.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: kern_fork.c,v 1.254 2024/01/15 15:47:37 mvs Exp $ */
|
||||
/* $OpenBSD: kern_fork.c,v 1.255 2024/01/16 19:05:01 deraadt Exp $ */
|
||||
/* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -249,6 +249,21 @@ process_new(struct proc *p, struct process *parent, int flags)
|
|||
if (parent->ps_session->s_ttyvp != NULL)
|
||||
pr->ps_flags |= parent->ps_flags & PS_CONTROLT;
|
||||
|
||||
if (parent->ps_pin.pn_pins) {
|
||||
pr->ps_pin.pn_pins = mallocarray(parent->ps_pin.pn_npins,
|
||||
sizeof(u_int), M_PINSYSCALL, M_WAITOK);
|
||||
memcpy(pr->ps_pin.pn_pins, parent->ps_pin.pn_pins,
|
||||
parent->ps_pin.pn_npins * sizeof(u_int));
|
||||
pr->ps_flags |= PS_PIN;
|
||||
}
|
||||
if (parent->ps_libcpin.pn_pins) {
|
||||
pr->ps_libcpin.pn_pins = mallocarray(parent->ps_libcpin.pn_npins,
|
||||
sizeof(u_int), M_PINSYSCALL, M_WAITOK);
|
||||
memcpy(pr->ps_libcpin.pn_pins, parent->ps_libcpin.pn_pins,
|
||||
parent->ps_libcpin.pn_npins * sizeof(u_int));
|
||||
pr->ps_flags |= PS_LIBCPIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicate sub-structures as needed.
|
||||
* Increase reference counts on shared objects.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue