summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_misc.c
diff options
context:
space:
mode:
authorrobert <robert@openbsd.org>2011-12-14 08:33:18 +0000
committerrobert <robert@openbsd.org>2011-12-14 08:33:18 +0000
commitd367e7f4c22908915ddc487dde1e67743eff2c23 (patch)
tree4fff8dbd406d50d458c53934778b5faac91901e0 /sys/compat/linux/linux_misc.c
parentHandle rthreads consistently in ktrace by moving the flags and vnode into (diff)
downloadwireguard-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.c84
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);
+}