From 70e601267b0264a3e6c42656517870cd0b021372 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Tue, 30 Apr 2019 18:18:18 +0200 Subject: [PATCH] daemon: use readlink not realpath to find the exe The realpath(3) will fail if the target does not exist (internally realpath will stat all the components of the link target path). This is a problem in the case of sandbox applications where the exe points to the absolute path *inside* the sandbox, e.g. to /app/bin/ in the case of flatpak. For these cases realpath(3) will then fail. Therefore use readlink(3) instead. --- daemon/gamemode.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/daemon/gamemode.c b/daemon/gamemode.c index 9855fe6..e8fab8b 100644 --- a/daemon/gamemode.c +++ b/daemon/gamemode.c @@ -40,10 +40,14 @@ POSSIBILITY OF SUCH DAMAGE. #include "helpers.h" #include "logging.h" +#include #include #include #include +#include +#include #include +#include /** * The GameModeClient encapsulates the remote connection, providing a list @@ -650,15 +654,31 @@ static char *game_mode_context_find_exe(pid_t pid) { char buffer[PATH_MAX]; char *proc_path = NULL, *wine_exe = NULL; + autoclose_fd int pidfd = -1; + ssize_t r; - if (!(proc_path = buffered_snprintf(buffer, "/proc/%d/exe", pid))) + if (!(proc_path = buffered_snprintf(buffer, "/proc/%d", pid))) goto fail; - /* Allocate the realpath if possible */ - char *exe = realpath(proc_path, NULL); - if (!exe) + /* Translate /proc//exe to the application binary */ + pidfd = openat(AT_FDCWD, proc_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); + if (pidfd == -1) goto fail; + r = readlinkat(pidfd, "exe", buffer, sizeof(buffer)); + + if (r == sizeof(buffer)) { + errno = ENAMETOOLONG; + r = -1; + } + + if (r == -1) + goto fail; + + buffer[r] = '\0'; + + char *exe = strdup(buffer); + /* Detect if the process is a wine loader process */ if (game_mode_detect_wine_preloader(exe)) { LOG_MSG("Detected wine preloader for client %d [%s].\n", pid, exe);