summaryrefslogtreecommitdiff
path: root/hw/xfree86/fbdevhw/fbdevhw.c
diff options
context:
space:
mode:
authorMoritz Bruder <muesli4@gmail.com>2022-12-17 18:19:57 +0100
committerMatt Turner <mattst88@gmail.com>2023-12-17 17:21:56 +0000
commita8e41a81909ef74faa38ef12ca35c5d83f7c56a5 (patch)
tree70fdd03cab16f26f6054066e1d3b98443278f808 /hw/xfree86/fbdevhw/fbdevhw.c
parent5c8f70a17c2eea3e04f0b41a8ac59e4c60ccd8c3 (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.c44
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 ||