diff options
author | marha <marha@users.sourceforge.net> | 2014-03-25 17:56:10 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2014-03-25 17:56:10 +0100 |
commit | ba6115f56f066621a20fa545ddd67721afd35523 (patch) | |
tree | 418b724d4f318d24dc8e5183e6b252922f85f149 /xorg-server/hw/xfree86/xorg-wrapper.c | |
parent | eb71c0f23999d1cc156e1821d73634ec79621fc2 (diff) | |
parent | e0927d908a12c9c140458c355b29b884a7705f2d (diff) | |
download | vcxsrv-ba6115f56f066621a20fa545ddd67721afd35523.tar.gz vcxsrv-ba6115f56f066621a20fa545ddd67721afd35523.tar.bz2 vcxsrv-ba6115f56f066621a20fa545ddd67721afd35523.zip |
Merge remote-tracking branch 'origin/released'
Conflicts:
xorg-server/hw/xwin/InitInput.c
xorg-server/hw/xwin/InitOutput.c
xorg-server/hw/xwin/winglobals.c
xorg-server/hw/xwin/winglobals.h
xorg-server/hw/xwin/winmsgwindow.c
xorg-server/hw/xwin/winmultiwindowwm.c
xorg-server/hw/xwin/winmultiwindowwndproc.c
Diffstat (limited to 'xorg-server/hw/xfree86/xorg-wrapper.c')
-rw-r--r-- | xorg-server/hw/xfree86/xorg-wrapper.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/xorg-wrapper.c b/xorg-server/hw/xfree86/xorg-wrapper.c new file mode 100644 index 000000000..90c8c11ef --- /dev/null +++ b/xorg-server/hw/xfree86/xorg-wrapper.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2014 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Hans de Goede <hdegoede@redhat.com> + */ + +#include "dix-config.h" + +#include <fcntl.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <drm/drm.h> +#include <xf86drm.h> /* For DRM_DEV_NAME */ + +#define CONFIG_FILE SYSCONFDIR "/X11/Xwrapper.config" + +enum { ROOT_ONLY, CONSOLE_ONLY, ANYBODY }; + +/* KISS non locale / LANG parsing isspace version */ +static int is_space(char c) +{ + return c == ' ' || c == '\t' || c == '\n'; +} + +static char *strip(char *s) +{ + int i; + + /* Strip leading whitespace */ + while (s[0] && is_space(s[0])) + s++; + + /* Strip trailing whitespace */ + i = strlen(s) - 1; + while (i >= 0 && is_space(s[i])) { + s[i] = 0; + i--; + } + + return s; +} + +static void parse_config(int *allowed, int *needs_root_rights) +{ + FILE *f; + char buf[1024]; + char *stripped, *equals, *key, *value; + int line = 0; + + f = fopen(CONFIG_FILE, "r"); + if (!f) + return; + + while (fgets(buf, sizeof(buf), f)) { + line++; + + /* Skip comments and empty lines */ + stripped = strip(buf); + if (stripped[0] == '#' || stripped[0] == 0) + continue; + + /* Split in a key + value pair */ + equals = strchr(stripped, '='); + if (!equals) { + fprintf(stderr, "Syntax error at %s line %d\n", CONFIG_FILE, line); + exit(1); + } + *equals = 0; + key = strip(stripped); /* To remove trailing whitespace from key */ + value = strip(equals + 1); /* To remove leading whitespace from val */ + if (!key[0]) { + fprintf(stderr, "Missing key at %s line %d\n", CONFIG_FILE, line); + exit(1); + } + if (!value[0]) { + fprintf(stderr, "Missing value at %s line %d\n", CONFIG_FILE, line); + exit(1); + } + + /* And finally process */ + if (strcmp(key, "allowed_users") == 0) { + if (strcmp(value, "rootonly") == 0) + *allowed = ROOT_ONLY; + else if (strcmp(value, "console") == 0) + *allowed = CONSOLE_ONLY; + else if (strcmp(value, "anybody") == 0) + *allowed = ANYBODY; + else { + fprintf(stderr, + "Invalid value '%s' for 'allowed_users' at %s line %d\n", + value, CONFIG_FILE, line); + exit(1); + } + } + else if (strcmp(key, "needs_root_rights") == 0) { + if (strcmp(value, "yes") == 0) + *needs_root_rights = 1; + else if (strcmp(value, "no") == 0) + *needs_root_rights = 0; + else if (strcmp(value, "auto") == 0) + *needs_root_rights = -1; + else { + fprintf(stderr, + "Invalid value '%s' for 'needs_root_rights' at %s line %d\n", + value, CONFIG_FILE, line); + exit(1); + } + } + else if (strcmp(key, "nice_value") == 0) { + /* Backward compatibility with older Debian Xwrapper, ignore */ + } + else { + fprintf(stderr, "Invalid key '%s' at %s line %d\n", key, + CONFIG_FILE, line); + exit(1); + } + } + fclose(f); +} + +int main(int argc, char *argv[]) +{ + struct drm_mode_card_res res; + struct stat st; + char buf[PATH_MAX]; + int i, r, fd; + int kms_cards = 0; + int total_cards = 0; + int allowed = CONSOLE_ONLY; + int needs_root_rights = -1; + + parse_config(&allowed, &needs_root_rights); + + /* For non root users check if they are allowed to run the X server */ + if (getuid() != 0) { + switch (allowed) { + case ROOT_ONLY: + /* Already checked above */ + fprintf(stderr, "%s: Only root is allowed to run the X server\n", argv[0]); + exit(1); + break; + case CONSOLE_ONLY: + /* Some of stdin / stdout / stderr maybe redirected to a file */ + for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) { + r = fstat(i, &st); + if (r == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) + break; + } + if (i > STDERR_FILENO) { + fprintf(stderr, "%s: Only console users are allowed to run the X server\n", argv[0]); + exit(1); + } + break; + case ANYBODY: + break; + } + } + + /* Detect if we need root rights, except when overriden by the config */ + if (needs_root_rights == -1) { + for (i = 0; i < 16; i++) { + snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, i); + fd = open(buf, O_RDWR); + if (fd == -1) + continue; + + total_cards++; + + memset(&res, 0, sizeof(struct drm_mode_card_res)); + r = ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res); + if (r == 0 && res.count_connectors > 0) + kms_cards++; + + close(fd); + } + } + + /* If we've found cards, and all cards support kms, drop root rights */ + if (needs_root_rights == 0 || (total_cards && kms_cards == total_cards)) { + gid_t realgid = getgid(); + uid_t realuid = getuid(); + + if (setresgid(-1, realgid, realgid) != 0) { + perror("Could not drop setgid privileges"); + exit(1); + } + if (setresuid(-1, realuid, realuid) != 0) { + perror("Could not drop setuid privileges"); + exit(1); + } + } + + snprintf(buf, sizeof(buf), "%s/Xorg.bin", SUID_WRAPPER_DIR); + + /* Check if the server is executable by our real uid */ + if (access(buf, X_OK) != 0) { + perror("Missing execute permissions for " SUID_WRAPPER_DIR "Xorg.bin"); + exit(1); + } + + argv[0] = buf; + (void) execv(argv[0], argv); + perror("Failed to execute " SUID_WRAPPER_DIR "/Xorg.bin"); + exit(1); +} |