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) {
printf("| +-> faux\n");
printf("+-> deviceinfo\n");
printf("+-> businfo\n");
printf(" +-> faux\n");
printf(" +-> name %s\n", device->deviceinfo.faux->name);
printf(" +-> name %s\n", device->businfo.faux->name);
} else {
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;
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:
break;
@ -4472,7 +4472,7 @@ free_device:
return ret;
}
static int drmParseFauxDeviceInfo(int maj, int min, drmFauxDeviceInfoPtr info)
static int drmParseFauxBusInfo(int maj, int min, char *fullname)
{
#ifdef __linux__
char path[PATH_MAX + 1] = "";
@ -4488,13 +4488,12 @@ static int drmParseFauxDeviceInfo(int maj, int min, drmFauxDeviceInfoPtr info)
if (!name)
return -ENOENT;
info->name = strdup(name);
if (!info->name)
return -errno;
strncpy(fullname, name, DRM_FAUX_DEVICE_NAME_LEN - 1);
fullname[DRM_FAUX_DEVICE_NAME_LEN - 1] = '\0';
return 0;
#else
#warning "Missing implementation of drmParseFauxDeviceInfo"
#warning "Missing implementation of drmParseFauxBusInfo"
return -EINVAL;
#endif
}
@ -4508,17 +4507,25 @@ static int drmProcessFauxDevice(drmDevicePtr *device,
char *ptr;
int ret;
dev = drmDeviceAlloc(node_type, node, 0, sizeof(drmFauxDeviceInfo), &ptr);
dev = drmDeviceAlloc(node_type, node, sizeof(drmFauxBusInfo),
sizeof(drmFauxDeviceInfo), &ptr);
if (!dev)
return -ENOMEM;
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) {
ptr += sizeof(drmFauxBusInfo);
dev->deviceinfo.faux = (drmFauxDeviceInfoPtr)ptr;
ret = drmParseFauxDeviceInfo(maj, min, dev->deviceinfo.faux);
if (ret < 0)
dev->deviceinfo.faux->name = strdup(dev->businfo.faux->name);
if (!dev->deviceinfo.faux->name)
goto free_device;
}

View file

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