Index: sys/compat/linux/linux_misc.h =================================================================== --- sys/compat/linux/linux_misc.h +++ sys/compat/linux/linux_misc.h @@ -50,6 +50,8 @@ * Second arg is a ptr to return the * signal. */ +#define LINUX_PR_GET_DUMPABLE 3 +#define LINUX_PR_SET_DUMPABLE 4 #define LINUX_PR_GET_KEEPCAPS 7 /* Get drop capabilities on setuid */ #define LINUX_PR_SET_KEEPCAPS 8 /* Set drop capabilities on setuid */ #define LINUX_PR_SET_NAME 15 /* Set process name. */ @@ -57,6 +59,11 @@ #define LINUX_MAX_COMM_LEN 16 /* Maximum length of the process name. */ +/* For GET/SET DUMPABLE */ +#define LINUX_SUID_DUMP_DISABLE 0 /* Don't coredump setuid processes. */ +#define LINUX_SUID_DUMP_USER 1 /* Dump as user of process. */ +#define LINUX_SUID_DUMP_ROOT 2 /* Dump as root. */ + #define LINUX_MREMAP_MAYMOVE 1 #define LINUX_MREMAP_FIXED 2 Index: sys/compat/linux/linux_misc.c =================================================================== --- sys/compat/linux/linux_misc.c +++ sys/compat/linux/linux_misc.c @@ -1912,6 +1912,45 @@ (void *)(register_t)args->arg2, sizeof(pdeath_signal))); break; + /* + * As far as I can tell, in Linux these control two sort of unrelated + * policies: can set[gu]id processes dump, and who should own the + * resulting corefile? And processes that can not be dumped aldo can + * not be traced. In FreeBSD, we control the setuid dump + * enable/disable system-wide with 'sugid_coredump,' and tracability + * with P2_NOTRACE (PROC_TRACE_STATUS / PROC_TRACE_CTL_DISABLE). + */ + case LINUX_PR_GET_DUMPABLE: + PROC_LOCK(p); + error = p_candump(p); + PROC_UNLOCK(p); + /* + * Indicate that a process can dump if coredumping is enabled, + * the process is not NOTRACE, and the process is not setuid, + * or if setuid, sugid_coredump is enabled. + */ + td->td_retval[0] = (error == 0); + break; + case LINUX_PR_SET_DUMPABLE: + /* + * It is only valid for userspace to set one of these two + * flags, and only one at a time. + */ + switch (args->arg2) { + case LINUX_SUID_DUMP_DISABLE: + case LINUX_SUID_DUMP_USER: + break; + default: + return (EINVAL); + } + /* + * As we do not track this configuration in any explicit + * feature flags, ignore requests to set the Linux dumpable + * bit. If we added similar functionality to native + * procctl(2), it would make sense to proxy through to that + * from the emulation layer. + */ + break; case LINUX_PR_GET_KEEPCAPS: /* * Indicate that we always clear the effective and Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -3710,6 +3710,21 @@ return (0); } +/* + * Can this process dump, as a question of policy? + */ +int +p_candump(struct proc *p) +{ + + PROC_LOCK_ASSERT(p, MA_OWNED); + + if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) || + (p->p_flag2 & P2_NOTRACE) != 0) + return (EPERM); + return (0); +} + /* * Dump a process' core. The main routine does some * policy checking, and creates the name of the coredump; @@ -3717,7 +3732,6 @@ * coredump routine if there is one; if there _is not_ one, it returns * ENOSYS; otherwise it returns the error from the process-specific routine. */ - static int coredump(struct thread *td) { @@ -3737,8 +3751,7 @@ PROC_LOCK_ASSERT(p, MA_OWNED); MPASS((p->p_flag & P_HADTHREADS) == 0 || p->p_singlethread == td); - if (!do_coredump || (!sugid_coredump && (p->p_flag & P_SUGID) != 0) || - (p->p_flag2 & P2_NOTRACE) != 0) { + if (p_candump(p) != 0) { PROC_UNLOCK(p); return (EFAULT); } Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -1061,6 +1061,7 @@ void maybe_yield(void); void mi_switch(int flags); int p_candebug(struct thread *td, struct proc *p); +int p_candump(struct proc *p); int p_cansee(struct thread *td, struct proc *p); int p_cansched(struct thread *td, struct proc *p); int p_cansignal(struct thread *td, struct proc *p, int signum);