summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDylan Baker <dylan@pnwbakers.com>2024-02-08 12:11:18 -0800
committerDylan Baker <dylan@pnwbakers.com>2024-02-12 12:03:21 -0800
commit7c5c742de8a8b577654964635f05d7033c92ee53 (patch)
treede508a0087272a643ce70e423f7b883ae375248c
parent1aa800d4644cd2ac8ab7683ffe8a1265108fcc7f (diff)
xf86drm: Don't consider node names longer than the maximum allowed
This fixes the logic that decides if a node name is valid to use the same length restrictions that are used in drmDeviceAlloc, which expects node names to conform to a specific naming scheme (On OSes except OpenBSD this means `/dev/dri/renderD123`). This addresses the problem of node names that are longer than expected, while still allowing symlinks to work. I've also applied the same fix to the OpenBSD path, while bringing the check that `snprintf` didn't error from OpenBSD to the main path. Signed-off-by: Dylan Baker <dylan.c.baker@intel.com> Tested-by: Mark Janes <markjanes@swizzler.org> Tested-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de>
-rw-r--r--xf86drm.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/xf86drm.c b/xf86drm.c
index 2e76f0ea..1c871106 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -4471,14 +4471,24 @@ process_device(drmDevicePtr *device, const char *d_name,
{
struct stat sbuf;
char node[PATH_MAX + 1];
- int node_type, subsystem_type;
+ int node_type, subsystem_type, written;
unsigned int maj, min;
+ const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
node_type = drmGetNodeType(d_name);
if (node_type < 0)
return -1;
- snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
+ written = snprintf(node, PATH_MAX, "%s/%s", DRM_DIR_NAME, d_name);
+ if (written < 0)
+ return -1;
+
+ /* anything longer than this will be truncated in drmDeviceAlloc.
+ * Account for NULL byte
+ */
+ if (written + 1 > max_node_length)
+ return -1;
+
if (stat(node, &sbuf))
return -1;
@@ -4585,6 +4595,7 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
const char *dev_name;
int node_type, subsystem_type;
int maj, min, n, ret;
+ const int max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
if (device == NULL)
return -EINVAL;
@@ -4603,9 +4614,14 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
if (!dev_name)
return -EINVAL;
+ /* anything longer than this will be truncated in drmDeviceAlloc.
+ * Account for NULL byte
+ */
n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
if (n == -1 || n >= PATH_MAX)
return -errno;
+ if (written + 1 > max_node_length)
+ return -EINVAL
if (stat(node, &sbuf))
return -EINVAL;