From: Oliver Kurth Date: Tue, 24 Apr 2018 00:08:18 +0000 (-0700) Subject: [Wayland DnD] Part2: Open the uinput device file with root permission. X-Git-Tag: stable-10.3.0~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa59d16e0b5968efc298065ef50ece282d406265;p=thirdparty%2Fopen-vm-tools.git [Wayland DnD] Part2: Open the uinput device file with root permission. The device file /dev/uinput (or /dev/input/uinput) can only be accessed by root account, so the dndcp plugin may failed to open this device file if the current user is not root account. A way to fix this issue is opening this device file with root account, then pass the file descriptor to the sub task which is started with the current account. An example for this solution is blockVM file system device file. This patch is part of the new feature 'Wayland support in Linux guest'. --- diff --git a/open-vm-tools/lib/include/vmware/tools/plugin.h b/open-vm-tools/lib/include/vmware/tools/plugin.h index 17f7cfd79..76b07c572 100644 --- a/open-vm-tools/lib/include/vmware/tools/plugin.h +++ b/open-vm-tools/lib/include/vmware/tools/plugin.h @@ -259,6 +259,8 @@ typedef struct ToolsAppCtx { #else /** The FD to access the VMware blocking fs. -1 if no FD available. */ int blockFD; + /** The FD to access the uinput. -1 if no FD available. */ + int uinputFD; /** The native environment (without any VMware modifications). */ const char **envp; #endif diff --git a/open-vm-tools/services/vmtoolsd/cmdLine.c b/open-vm-tools/services/vmtoolsd/cmdLine.c index ee40b2611..17ac5a112 100644 --- a/open-vm-tools/services/vmtoolsd/cmdLine.c +++ b/open-vm-tools/services/vmtoolsd/cmdLine.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2008-2017 VMware, Inc. All rights reserved. + * Copyright (C) 2008-2018 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -260,6 +260,9 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state, { "blockFd", '\0', 0, G_OPTION_ARG_INT, &state->ctx.blockFD, SU_(cmdline.blockfd, "File descriptor for the VMware blocking fs."), SU_(cmdline.blockfd.fd, "fd") }, + { "uinputFd", '\0', 0, G_OPTION_ARG_INT, &state->ctx.uinputFD, + SU_(cmdline.uinputfd, "File descriptor for the uinput device."), + SU_(cmdline.uinputfd.fd, "fd") }, #endif { "config", 'c', 0, G_OPTION_ARG_FILENAME, &state->configFile, SU_(cmdline.config, "Uses the config file at the given path."), @@ -280,6 +283,7 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state, #if !defined(G_PLATFORM_WIN32) state->ctx.blockFD = -1; + state->ctx.uinputFD = -1; #endif /* @@ -344,12 +348,17 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state, exit(ToolsCoreSignalEvent(state->name, DUMP_STATE_EVENT_NAME_FMT) ? 0 : 1); } #else - /* If not running the "vmusr" service, ignore the blockFd parameter. */ + /* If not running the "vmusr" service, ignore the blockFd and uinputFd parameter. */ if (!TOOLS_IS_USER_SERVICE(state)) { if (state->ctx.blockFD >= 0) { close(state->ctx.blockFD); } state->ctx.blockFD = -1; + + if (state->ctx.uinputFD >= 0) { + close(state->ctx.uinputFD); + } + state->ctx.uinputFD = -1; } #endif diff --git a/open-vm-tools/vmware-user-suid-wrapper/main.c b/open-vm-tools/vmware-user-suid-wrapper/main.c index 2e4cabf22..e9d7e5084 100644 --- a/open-vm-tools/vmware-user-suid-wrapper/main.c +++ b/open-vm-tools/vmware-user-suid-wrapper/main.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2007-2017 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2018 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -20,12 +20,14 @@ /* * main.c -- * - * This program is run as root to prepare the system for vmware-user. It - * unmounts the vmblock file system, unloads the vmblock module, then - * reloads the module, mounts the file system, and opens a file descriptor - * that vmware-user can use to add and remove blocks. This must all - * happen as root since we cannot allow any random process to add and - * remove blocks in the blocking file system. + * This program is run as root to prepare the system for vmware-user. + * - It unmounts the vmblock file system, unloads the vmblock module, then + * reloads the module, mounts the file system, and opens a file descriptor + * that vmware-user can use to add and remove blocks. + * This must all happen as root since we cannot allow any random process + * to add and remove blocks in the blocking file system. + * - It opens the uinput device file and passes the file descriptor to + * vmware-user. */ #if !defined(sun) && !defined(__FreeBSD__) && !defined(__linux__) @@ -173,11 +175,16 @@ StartVMwareUser(char *const envp[]) pid_t pid; uid_t uid; gid_t gid; - int fd = -1; + int blockFd = -1; + char blockFdStr[8]; + int uinputFd = -1; + char uinputFdStr[8]; int ret; char path[MAXPATHLEN]; - char *argv[6]; + char *argv[8]; size_t idx = 0; + char *xdgSessionType; + Bool useWayland = FALSE; if (!BuildExecPath(path, sizeof path)) { return FALSE; @@ -198,15 +205,28 @@ StartVMwareUser(char *const envp[]) /* Child */ + xdgSessionType = getenv("XDG_SESSION_TYPE"); + if ( (xdgSessionType != NULL) + && (strstr(xdgSessionType, "wayland") != NULL)) { + useWayland = TRUE; + } + /* * We know the file system is mounted and want to keep this suid * root wrapper as small as possible, so here we directly open(2) the * "device" instead of calling DnD_InitializeBlocking() and bringing along * a whole host of libs. */ - fd = open(VMBLOCK_FUSE_DEVICE, VMBLOCK_FUSE_DEVICE_MODE); - if (fd < 0) { - fd = open(VMBLOCK_DEVICE, VMBLOCK_DEVICE_MODE); + blockFd = open(VMBLOCK_FUSE_DEVICE, VMBLOCK_FUSE_DEVICE_MODE); + if (blockFd < 0) { + blockFd = open(VMBLOCK_DEVICE, VMBLOCK_DEVICE_MODE); + } + + if (useWayland) { + uinputFd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinputFd < 0) { + uinputFd = open("/dev/input/uinput", O_WRONLY | O_NONBLOCK); + } } uid = getuid(); @@ -215,8 +235,13 @@ StartVMwareUser(char *const envp[]) if ((setreuid(uid, uid) != 0) || (setregid(gid, gid) != 0)) { Error("could not drop privileges: %s\n", strerror(errno)); - if (fd != -1) { - close(fd); + if (blockFd != -1) { + close(blockFd); + } + if (useWayland) { + if (uinputFd != -1) { + close(uinputFd); + } } return FALSE; } @@ -231,17 +256,29 @@ StartVMwareUser(char *const envp[]) argv[idx++] = "-n"; argv[idx++] = "vmusr"; - if (fd < 0) { + if (blockFd < 0) { Error("could not open %s\n", VMBLOCK_DEVICE); } else { - char fdStr[8]; - - ret = snprintf(fdStr, sizeof fdStr, "%d", fd); - if (ret == 0 || ret >= sizeof fdStr) { - Error("could not parse file descriptor (%d)\n", fd); + ret = snprintf(blockFdStr, sizeof blockFdStr, "%d", blockFd); + if (ret == 0 || ret >= sizeof blockFdStr) { + Error("could not parse file descriptor (%d)\n", blockFd); } else { argv[idx++] = "--blockFd"; - argv[idx++] = fdStr; + argv[idx++] = blockFdStr; + } + } + + if (useWayland) { + if (uinputFd < 0) { + Error("could not open uinput device\n"); + } else { + ret = snprintf(uinputFdStr, sizeof uinputFdStr, "%d", uinputFd); + if (ret == 0 || ret >= sizeof uinputFdStr) { + Error("could not parse uinput file descriptor (%d)\n", uinputFd); + } else { + argv[idx++] = "--uinputFd"; + argv[idx++] = uinputFdStr; + } } }