diff options
| author | 2011-12-14 08:33:18 +0000 | |
|---|---|---|
| committer | 2011-12-14 08:33:18 +0000 | |
| commit | d367e7f4c22908915ddc487dde1e67743eff2c23 (patch) | |
| tree | 4fff8dbd406d50d458c53934778b5faac91901e0 /sys/compat/linux/linux_misc.c | |
| parent | Handle rthreads consistently in ktrace by moving the flags and vnode into (diff) | |
| download | wireguard-openbsd-d367e7f4c22908915ddc487dde1e67743eff2c23.tar.xz wireguard-openbsd-d367e7f4c22908915ddc487dde1e67743eff2c23.zip | |
implement prctl() for COMPAT_LINUX
ok pirofti@
Diffstat (limited to 'sys/compat/linux/linux_misc.c')
| -rw-r--r-- | sys/compat/linux/linux_misc.c | 84 |
1 files changed, 83 insertions, 1 deletions
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); +} |
