Sun Apr 21 03:02:51 2024 UTC (19d)
drm: Allow DRM_IOCTL_GET_UNIQUE on render nodes.

On NetBSD, libdrm uses this to discover what kind of bus the device
is on, without which it refuses to expose the render node at all,
rendering it useless.  With this change, libdrm is able to use render
nodes on NetBSD.

Since this is just reading out information about the bus type and
bus/dev/func numbers, I don't think it's problematic to expose to
render nodes.

This requires tweaking the access path to the master.

PR kern/58180


(riastradh)
diff -r1.24 -r1.25 src/sys/external/bsd/drm2/dist/drm/drm_ioctl.c

cvs diff -r1.24 -r1.25 src/sys/external/bsd/drm2/dist/drm/drm_ioctl.c (expand / switch to unified diff)

--- src/sys/external/bsd/drm2/dist/drm/drm_ioctl.c 2022/10/15 15:19:28 1.24
+++ src/sys/external/bsd/drm2/dist/drm/drm_ioctl.c 2024/04/21 03:02:51 1.25
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $ */ 1/* $NetBSD: drm_ioctl.c,v 1.25 2024/04/21 03:02:51 riastradh Exp $ */
2 2
3/* 3/*
4 * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com 4 * Created: Fri Jan 8 09:01:26 1999 by faith@valinux.com
5 * 5 *
6 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 6 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
7 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 7 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8 * All Rights Reserved. 8 * All Rights Reserved.
9 * 9 *
10 * Author Rickard E. (Rik) Faith <faith@valinux.com> 10 * Author Rickard E. (Rik) Faith <faith@valinux.com>
11 * Author Gareth Hughes <gareth@valinux.com> 11 * Author Gareth Hughes <gareth@valinux.com>
12 * 12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a 13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"), 14 * copy of this software and associated documentation files (the "Software"),
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * paragraph) shall be included in all copies or substantial portions of the 21 * paragraph) shall be included in all copies or substantial portions of the
22 * Software. 22 * Software.
23 * 23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 27 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE. 30 * OTHER DEALINGS IN THE SOFTWARE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.24 2022/10/15 15:19:28 riastradh Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,v 1.25 2024/04/21 03:02:51 riastradh Exp $");
35 35
36#include <linux/export.h> 36#include <linux/export.h>
37#include <linux/nospec.h> 37#include <linux/nospec.h>
38#include <linux/pci.h> 38#include <linux/pci.h>
39#include <linux/uaccess.h> 39#include <linux/uaccess.h>
40#include <linux/capability.h> 40#include <linux/capability.h>
41 41
42#ifdef __NetBSD__ 42#ifdef __NetBSD__
43#include <sys/types.h> 43#include <sys/types.h>
44#include <sys/file.h> 44#include <sys/file.h>
45#endif 45#endif
46 46
47#include <drm/drm_agpsupport.h> 47#include <drm/drm_agpsupport.h>
@@ -119,39 +119,55 @@ __KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c, @@ -119,39 +119,55 @@ __KERNEL_RCSID(0, "$NetBSD: drm_ioctl.c,
119 * 119 *
120 * \param inode device inode. 120 * \param inode device inode.
121 * \param file_priv DRM file private. 121 * \param file_priv DRM file private.
122 * \param cmd command. 122 * \param cmd command.
123 * \param arg user argument, pointing to a drm_unique structure. 123 * \param arg user argument, pointing to a drm_unique structure.
124 * \return zero on success or a negative number on failure. 124 * \return zero on success or a negative number on failure.
125 * 125 *
126 * Copies the bus id from drm_device::unique into user space. 126 * Copies the bus id from drm_device::unique into user space.
127 */ 127 */
128int drm_getunique(struct drm_device *dev, void *data, 128int drm_getunique(struct drm_device *dev, void *data,
129 struct drm_file *file_priv) 129 struct drm_file *file_priv)
130{ 130{
131 struct drm_unique *u = data; 131 struct drm_unique *u = data;
132 struct drm_master *master = file_priv->master; 132 struct drm_master *master;
 133 int ret;
133 134
134 mutex_lock(&master->dev->master_mutex); 135 mutex_lock(&dev->master_mutex);
135 if (u->unique_len >= master->unique_len) { 136 master = dev->master;
136 if (copy_to_user(u->unique, master->unique, master->unique_len)) { 137 if (master == NULL) {
137 mutex_unlock(&master->dev->master_mutex); 138 ret = -ENXIO;
138 return -EFAULT; 139 goto out;
139 } 140 }
 141
 142 /*
 143 * Copy out only if the user allocated enough space. Either
 144 * way, on success, report the actual size -- so the user can
 145 * allocate enough space if they didn't before, or so they know
 146 * exactly how much we copied out.
 147 */
 148 if (u->unique_len < master->unique_len) {
 149 ret = 0;
 150 } else {
 151 ret = copy_to_user(u->unique, master->unique,
 152 master->unique_len);
 153 if (ret)
 154 goto out;
140 } 155 }
141 u->unique_len = master->unique_len; 156 u->unique_len = master->unique_len;
142 mutex_unlock(&master->dev->master_mutex); 
143 157
144 return 0; 158out: mutex_unlock(&dev->master_mutex);
 159
 160 return ret;
145} 161}
146 162
147static void 163static void
148drm_unset_busid(struct drm_device *dev, 164drm_unset_busid(struct drm_device *dev,
149 struct drm_master *master) 165 struct drm_master *master)
150{ 166{
151 kfree(master->unique); 167 kfree(master->unique);
152 master->unique = NULL; 168 master->unique = NULL;
153 master->unique_len = 0; 169 master->unique_len = 0;
154} 170}
155 171
156static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) 172static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
157{ 173{
@@ -587,27 +603,27 @@ EXPORT_SYMBOL(drm_ioctl_permit); @@ -587,27 +603,27 @@ EXPORT_SYMBOL(drm_ioctl_permit);
587 .flags = _flags, \ 603 .flags = _flags, \
588 .name = #ioctl \ 604 .name = #ioctl \
589 } 605 }
590 606
591#if IS_ENABLED(CONFIG_DRM_LEGACY) 607#if IS_ENABLED(CONFIG_DRM_LEGACY)
592#define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, _func, _flags) 608#define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, _func, _flags)
593#else 609#else
594#define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, drm_invalid_op, _flags) 610#define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, drm_invalid_op, _flags)
595#endif 611#endif
596 612
597/* Ioctl table */ 613/* Ioctl table */
598static const struct drm_ioctl_desc drm_ioctls[] = { 614static const struct drm_ioctl_desc drm_ioctls[] = {
599 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW), 615 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW),
600 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), 616 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, DRM_RENDER_ALLOW),
601 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), 617 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
602 DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), 618 DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
603 619
604 DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0), 620 DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0),
605 621
606 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), 622 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
607 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), 623 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
608 DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW), 624 DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW),
609 DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), 625 DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0),
610 DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), 626 DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
611 627
612 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 628 DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
613 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 629 DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),