xf86drm: Fix drmDevicesEqual() for nodes on the faux bus

The name string is allocated on the heap, so the memcmp() function will
not return 0 even though two nodes share the same device name.

Also, the device info will not be populated when counting the available
drm devices. For example, using drmGetDevices2(0, NULL, 0). In that
case, drmGetDevices2() will eventually crash in drmDevicesEqual() while
merging nodes belonging to the same device due to passing null pointers
to memcmp().

This change adds faux device name to businfo. The businfo is populated
regardless whether device info is needed, which is needed to make the
drmGetDevices2(0, NULL, 0) case work. drmFauxBusInfo can also be used
with the memcmp() function to match the other cases in drmDevicesEqual().

Signed-off-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This commit is contained in:
Vlad Zahorodnii 2025-10-09 13:17:35 +03:00
parent 0a5e2c96b1
commit 1e9b50f1d5
3 changed files with 26 additions and 12 deletions

View file

@ -101,9 +101,9 @@ print_device_info(drmDevicePtr device, int i, bool print_revision)
} else if (device->bustype == DRM_BUS_FAUX) { } else if (device->bustype == DRM_BUS_FAUX) {
printf("| +-> faux\n"); printf("| +-> faux\n");
printf("+-> deviceinfo\n"); printf("+-> businfo\n");
printf(" +-> faux\n"); printf(" +-> faux\n");
printf(" +-> name %s\n", device->deviceinfo.faux->name); printf(" +-> name %s\n", device->businfo.faux->name);
} else { } else {
printf("Unknown/unhandled bustype\n"); printf("Unknown/unhandled bustype\n");
} }

View file

@ -3798,7 +3798,7 @@ drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b)
return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0;
case DRM_BUS_FAUX: case DRM_BUS_FAUX:
return memcmp(a->deviceinfo.faux, b->deviceinfo.faux, sizeof(drmFauxDeviceInfo)) == 0; return memcmp(a->businfo.faux, b->businfo.faux, sizeof(drmFauxBusInfo)) == 0;
default: default:
break; break;
@ -4472,7 +4472,7 @@ free_device:
return ret; return ret;
} }
static int drmParseFauxDeviceInfo(int maj, int min, drmFauxDeviceInfoPtr info) static int drmParseFauxBusInfo(int maj, int min, char *fullname)
{ {
#ifdef __linux__ #ifdef __linux__
char path[PATH_MAX + 1] = ""; char path[PATH_MAX + 1] = "";
@ -4488,13 +4488,12 @@ static int drmParseFauxDeviceInfo(int maj, int min, drmFauxDeviceInfoPtr info)
if (!name) if (!name)
return -ENOENT; return -ENOENT;
info->name = strdup(name); strncpy(fullname, name, DRM_FAUX_DEVICE_NAME_LEN - 1);
if (!info->name) fullname[DRM_FAUX_DEVICE_NAME_LEN - 1] = '\0';
return -errno;
return 0; return 0;
#else #else
#warning "Missing implementation of drmParseFauxDeviceInfo" #warning "Missing implementation of drmParseFauxBusInfo"
return -EINVAL; return -EINVAL;
#endif #endif
} }
@ -4508,17 +4507,25 @@ static int drmProcessFauxDevice(drmDevicePtr *device,
char *ptr; char *ptr;
int ret; int ret;
dev = drmDeviceAlloc(node_type, node, 0, sizeof(drmFauxDeviceInfo), &ptr); dev = drmDeviceAlloc(node_type, node, sizeof(drmFauxBusInfo),
sizeof(drmFauxDeviceInfo), &ptr);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
dev->bustype = DRM_BUS_FAUX; dev->bustype = DRM_BUS_FAUX;
dev->businfo.faux = (drmFauxBusInfoPtr)ptr;
ret = drmParseFauxBusInfo(maj, min, dev->businfo.faux->name);
if (ret < 0)
goto free_device;
if (fetch_deviceinfo) { if (fetch_deviceinfo) {
ptr += sizeof(drmFauxBusInfo);
dev->deviceinfo.faux = (drmFauxDeviceInfoPtr)ptr; dev->deviceinfo.faux = (drmFauxDeviceInfoPtr)ptr;
ret = drmParseFauxDeviceInfo(maj, min, dev->deviceinfo.faux); dev->deviceinfo.faux->name = strdup(dev->businfo.faux->name);
if (ret < 0) if (!dev->deviceinfo.faux->name)
goto free_device; goto free_device;
} }

View file

@ -890,8 +890,14 @@ typedef struct _drmHost1xDeviceInfo {
char **compatible; /* NULL terminated list of compatible strings */ char **compatible; /* NULL terminated list of compatible strings */
} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; } drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr;
#define DRM_FAUX_DEVICE_NAME_LEN 512
typedef struct _drmFauxBusInfo {
char name[DRM_FAUX_DEVICE_NAME_LEN];
} drmFauxBusInfo, *drmFauxBusInfoPtr;
typedef struct _drmFauxDeviceInfo { typedef struct _drmFauxDeviceInfo {
char *name; char *name; /* deprecated, use drmFauxBusInfo::name instead */
} drmFauxDeviceInfo, *drmFauxDeviceInfoPtr; } drmFauxDeviceInfo, *drmFauxDeviceInfoPtr;
typedef struct _drmDevice { typedef struct _drmDevice {
@ -903,6 +909,7 @@ typedef struct _drmDevice {
drmUsbBusInfoPtr usb; drmUsbBusInfoPtr usb;
drmPlatformBusInfoPtr platform; drmPlatformBusInfoPtr platform;
drmHost1xBusInfoPtr host1x; drmHost1xBusInfoPtr host1x;
drmFauxBusInfoPtr faux;
} businfo; } businfo;
union { union {
drmPciDeviceInfoPtr pci; drmPciDeviceInfoPtr pci;