From 7c5c742de8a8b577654964635f05d7033c92ee53 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 8 Feb 2024 12:11:18 -0800 Subject: [PATCH] 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 Tested-by: Mark Janes Tested-by: Tobias Jakobi --- xf86drm.c | 20 ++++++++++++++++++-- 1 file 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;