diff options
author | Moritz Bruder <muesli4@gmail.com> | 2022-12-17 18:19:57 +0100 |
---|---|---|
committer | Matt Turner <mattst88@gmail.com> | 2023-12-17 17:21:56 +0000 |
commit | a8e41a81909ef74faa38ef12ca35c5d83f7c56a5 (patch) | |
tree | 70fdd03cab16f26f6054066e1d3b98443278f808 /hw/xfree86/fbdevhw/fbdevhw.c | |
parent | 5c8f70a17c2eea3e04f0b41a8ac59e4c60ccd8c3 (diff) |
fbdevhw: Support symbolic links in fbdev_open
Resolve symbolic links before the PCI device check in fbdev_open.
Otherwise, opening device files that are symbolic links will fail.
Fixes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1419
Signed-off-by: Moritz Bruder <muesli4@gmail.com>
Diffstat (limited to 'hw/xfree86/fbdevhw/fbdevhw.c')
-rw-r--r-- | hw/xfree86/fbdevhw/fbdevhw.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c index 3d8b92e66..8d4e3c596 100644 --- a/hw/xfree86/fbdevhw/fbdevhw.c +++ b/hw/xfree86/fbdevhw/fbdevhw.c @@ -304,6 +304,31 @@ fbdev_open_pci(struct pci_device *pPci, char **namep) return -1; } +/* * + * Try to resolve a filename as symbolic link. If the file is not a link, the + * original filename is returned. NULL is returned if readlink raised an + * error. + */ +static const char * +resolve_link(const char *filename, char *resolve_buf, size_t resolve_buf_size) +{ + ssize_t len = readlink(filename, resolve_buf, resolve_buf_size - 1); + /* if it is a link resolve it */ + if (len >= 0) { + resolve_buf[len] = '\0'; + return resolve_buf; + } + else { + if (errno == EINVAL) { + return filename; + } + else { + // Have caller handle error condition. + return NULL; + } + } +} + static int fbdev_open(int scrnIndex, const char *dev, char **namep) { @@ -331,9 +356,26 @@ fbdev_open(int scrnIndex, const char *dev, char **namep) /* only touch non-PCI devices on this path */ { + char device_path_buf[PATH_MAX]; char buf[PATH_MAX] = {0}; char *sysfs_path = NULL; - char *node = strrchr(dev, '/') + 1; + char const *real_dev = resolve_link(dev, device_path_buf, + sizeof(device_path_buf)); + if (real_dev == NULL) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Failed resolving symbolic link for device '%s': %s", + dev, strerror(errno)); + return -1; + } + + const char *node = strrchr(real_dev, '/'); + + if (node == NULL) { + node = real_dev; + } + else { + node++; + } if (asprintf(&sysfs_path, "/sys/class/graphics/%s", node) < 0 || readlink(sysfs_path, buf, sizeof(buf) - 1) < 0 || |