diff options
author | Robert Nagy <robert@cvs.openbsd.org> | 2011-12-14 08:33:19 +0000 |
---|---|---|
committer | Robert Nagy <robert@cvs.openbsd.org> | 2011-12-14 08:33:19 +0000 |
commit | 28418b9c18a7140add5f1412afc87f068dcdfb0e (patch) | |
tree | 1bf3bb32588836160d7be4d8f7e34367970dd2fc | |
parent | 24411f6f435ea431230a0ce4d62b6e8c4a67208e (diff) |
implement prctl() for COMPAT_LINUX
ok pirofti@
-rw-r--r-- | sys/compat/linux/linux_dummy.c | 3 | ||||
-rw-r--r-- | sys/compat/linux/linux_emuldata.h | 3 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 84 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.h | 15 | ||||
-rw-r--r-- | sys/compat/linux/syscalls.master | 6 |
5 files changed, 104 insertions, 7 deletions
diff --git a/sys/compat/linux/linux_dummy.c b/sys/compat/linux/linux_dummy.c index d77613043cd..983e76fceb2 100644 --- a/sys/compat/linux/linux_dummy.c +++ b/sys/compat/linux/linux_dummy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_dummy.c,v 1.18 2011/11/25 10:10:05 robert Exp $ */ +/* $OpenBSD: linux_dummy.c,v 1.19 2011/12/14 08:33:18 robert Exp $ */ /*- * Copyright (c) 1994-1995 Søren Schmidt @@ -99,7 +99,6 @@ DUMMY(sched_rr_get_interval); /* #161 */ DUMMY(vm86); /* #166 */ DUMMY(query_module); /* #167 */ DUMMY(nfsservctl); /* #169 */ -DUMMY(prctl); /* #172 */ DUMMY(rt_sigtimedwait); /* #177 */ DUMMY(rt_queueinfo); /* #178 */ DUMMY(capget); /* #184 */ diff --git a/sys/compat/linux/linux_emuldata.h b/sys/compat/linux/linux_emuldata.h index 63b22d1e498..783327715cb 100644 --- a/sys/compat/linux/linux_emuldata.h +++ b/sys/compat/linux/linux_emuldata.h @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_emuldata.h,v 1.7 2011/09/18 02:23:18 pirofti Exp $ */ +/* $OpenBSD: linux_emuldata.h,v 1.8 2011/12/14 08:33:18 robert Exp $ */ /* $NetBSD: linux_emuldata.h,v 1.4 2002/02/15 16:48:02 christos Exp $ */ /*- * Copyright (c) 1998,2002 The NetBSD Foundation, Inc. @@ -51,5 +51,6 @@ struct linux_emuldata { struct linux_robust_list_head *led_robust_head; + int pdeath_signal; /* parent death signal */ }; #endif /* !_LINUX_EMULDATA_H_ */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 57020d126fa..ffa718dc1be 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_misc.c,v 1.72 2011/07/09 00:10:52 deraadt Exp $ */ +/* $OpenBSD: linux_misc.c,v 1.73 2011/12/14 08:33:18 robert Exp $ */ /* $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $ */ /*- @@ -1481,3 +1481,85 @@ linux_sys_swapon(struct proc *p, void *v, register_t *retval) SCARG(&ua, misc) = 0; /* priority */ return (sys_swapctl(p, &ua, retval)); } + +int +linux_sys_prctl(struct proc *p, void *v, register_t *retval) +{ + int error = 0, max_size, pdeath_signal; + char comm[LINUX_MAX_COMM_LEN]; + struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata; + + struct linux_sys_prctl_args /* { + int option; + unsigned long arg2; + unsigned long arg3; + unsigned long arg4; + unsigned long arg5; + } */ *uap = v; + + switch (SCARG(uap, option)) { + case LINUX_PR_SET_PDEATHSIG: + if (SCARG(uap, arg2) < 0 || SCARG(uap, arg2) >= LINUX__NSIG) + return (EINVAL); + ed->pdeath_signal = SCARG(uap, arg2); + break; + case LINUX_PR_GET_PDEATHSIG: + pdeath_signal = ed->pdeath_signal; + error = copyout(&pdeath_signal, (void *)SCARG(uap, arg2), + sizeof(pdeath_signal)); + break; + case LINUX_PR_GET_KEEPCAPS: + /* + * Indicate that we always clear the effective and + * permitted capability sets when the user id becomes + * non-zero (actually the capability sets are simply + * always zero in the current implementation). + */ + *retval = 0; + break; + case LINUX_PR_SET_KEEPCAPS: + /* Ignore requests to keep the effective and permitted + * capability sets when the user id becomes non-zero. + */ + break; + case LINUX_PR_SET_NAME: + /* + * To be on the safe side we need to make sure not to + * overflow the size a linux program expects. We already + * do this here in the copyin, so that we don't need to + * check on copyout. + */ + max_size = MIN(sizeof(comm), sizeof(p->p_comm)); + error = copyinstr((void *)SCARG(uap, arg2), comm, + max_size, NULL); + + /* Linux silently truncates the name if it is too long. */ + if (error == ENAMETOOLONG) { + /* + * XXX: copyinstr() isn't documented to populate the + * array completely, so do a copyin() to be on the + * safe side. This should be changed in case copyinstr() + * is changed to guarantee this. + */ + error = copyin((void *)SCARG(uap, arg2), comm, + max_size - 1); + comm[max_size - 1] = '\0'; + } + if (error) + return (error); + strlcpy(p->p_comm, comm, sizeof(p->p_comm)); + break; + case LINUX_PR_GET_NAME: + strlcpy(comm, p->p_comm, sizeof(comm)); + error = copyout(comm, (void *)SCARG(uap, arg2), + strlen(comm) + 1); + break; + default: + printf("linux_sys_prctl: unsupported option %d\n", + SCARG(uap, option)); + error = EINVAL; + break; + } + + return (error); +} diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h index a4fd5c17baa..a556cba3159 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_misc.h,v 1.5 2011/04/05 22:54:30 pirofti Exp $ */ +/* $OpenBSD: linux_misc.h,v 1.6 2011/12/14 08:33:18 robert Exp $ */ /* $NetBSD: linux_misc.h,v 1.3 1999/05/13 00:31:57 thorpej Exp $ */ /*- @@ -33,6 +33,19 @@ #ifndef _LINUX_MISC_H_ #define _LINUX_MISC_H_ +/* defined for prctl(2) */ +#define LINUX_PR_SET_PDEATHSIG 1 /* Second arg is signal. */ +#define LINUX_PR_GET_PDEATHSIG 2 /* + * Second arg is a ptr to return the + * signal. + */ +#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. */ +#define LINUX_PR_GET_NAME 16 /* Get process name. */ + +#define LINUX_MAX_COMM_LEN 16 /* Maximum length of process name. */ + /* This looks very unportable to me, but this is how Linux defines it. */ struct linux_sysinfo { long uptime; diff --git a/sys/compat/linux/syscalls.master b/sys/compat/linux/syscalls.master index ed1132c5358..78c776f17c0 100644 --- a/sys/compat/linux/syscalls.master +++ b/sys/compat/linux/syscalls.master @@ -1,4 +1,4 @@ - $OpenBSD: syscalls.master,v 1.65 2011/11/25 10:10:05 robert Exp $ + $OpenBSD: syscalls.master,v 1.66 2011/12/14 08:33:18 robert Exp $ ; $NetBSD: syscalls.master,v 1.15 1995/12/18 14:35:10 fvdl Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -286,7 +286,9 @@ u_int16_t egid, u_int16_t sgid); } 171 STD { int linux_sys_getresgid16(u_int16_t *rgid, \ u_int16_t *egid, u_int16_t *sgid); } -172 STD { int linux_sys_prctl(void); } +172 STD { int linux_sys_prctl(int option, unsigned long arg2, \ + unsigned long arg3, unsigned long arg4, \ + unsigned long arg5); } 173 STD { int linux_sys_rt_sigreturn( \ struct linux_rt_sigframe *sfp); } 174 STD { int linux_sys_rt_sigaction(int signum, \ |