summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2016-01-06 09:09:16 +0000
committerkettenis <kettenis@openbsd.org>2016-01-06 09:09:16 +0000
commitf6b590bc696749d85aad6a323b5989cc0c9ed222 (patch)
tree334a929ce1156969357425302ed9cb0f8d47b36e
parentdeactivate POOL_DEBUG for release (diff)
downloadwireguard-openbsd-f6b590bc696749d85aad6a323b5989cc0c9ed222.tar.xz
wireguard-openbsd-f6b590bc696749d85aad6a323b5989cc0c9ed222.zip
Add pledge "drm", which allows a subset of the drm(4) ioctls. These are
basically only the ioctls that Linux allows on the so-called "render nodes". For now, it also allows DRM_IOCTL_GET_MAGIC and DRM_IOCTL_GEM_OPEN, as we don't implement prime/dma-buf yet in OpenBSD. That still leaves a big gaping hole, so they will be removed as soon as we can. Based on a diff by robert@, who did all the heavy lifting by studying the behaviour of the chromium GPU process, with some further suggestions by deraadt@. ok jsg@, deraadt@, robert@
-rw-r--r--sys/dev/pci/drm/drm_drv.c38
-rw-r--r--sys/kern/kern_pledge.c23
-rw-r--r--sys/sys/conf.h3
-rw-r--r--sys/sys/pledge.h5
4 files changed, 64 insertions, 5 deletions
diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
index 867f8c56373..d5d8a4fa761 100644
--- a/sys/dev/pci/drm/drm_drv.c
+++ b/sys/dev/pci/drm/drm_drv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: drm_drv.c,v 1.142 2015/12/31 13:01:00 kettenis Exp $ */
+/* $OpenBSD: drm_drv.c,v 1.143 2016/01/06 09:09:16 kettenis Exp $ */
/*-
* Copyright 2007-2009 Owain G. Ainsworth <oga@openbsd.org>
* Copyright © 2008 Intel Corporation
@@ -44,6 +44,7 @@
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/limits.h>
+#include <sys/pledge.h>
#include <sys/poll.h>
#include <sys/specdev.h>
#include <sys/systm.h>
@@ -246,6 +247,41 @@ static struct drm_ioctl_desc drm_ioctls[] = {
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
int
+pledge_ioctl_drm(struct proc *p, long com, dev_t device)
+{
+ struct drm_device *dev = drm_get_device_from_kdev(device);
+ unsigned int nr = DRM_IOCTL_NR(com);
+ const struct drm_ioctl_desc *ioctl;
+
+ if (dev == NULL)
+ return EPERM;
+
+ if (nr < DRM_CORE_IOCTL_COUNT &&
+ ((nr < DRM_COMMAND_BASE || nr >= DRM_COMMAND_END)))
+ ioctl = &drm_ioctls[nr];
+ else if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END &&
+ nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ else
+ return EPERM;
+
+ if (ioctl->flags & DRM_RENDER_ALLOW)
+ return 0;
+
+ /*
+ * These are dangerous, but we have to allow them until we
+ * have prime/dma-buf support.
+ */
+ switch (com) {
+ case DRM_IOCTL_GET_MAGIC:
+ case DRM_IOCTL_GEM_OPEN:
+ return 0;
+ }
+
+ return EPERM;
+}
+
+int
drm_setunique(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c
index 4323a6b9e86..89808cd1178 100644
--- a/sys/kern/kern_pledge.c
+++ b/sys/kern/kern_pledge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_pledge.c,v 1.141 2016/01/05 18:09:24 deraadt Exp $ */
+/* $OpenBSD: kern_pledge.c,v 1.142 2016/01/06 09:09:16 kettenis Exp $ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -67,6 +67,11 @@
#include "audio.h"
#include "pty.h"
+#if defined(__amd64__) || defined(__i386__) || \
+ defined(__macppc__) || defined(__sparc64__)
+#include "drm.h"
+#endif
+
int pledgereq_flags(const char *req);
int canonpath(const char *input, char *buf, size_t bufsize);
int substrcmp(const char *p1, size_t s1, const char *p2, size_t s2);
@@ -338,6 +343,7 @@ static const struct {
{ "disklabel", PLEDGE_DISKLABEL },
{ "dns", PLEDGE_DNS },
{ "dpath", PLEDGE_DPATH },
+ { "drm", PLEDGE_DRM },
{ "exec", PLEDGE_EXEC },
{ "fattr", PLEDGE_FATTR },
{ "flock", PLEDGE_FLOCK },
@@ -1123,6 +1129,7 @@ int
pledge_ioctl(struct proc *p, long com, struct file *fp)
{
struct vnode *vp = NULL;
+ int error = EPERM;
if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
return (0);
@@ -1174,6 +1181,18 @@ pledge_ioctl(struct proc *p, long com, struct file *fp)
}
}
+ if ((p->p_p->ps_pledge & PLEDGE_DRM)) {
+#if NDRM > 0
+ if ((fp->f_type == DTYPE_VNODE) &&
+ (vp->v_type == VCHR) &&
+ (cdevsw[major(vp->v_rdev)].d_open == drmopen)) {
+ error = pledge_ioctl_drm(p, com, vp->v_rdev);
+ if (error == 0)
+ return 0;
+ }
+#endif /* NDRM > 0 */
+ }
+
if ((p->p_p->ps_pledge & PLEDGE_AUDIO)) {
#if NAUDIO > 0
switch (com) {
@@ -1306,7 +1325,7 @@ pledge_ioctl(struct proc *p, long com, struct file *fp)
}
}
- return pledge_fail(p, EPERM, PLEDGE_IOCTL);
+ return pledge_fail(p, error, PLEDGE_IOCTL);
}
int
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index a44b3c2eee9..9be9b67750e 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.h,v 1.135 2015/10/23 15:10:52 claudio Exp $ */
+/* $OpenBSD: conf.h,v 1.136 2016/01/06 09:09:16 kettenis Exp $ */
/* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */
/*-
@@ -529,6 +529,7 @@ cdev_decl(ptm);
cdev_decl(ctty);
cdev_decl(audio);
+cdev_decl(drm);
cdev_decl(midi);
cdev_decl(radio);
cdev_decl(video);
diff --git a/sys/sys/pledge.h b/sys/sys/pledge.h
index f01dd90a65b..cd261ec3929 100644
--- a/sys/sys/pledge.h
+++ b/sys/sys/pledge.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pledge.h,v 1.24 2015/12/06 17:50:21 deraadt Exp $ */
+/* $OpenBSD: pledge.h,v 1.25 2016/01/06 09:09:16 kettenis Exp $ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -55,6 +55,7 @@
#define PLEDGE_PF 0x0000000004000000ULL /* pf ioctls */
#define PLEDGE_AUDIO 0x0000000008000000ULL /* audio ioctls */
#define PLEDGE_DPATH 0x0000000010000000ULL /* mknod & mkfifo */
+#define PLEDGE_DRM 0x0000000020000000ULL /* drm ioctls */
/*
* Bits outside PLEDGE_USERSET are used by the kernel itself
@@ -98,6 +99,7 @@ static struct {
{ PLEDGE_PF, "pf" },
{ PLEDGE_AUDIO, "audio" },
{ PLEDGE_DPATH, "dpath" },
+ { PLEDGE_DRM, "drm" },
{ 0, NULL },
};
#endif
@@ -119,6 +121,7 @@ int pledge_sendit(struct proc *p, const void *to);
int pledge_sockopt(struct proc *p, int set, int level, int optname);
int pledge_socket(struct proc *p, int domain, int state);
int pledge_ioctl(struct proc *p, long com, struct file *);
+int pledge_ioctl_drm(struct proc *p, long com, dev_t device);
int pledge_flock(struct proc *p);
int pledge_fcntl(struct proc *p, int cmd);
int pledge_swapctl(struct proc *p);