diff --git a/include/unistd.h b/include/unistd.h index 0329122..dc22814 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -499,6 +499,9 @@ int exect(const char *, char * const *, char * const *); int execvP(const char *, const char *, char * const *); int feature_present(const char *); char *fflagstostr(u_long); +#if __BSD_VISIBLE +int forkdepth(u_int *); +#endif int getdomainname(char *, int); int getgrouplist(const char *, gid_t, gid_t *, int *); int getloginclass(char *, size_t); diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 2232b79..6bc4081 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -44,6 +44,7 @@ SRCS+= __getosreldate.c \ fmtcheck.c \ fmtmsg.c \ fnmatch.c \ + forkdepth.c \ fpclassify.c \ frexp.c \ fstab.c \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index ee4d619..0c015c8 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -410,6 +410,7 @@ FBSD_1.3 { }; FBSD_1.4 { + forkdepth; scandir_b; }; diff --git a/lib/libc/gen/auxv.c b/lib/libc/gen/auxv.c index 3767ac0..358cd92 100644 --- a/lib/libc/gen/auxv.c +++ b/lib/libc/gen/auxv.c @@ -66,7 +66,7 @@ __init_elf_aux_vector(void) static pthread_once_t aux_once = PTHREAD_ONCE_INIT; static int pagesize, osreldate, canary_len, ncpus, pagesizes_len; static char *canary, *pagesizes; -static void *timekeep; +static void *timekeep, *pids; static void init_aux(void) @@ -106,6 +106,10 @@ init_aux(void) case AT_TIMEKEEP: timekeep = aux->a_un.a_ptr; break; + + case AT_PIDS: + pids = aux->a_un.a_ptr; + break; } } } @@ -178,6 +182,16 @@ _elf_aux_info(int aux, void *buf, int buflen) } else res = EINVAL; break; + case AT_PIDS: + if (buflen == sizeof(void *)) { + if (pids != NULL) { + *(void **)buf = pids; + res = 0; + } else + res = ENOENT; + } else + res = EINVAL; + break; default: res = ENOENT; break; diff --git a/lib/libc/gen/forkdepth.c b/lib/libc/gen/forkdepth.c new file mode 100644 index 0000000..2233d1d --- /dev/null +++ b/lib/libc/gen/forkdepth.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include "libc_private.h" + +int __forkdepth(u_int *); + +__weak_reference(__forkdepth, forkdepth); + +int +__forkdepth(u_int *res) +{ + + return (__vdso_forkdepth(res)); +} diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index bfcd3d0..a9c9c6c 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -372,4 +372,11 @@ void __init_elf_aux_vector(void); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); +struct vdso_pids; +extern struct vdso_pids *vdso_pids_ptr; +int fetch_vdso_pids_ptr(void); + +__pid_t __sys_getpid(void); +__pid_t __sys_getppid(void); + #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index e8ec58e..cb182ba 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -19,6 +19,12 @@ SRCS+= clock_gettime.c gettimeofday.c __vdso_gettimeofday.c NOASM+= clock_gettime.o gettimeofday.o PSEUDO+= _clock_gettime.o _gettimeofday.o +SRCS+= vdso_pids.c +SRCS+= getpid.c __vdso_getpid.c +NOASM+= getpid.o +PSEUDO+= _getpid.o +SRCS+= __vdso_forkdepth.c + # Sources common to both syscall interfaces: SRCS+= \ stack_protector.c \ diff --git a/lib/libc/sys/__vdso_forkdepth.c b/lib/libc/sys/__vdso_forkdepth.c new file mode 100644 index 0000000..2851905 --- /dev/null +++ b/lib/libc/sys/__vdso_forkdepth.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include "libc_private.h" + +#pragma weak __vdso_forkdepth +int +__vdso_forkdepth(u_int *res) +{ + uint32_t res1; + int error; + uint32_t flags; + + error = fetch_vdso_pids_ptr(); + if (error != 0) + return (error); + res1 = vdso_pids_ptr->pid_gen; + flags = atomic_load_acq_int(&vdso_pids_ptr->pid_flags); + if ((flags & VDSO_PID_VALID) == 0) + return (ESRCH); + *res = res1; + return (0); +} diff --git a/lib/libc/sys/__vdso_getpid.c b/lib/libc/sys/__vdso_getpid.c new file mode 100644 index 0000000..418a30d --- /dev/null +++ b/lib/libc/sys/__vdso_getpid.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include "libc_private.h" + +#pragma weak __vdso_getpid +int +__vdso_getpid(pid_t *res) +{ + pid_t res1; + int error; + uint32_t flags; + + error = fetch_vdso_pids_ptr(); + if (error != 0) + return (error); + res1 = vdso_pids_ptr->pid_my; + flags = atomic_load_acq_int(&vdso_pids_ptr->pid_flags); + if ((flags & VDSO_PID_VALID) == 0) + return (ENOSYS); + *res = res1; + return (0); +} diff --git a/lib/libc/sys/getpid.c b/lib/libc/sys/getpid.c new file mode 100644 index 0000000..7ace6b6 --- /dev/null +++ b/lib/libc/sys/getpid.c @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include "libc_private.h" + +int __getpid(void); + +__weak_reference(__getpid, getpid); + +pid_t +__getpid(void) +{ + pid_t res; + int error; + + error = __vdso_getpid(&res); + if (error == ENOSYS) + res = __sys_getpid(); + return (res); +} diff --git a/lib/libc/sys/vdso_pids.c b/lib/libc/sys/vdso_pids.c new file mode 100644 index 0000000..efc1ab1 --- /dev/null +++ b/lib/libc/sys/vdso_pids.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include "libc_private.h" + +struct vdso_pids *vdso_pids_ptr; + +int +fetch_vdso_pids_ptr(void) +{ + int error; + + error = _elf_aux_info(AT_PIDS, &vdso_pids_ptr, sizeof(vdso_pids_ptr)); + if (error != 0 || vdso_pids_ptr == NULL) + return (ENOSYS); + return (0); +} diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index a72612b..0cd07fd 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -2782,6 +2782,7 @@ freebsd32_copyout_strings(struct image_params *imgp) struct freebsd32_ps_strings *arginfo; char canary[sizeof(long) * 8]; int32_t pagesizes32[MAXPAGESIZES]; + struct vdso_pids vp; size_t execpath_len; int szsigcode; @@ -2840,6 +2841,20 @@ freebsd32_copyout_strings(struct image_params *imgp) copyout(pagesizes32, (void *)destp, sizeof(pagesizes32)); imgp->pagesizeslen = sizeof(pagesizes32); + /* + * Fast getpid data. + */ + destp -= sizeof(struct vdso_pids); + destp = rounddown2(destp, sizeof(uint32_t)); + p->p_vdso_pids = destp; + vp.pid_flags = VDSO_PID_VALID; + vp.pid_gen = 0; + vp.pid_my = imgp->proc->p_pid; + sx_slock(&proctree_lock); + vp.pid_parent = proc_realparent(imgp->proc)->p_pid; + sx_sunlock(&proctree_lock); + copyout(&vp, (void *)destp, sizeof(vp)); + destp -= ARG_MAX - imgp->args->stringspace; destp = rounddown2(destp, sizeof(uint32_t)); diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 53abf92..dbdb620 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1024,6 +1024,8 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY(pos, AT_STACKPROT, imgp->sysent->sv_shared_page_obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot : imgp->sysent->sv_stackprot); + if (curproc->p_vdso_pids != 0) + AUXARGS_ENTRY(pos, AT_PIDS, curproc->p_vdso_pids); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 5b80f5c..28fee95 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #ifdef KTRACE @@ -1225,6 +1226,7 @@ exec_copyout_strings(imgp) register_t *stack_base; struct ps_strings *arginfo; struct proc *p; + struct vdso_pids vp; size_t execpath_len; int szsigcode, szps; char canary[sizeof(long) * 8]; @@ -1283,6 +1285,20 @@ exec_copyout_strings(imgp) copyout(pagesizes, (void *)destp, szps); imgp->pagesizeslen = szps; + /* + * Fast getpid data. + */ + destp -= sizeof(struct vdso_pids); + destp = rounddown2(destp, sizeof(uint32_t)); + p->p_vdso_pids = destp; + vp.pid_flags = VDSO_PID_VALID; + vp.pid_gen = 0; + vp.pid_my = p->p_pid; + sx_slock(&proctree_lock); + vp.pid_parent = proc_realparent(p)->p_pid; + sx_sunlock(&proctree_lock); + copyout(&vp, (void *)destp, sizeof(vp)); + destp -= ARG_MAX - imgp->args->stringspace; destp = rounddown2(destp, sizeof(void *)); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 2c83422..86dfaa7 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -1021,8 +1022,8 @@ fork_return(struct thread *td, struct trapframe *frame) { struct proc *p, *dbg; + p = td->td_proc; if (td->td_dbgflags & TDB_STOPATFORK) { - p = td->td_proc; sx_xlock(&proctree_lock); PROC_LOCK(p); if ((p->p_pptr->p_flag & (P_TRACED | P_FOLLOWFORK)) == @@ -1049,6 +1050,7 @@ fork_return(struct thread *td, struct trapframe *frame) } PROC_UNLOCK(p); } + vdso_pids_refresh(p); userret(td, frame); diff --git a/sys/kern/kern_sharedpage.c b/sys/kern/kern_sharedpage.c index fd619cd..2b93f1c 100644 --- a/sys/kern/kern_sharedpage.c +++ b/sys/kern/kern_sharedpage.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -237,3 +238,74 @@ exec_sysvec_init(void *param) sv->sv_timekeep_off = tk_base; timekeep_push_vdso(); } + +int +vdso_pids_update(struct proc *p) +{ + pid_t ppid; + uint32_t gen, ngen; + int error; + + KASSERT(p == curproc, ("no remote vm access")); + if (p->p_vdso_pids == 0) + return (ENOENT); + error = suword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_my)), p->p_pid); + if (error == 0) { + sx_slock(&proctree_lock); + ppid = proc_realparent(p)->p_pid; + sx_sunlock(&proctree_lock); + error = suword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_parent)), ppid); + } + while (error == 0) { + error = fueword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_gen)), &gen); + if (error != 0) + break; + error = casueword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_gen)), gen, &ngen, + gen + 1); + if (error == -1 || ngen == gen) + break; + } + if (error == -1) + error = EFAULT; + return (error); +} + +void +vdso_pids_flip(struct proc *p, bool enable) +{ + int error; + uint32_t nflags, rflags, xflags; + + KASSERT(p == curproc, ("no remote vm access")); + if (p->p_vdso_pids == 0) + return; + for (;;) { + error = fueword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_flags)), &xflags); + if (error != 0) + break; + if (enable) + nflags = xflags | VDSO_PID_VALID; + else + nflags = xflags & ~VDSO_PID_VALID; + error = casueword32((void *)(p->p_vdso_pids + + offsetof(struct vdso_pids, pid_flags)), xflags, + &rflags, nflags); + if (error == -1 || rflags == xflags) + break; + } + +} + +void +vdso_pids_refresh(struct proc *p) +{ + int error; + + error = vdso_pids_update(p); + vdso_pids_flip(p, error == 0); +} diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 64b99fc..03d27cd 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -575,6 +575,7 @@ struct proc { rlim_t p_cpulimit; /* (c) Current CPU limit in seconds. */ signed char p_nice; /* (c) Process "nice" value. */ int p_fibnum; /* in this routing domain XXX MRT */ + uintptr_t p_vdso_pids; /* (x) Usermode address of vdso_pids */ pid_t p_reapsubtree; /* (e) Pid of the direct child of the reaper which spawned our subtree. */ diff --git a/sys/sys/vdso.h b/sys/sys/vdso.h index d905304..89a848e 100644 --- a/sys/sys/vdso.h +++ b/sys/sys/vdso.h @@ -1,7 +1,11 @@ /*- * Copyright 2012 Konstantin Belousov . + * Copyright (c) 2014 The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -54,6 +58,16 @@ struct vdso_timekeep { #define VDSO_TK_VER_CURR VDSO_TK_VER_1 #define VDSO_TH_ALGO_1 0x1 +struct vdso_pids { + uint32_t pid_flags; + uint32_t pid_gen; + pid_t pid_my; + pid_t pid_parent; + uint32_t pad[12]; +}; + +#define VDSO_PID_VALID 0x0001 + #ifndef _KERNEL struct timespec; @@ -64,6 +78,8 @@ int __vdso_clock_gettime(clockid_t clock_id, struct timespec *ts); int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz); u_int __vdso_gettc(const struct vdso_timehands *vdso_th); int __vdso_gettimekeep(struct vdso_timekeep **tk); +int __vdso_getpid(pid_t *res); +int __vdso_forkdepth(u_int *res); #endif @@ -71,6 +87,10 @@ int __vdso_gettimekeep(struct vdso_timekeep **tk); struct timecounter; +int vdso_pids_update(struct proc *p); +void vdso_pids_flip(struct proc *p, bool enable); +void vdso_pids_refresh(struct proc *p); + void timekeep_push_vdso(void); uint32_t tc_fill_vdso_timehands(struct vdso_timehands *vdso_th); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index c9ee890..96d83b0 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -636,6 +637,7 @@ vm_forkproc(td, p2, td2, vm2, flags) error = vmspace_unshare(p1); if (error) return (error); + vdso_pids_refresh(p1); } } cpu_fork(td, p2, td2, flags); @@ -645,6 +647,13 @@ vm_forkproc(td, p2, td2, vm2, flags) if (flags & RFMEM) { p2->p_vmspace = p1->p_vmspace; atomic_add_int(&p1->p_vmspace->vm_refcnt, 1); + + /* + * When address space is shared among processes, + * indicate to usermode that the structure must not be + * used. + */ + vdso_pids_flip(p1, false); } while (vm_page_count_severe()) { diff --git a/sys/x86/include/elf.h b/sys/x86/include/elf.h index cde395b..ac60d3f 100644 --- a/sys/x86/include/elf.h +++ b/sys/x86/include/elf.h @@ -100,8 +100,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_PIDS 24 /* Pointer to pids. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 25 /* Count of defined aux entry types. */ /* * Relocation types. @@ -185,8 +186,9 @@ __ElfType(Auxinfo); #define AT_PAGESIZESLEN 21 /* Number of pagesizes. */ #define AT_TIMEKEEP 22 /* Pointer to timehands. */ #define AT_STACKPROT 23 /* Initial stack protection. */ +#define AT_PIDS 24 /* Pointer to pids. */ -#define AT_COUNT 24 /* Count of defined aux entry types. */ +#define AT_COUNT 25 /* Count of defined aux entry types. */ /* * Relocation types.