diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c index 4376dcb..5ce6073 100644 --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -120,6 +120,8 @@ extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); static register_t * linux_copyout_strings(struct image_params *imgp); +static int linux_coredump(struct thread *td, struct vnode *vp, + off_t limit, int flags); static int elf_linux_fixup(register_t **stack_base, struct image_params *iparams); static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel); @@ -794,6 +796,20 @@ linux_vsyscall(struct thread *td) return (0); } +static int +linux_coredump(struct thread *td, struct vnode *vp, off_t limit, int flags) +{ + struct linux_pemuldata *pem; + + pem = pem_find(td->td_proc); + KASSERT(pem != NULL, ("linux_coredump: proc emuldata not found.\n")); + + if (pem->flags & LINUX_FNONDUMPABLE) + return (ENOSYS); + + return (__elfN(coredump)(td, vp, limit, flags)); +} + struct sysentvec elf_linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, @@ -806,7 +822,7 @@ struct sysentvec elf_linux_sysvec = { .sv_sigcode = &_binary_linux_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF64", - .sv_coredump = elf64_coredump, + .sv_coredump = linux_coredump, .sv_imgact_try = exec_linux_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index 60b7033..f46543f 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -122,6 +122,8 @@ SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); static int elf_linux_fixup(register_t **stack_base, struct image_params *iparams); static register_t *linux_copyout_strings(struct image_params *imgp); +static int linux_coredump(struct thread *td, struct vnode *vp, + off_t limit, int flags); static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack); @@ -1007,6 +1009,20 @@ linux32_fixlimit(struct rlimit *rl, int which) } } +static int +linux_coredump(struct thread *td, struct vnode *vp, off_t limit, int flags) +{ + struct linux_pemuldata *pem; + + pem = pem_find(td->td_proc); + KASSERT(pem != NULL, ("linux_coredump: proc emuldata not found.\n")); + + if (pem->flags & LINUX_FNONDUMPABLE) + return (ENOSYS); + + return (__elfN(coredump)(td, vp, limit, flags)); +} + struct sysentvec elf_linux_sysvec = { .sv_size = LINUX32_SYS_MAXSYSCALL, .sv_table = linux32_sysent, @@ -1019,7 +1035,7 @@ struct sysentvec elf_linux_sysvec = { .sv_sigcode = &_binary_linux32_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF32", - .sv_coredump = elf32_coredump, + .sv_coredump = linux_coredump, .sv_imgact_try = exec_linux_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE, diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h index 7262093..7c25425 100644 --- a/sys/compat/linux/linux_emul.h +++ b/sys/compat/linux/linux_emul.h @@ -62,6 +62,11 @@ int linux_common_execve(struct thread *, struct image_args *); futex REQUEUE op*/ #define LINUX_XUNSUP_EPOLL 0x00000002 /* unsupported epoll events */ #define LINUX_XUNSUP_FUTEXPIOP 0x00000004 /* uses unsupported pi futex */ +#define LINUX_FNONDUMPABLE 0x00000008 /* state of the "dumpable" + flag, which determines + whether core dumps are + produced + */ struct linux_pemuldata { uint32_t flags; /* process emuldata flags */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index fe4dbf6..180da40 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1945,6 +1945,7 @@ linux_prctl(struct thread *td, struct linux_prctl_args *args) int error = 0, max_size; struct proc *p = td->td_proc; char comm[LINUX_MAX_COMM_LEN]; + struct linux_pemuldata *pem; struct linux_emuldata *em; int pdeath_signal; @@ -2023,6 +2024,27 @@ linux_prctl(struct thread *td, struct linux_prctl_args *args) error = copyout(comm, (void *)(register_t)args->arg2, strlen(comm) + 1); break; + case LINUX_PR_SET_DUMPABLE: + if (args->arg2 != LINUX_SUID_DUMP_DISABLE || + args->arg2 != LINUX_SUID_DUMP_USER) + return (EINVAL); + pem = pem_find(td->td_proc); + PROC_LOCK(p); + if (args->arg2 == LINUX_SUID_DUMP_DISABLE) + pem->flags |= LINUX_FNONDUMPABLE; + else + pem->flags &= ~LINUX_FNONDUMPABLE; + PROC_UNLOCK(p); + break; + case LINUX_PR_GET_DUMPABLE: + pem = pem_find(td->td_proc); + PROC_LOCK(p); + if (pem->flags & LINUX_FNONDUMPABLE) + td->td_retval[0] = 0; + else + td->td_retval[0] = 1; + PROC_UNLOCK(p); + break; default: error = EINVAL; break; diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h index 08bc85f..c2d6065 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -50,6 +50,13 @@ * Second arg is a ptr to return the * signal. */ +#define LINUX_PR_SET_DUMPABLE 3 /* Second arg is a SUID_DUMP flag. */ +#define LINUX_PR_GET_DUMPABLE 4 + +/* for [S|G]ET_DUMPABLE */ +#define LINUX_SUID_DUMP_DISABLE 0 /* No setuid dumping. */ +#define LINUX_SUID_DUMP_USER 1 /* Dump as user of a process. */ + #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. */ diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 886200c..6e868f7 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -118,6 +118,8 @@ static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void exec_linux_setregs(struct thread *td, struct image_params *imgp, u_long stack); static register_t *linux_copyout_strings(struct image_params *imgp); +static int linux_coredump(struct thread *td, struct vnode *vp, + off_t limit, int flags); static boolean_t linux_trans_osrel(const Elf_Note *note, int32_t *osrel); static void linux_vdso_install(void *param); static void linux_vdso_deinstall(void *param); @@ -952,6 +954,20 @@ linux_get_machine(const char **dst) } } +static int +linux_coredump(struct thread *td, struct vnode *vp, off_t limit, int flags) +{ + struct linux_pemuldata *pem; + + pem = pem_find(td->td_proc); + KASSERT(pem != NULL, ("linux_coredump: proc emuldata not found.\n")); + + if (pem->flags & LINUX_FNONDUMPABLE) + return (ENOSYS); + + return (__elfN(coredump)(td, vp, limit, flags)); +} + struct sysentvec linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, @@ -1001,7 +1017,7 @@ struct sysentvec elf_linux_sysvec = { .sv_sigcode = &_binary_linux_locore_o_start, .sv_szsigcode = &linux_szsigcode, .sv_name = "Linux ELF", - .sv_coredump = elf32_coredump, + .sv_coredump = linux_coredump, .sv_imgact_try = exec_linux_imgact_try, .sv_minsigstksz = LINUX_MINSIGSTKSZ, .sv_pagesize = PAGE_SIZE,