diff options
Diffstat (limited to 'xc/programs/Xserver/os/utils.c')
-rw-r--r-- | xc/programs/Xserver/os/utils.c | 270 |
1 files changed, 258 insertions, 12 deletions
diff --git a/xc/programs/Xserver/os/utils.c b/xc/programs/Xserver/os/utils.c index 35da9a210..337cfb6cd 100644 --- a/xc/programs/Xserver/os/utils.c +++ b/xc/programs/Xserver/os/utils.c @@ -45,7 +45,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $XFree86: xc/programs/Xserver/os/utils.c,v 3.56 2000/02/23 20:30:18 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/os/utils.c,v 3.59 2000/06/17 00:27:34 dawes Exp $ */ #ifdef WIN32 #include <X11/Xwinsock.h> @@ -993,6 +993,25 @@ char *argv[]; { SmartScheduleDisable = TRUE; } + else if ( strcmp( argv[i], "-schedInterval") == 0) + { + if (++i < argc) + { + SmartScheduleInterval = atoi(argv[i]); + SmartScheduleSlice = SmartScheduleInterval; + } + else + UseMsg(); + } + else if ( strcmp( argv[i], "-schedMax") == 0) + { + if (++i < argc) + { + SmartScheduleMaxSlice = atoi(argv[i]); + } + else + UseMsg(); + } #endif else { @@ -1542,17 +1561,59 @@ ErrorF( #ifdef SMART_SCHEDULE +unsigned long SmartScheduleIdleCount; +Bool SmartScheduleIdle; +Bool SmartScheduleTimerStopped; + #ifdef SIGVTALRM #define SMART_SCHEDULE_POSSIBLE #endif #ifdef SMART_SCHEDULE_POSSIBLE -#define SMART_SCHEDULE_SIGNAL SIGVTALRM +#define SMART_SCHEDULE_SIGNAL SIGALRM +#define SMART_SCHEDULE_TIMER ITIMER_REAL +#endif void +SmartScheduleStopTimer (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + struct itimerval timer; + + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 0; + (void) setitimer (ITIMER_REAL, &timer, 0); + SmartScheduleTimerStopped = TRUE; +#endif +} + +Bool +SmartScheduleStartTimer (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + struct itimerval timer; + + SmartScheduleTimerStopped = FALSE; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = SmartScheduleInterval * 1000; + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = SmartScheduleInterval * 1000; + return setitimer (ITIMER_REAL, &timer, 0) >= 0; +#endif + return FALSE; +} + +#ifdef SMART_SCHEDULE_POSSIBLE +void SmartScheduleTimer (int sig) { SmartScheduleTime += SmartScheduleInterval; + if (SmartScheduleIdle) + { + SmartScheduleStopTimer (); + } } #endif @@ -1578,11 +1639,7 @@ SmartScheduleInit (void) return FALSE; } /* Set up the virtual timer */ - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = SmartScheduleInterval * 1000; - timer.it_value.tv_sec = 0; - timer.it_value.tv_usec = SmartScheduleInterval * 1000; - if (setitimer (ITIMER_VIRTUAL, &timer, 0) < 0) + if (!SmartScheduleStartTimer ()) { perror ("scheduling timer"); return FALSE; @@ -1607,7 +1664,9 @@ System(command) char *command; { int pid, p; - void (*csig)(); +#ifdef SIGCHLD + void (*csig)(int); +#endif int status; if (!command) @@ -1617,7 +1676,9 @@ System(command) csig = signal(SIGCHLD, SIG_DFL); #endif +#ifdef DEBUG ErrorF("System: `%s'\n", command); +#endif switch (pid = fork()) { case -1: /* error */ @@ -1655,7 +1716,6 @@ Popen(command, type) struct pid *cur; FILE *iop; int pdes[2], pid; - void (*csig)(); if (command == NULL || type == NULL) return NULL; @@ -1713,7 +1773,7 @@ Popen(command, type) cur->next = pidlist; pidlist = cur; -#if 0 +#ifdef DEBUG ErrorF("Popen: `%s', fp = %p\n", command, iop); #endif @@ -1725,11 +1785,10 @@ Pclose(iop) pointer iop; { struct pid *cur, *last; - int omask; int pstat; int pid; -#if 0 +#ifdef DEBUG ErrorF("Pclose: fp = %p\n", iop); #endif @@ -1754,3 +1813,190 @@ Pclose(iop) return pid == -1 ? -1 : pstat; } #endif /* !WIN32 && !__EMX__ */ + + +/* + * CheckUserParameters: check for long command line arguments and long + * environment variables. By default, these checks are only done when + * the server's euid != ruid. In 3.3.x, these checks were done in an + * external wrapper utility. + */ + +/* Consider LD* variables insecure? */ +#ifndef REMOVE_ENV_LD +#define REMOVE_ENV_LD 1 +#endif + +/* Remove long environment variables? */ +#ifndef REMOVE_LONG_ENV +#define REMOVE_LONG_ENV 1 +#endif + +/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */ +#ifndef CHECK_EUID +#define CHECK_EUID 1 +#endif + +/* + * Maybe the locale can be faked to make isprint(3) report that everything + * is printable? Avoid it by default. + */ +#ifndef USE_ISPRINT +#define USE_ISPRINT 0 +#endif + +#define MAX_ARG_LENGTH 128 +#define MAX_ENV_LENGTH 256 +#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */ + +#if USE_ISPRINT +#include <ctype.h> +#define checkPrintable(c) isprint(c) +#else +#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f) +#endif + +enum BadCode { + NotBad = 0, + UnsafeArg, + ArgTooLong, + UnprintableArg, + EnvTooLong, + InternalError +}; + +#define ARGMSG \ + "\nIf the arguments used are valid, and have been rejected incorrectly\n" \ + "please send details of the arguments and why they are valid to\n" \ + "XFree86@XFree86.org. In the meantime, you can start the Xserver as\n" \ + "the \"super user\" (root).\n" + +#define ENVMSG \ + "\nIf the environment is valid, and have been rejected incorrectly\n" \ + "please send details of the environment and why it is valid to\n" \ + "XFree86@XFree86.org. In the meantime, you can start the Xserver as\n" \ + "the \"super user\" (root).\n" + +void +CheckUserParameters(int argc, char **argv, char **envp) +{ + enum BadCode bad = NotBad; + int i = 0, j; + char *a, *e = NULL; +#if defined(__QNX__) && !defined(__QNXNTO__) + char cmd_name[64]; +#endif + +#if CHECK_EUID + if (geteuid() == 0 && getuid() != geteuid()) +#endif + { + /* Check each argv[] */ + for (i = 1; i < argc; i++) { + if (strlen(argv[i]) > MAX_ARG_LENGTH) { + bad = ArgTooLong; + break; + } + a = argv[i]; + while (*a) { + if (checkPrintable(*a) == 0) { + bad = UnprintableArg; + break; + } + a++; + } + if (bad) + break; + } + if (!bad) { + /* Check each envp[] */ + for (i = 0; envp[i]; i++) { + + /* Check for bad environment variables and values */ +#if REMOVE_ENV_LD + while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) { +#ifdef ENVDEBUG + ErrorF("CheckUserParameters: removing %s from the " + "environment\n", strtok(envp[i], "=")); +#endif + for (j = i; envp[j]; j++) { + envp[j] = envp[j+1]; + } + } +#endif + if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) { +#if REMOVE_LONG_ENV +#ifdef ENVDEBUG + ErrorF("CheckUserParameters: removing %s from the " + "environment\n", strtok(envp[i], "=")); +#endif + for (j = i; envp[j]; j++) { + envp[j] = envp[j+1]; + } + i--; +#else + char *eq; + int len; + + eq = strchr(envp[i], '='); + if (!eq) + continue; + len = eq - envp[i]; + e = malloc(len + 1); + if (!e) { + bad = InternalError; + break; + } + strncpy(e, envp[i], len); + e[len] = 0; + if (len >= 4 && + (strcmp(e + len - 4, "PATH") == 0 || + strcmp(e, "TERMCAP") == 0)) { + if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) { + bad = EnvTooLong; + break; + } else { + free(e); + } + } else { + bad = EnvTooLong; + break; + } +#endif + } + } + } + } + switch (bad) { + case NotBad: + return; + case UnsafeArg: + ErrorF("Command line argument number %d is unsafe\n", i); + ErrorF(ARGMSG); + break; + case ArgTooLong: + ErrorF("Command line argument number %d is too long\n", i); + ErrorF(ARGMSG); + break; + case UnprintableArg: + ErrorF("Command line argument number %d contains unprintable" + " characters\n", i); + ErrorF(ARGMSG); + break; + case EnvTooLong: + ErrorF("Environment variable `%s' is too long\n", e); + ErrorF(ENVMSG); + break; + case InternalError: + ErrorF("Internal Error\n"); + break; + default: + ErrorF("Unknown error\n"); + ErrorF(ARGMSG); + ErrorF(ENVMSG); + break; + } + FatalError("X server aborted because of unsafe environment\n"); +} + + |