diff options
Diffstat (limited to 'xc/programs/Xserver/os/utils.c')
-rw-r--r-- | xc/programs/Xserver/os/utils.c | 677 |
1 files changed, 508 insertions, 169 deletions
diff --git a/xc/programs/Xserver/os/utils.c b/xc/programs/Xserver/os/utils.c index de6d851c7..14015a91c 100644 --- a/xc/programs/Xserver/os/utils.c +++ b/xc/programs/Xserver/os/utils.c @@ -1,9 +1,13 @@ -/* $TOG: utils.c /main/138 1998/04/22 16:32:51 msr $ */ +/* $Xorg: utils.c,v 1.5 2001/02/09 02:05:24 xorgcvs Exp $ */ /* Copyright 1987, 1998 The Open Group -All Rights Reserved. +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. @@ -45,9 +49,14 @@ 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.52 1999/05/15 12:10:35 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/os/utils.c,v 3.81 2002/01/16 20:39:51 dawes Exp $ */ -#ifdef WIN32 +#ifdef __CYGWIN__ +#include <stdlib.h> +#include <signal.h> +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) #include <X11/Xwinsock.h> #endif #include "Xos.h" @@ -55,6 +64,8 @@ OR PERFORMANCE OF THIS SOFTWARE. #include "misc.h" #include "X.h" #include "input.h" +#include "dixfont.h" +#include "osdep.h" #ifdef X_POSIX_C_SOURCE #define _POSIX_C_SOURCE X_POSIX_C_SOURCE #include <signal.h> @@ -69,39 +80,20 @@ OR PERFORMANCE OF THIS SOFTWARE. #endif #endif #include <sys/wait.h> -#if !defined(SYSV) && !defined(AMOEBA) && !defined(_MINIX) && !defined(WIN32) && !defined(Lynx) && !defined(QNX) +#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) #include <sys/resource.h> #endif #include <time.h> #include <sys/stat.h> #include <ctype.h> /* for isspace */ -#if NeedVarargsPrototypes #include <stdarg.h> -#endif #if defined(DGUX) #include <sys/resource.h> #include <netdb.h> #endif -#ifdef AMOEBA -#include "osdep.h" -#include <amoeba.h> -#include <module/mutex.h> - -static mutex print_lock; -#endif - -#if defined(__STDC__) || defined(AMOEBA) -/* DHD: SVR4.0 has a prototype for abs() in stdlib.h */ -/* DHD: might be better to move this include higher up? */ -#ifdef abs -#undef abs -#endif -#ifndef NOSTDHDRS #include <stdlib.h> /* for malloc() */ -#endif -#endif #if defined(TCPCONN) || defined(STREAMSCONN) # ifndef WIN32 @@ -111,14 +103,28 @@ static mutex print_lock; #include "opaque.h" +#ifdef SMART_SCHEDULE +#include "dixstruct.h" +#endif + +#ifdef XKB +#include "XKBsrv.h" +#endif +#ifdef XCSECURITY +#define _SECURITY_SERVER +#include "security.h" +#endif + +#define X_INCLUDE_NETDB_H +#include <X11/Xos_r.h> + #include <errno.h> -extern int errno; Bool CoreDump; Bool noTestExtensions; -Bool noPanoramiXExtension = TRUE; #ifdef PANORAMIX +Bool noPanoramiXExtension = TRUE; Bool PanoramiXVisibilityNotifySent = FALSE; Bool PanoramiXMapped = FALSE; Bool PanoramiXWindowExposureSent = FALSE; @@ -147,10 +153,8 @@ extern int SelectWaitTime; #ifdef MEMBUG #define MEM_FAIL_SCALE 100000 long Memory_fail = 0; -#ifdef linux #include <stdlib.h> /* for random() */ #endif -#endif #ifdef sgi int userdefinedfontpath = 0; @@ -177,7 +181,7 @@ OsSignal(sig, handler) return oact.sa_handler; #endif } - + #ifdef SERVER_LOCK /* * Explicit support for a server lock file like the ones used for UUCP. @@ -201,10 +205,6 @@ OsSignal(sig, handler) #include <sys/param.h> #endif -#ifdef _MINIX -#include <limits.h> /* For PATH_MAX */ -#endif - #ifdef __EMX__ #define link rename #endif @@ -226,6 +226,7 @@ OsSignal(sig, handler) static Bool StillLocking = FALSE; static char LockFile[PATH_MAX]; +static Bool nolock = FALSE; /* * LockServer -- @@ -236,7 +237,6 @@ static char LockFile[PATH_MAX]; void LockServer() { -#ifndef AMOEBA char tmp[PATH_MAX], pid_str[12]; int lfd, i, haslock, l_pid, t; char *tmppath = NULL; @@ -291,7 +291,7 @@ LockServer() } if (lfd < 0) FatalError("Could not create lock file in %s\n", tmp); - (void) sprintf(pid_str, "%10d\n", getpid()); + (void) sprintf(pid_str, "%10ld\n", (long)getpid()); (void) write(lfd, pid_str, 11); #ifndef __EMX__ #ifndef USE_CHMOD @@ -365,7 +365,6 @@ LockServer() if (!haslock) FatalError("Could not create server lock file: %s\n", LockFile); StillLocking = FALSE; -#endif /* !AMOEBA */ } /* @@ -375,7 +374,6 @@ LockServer() void UnlockServer() { -#ifndef AMOEBA if (nolock) return; if (!StillLocking){ @@ -385,8 +383,6 @@ UnlockServer() #endif /* __EMX__ */ (void) unlink(LockFile); } -#endif - } #endif /* SERVER_LOCK */ @@ -397,6 +393,8 @@ SIGVAL AutoResetServer (sig) int sig; { + int olderrno = errno; + dispatchException |= DE_RESET; isItTimeToYield = TRUE; #ifdef GPROF @@ -406,9 +404,7 @@ AutoResetServer (sig) #if defined(SYSV) && defined(X_NOT_POSIX) OsSignal (SIGHUP, AutoResetServer); #endif -#ifdef AMOEBA - WakeUpMainThread(); -#endif + errno = olderrno; } /* Force connections to close and then exit on SIGTERM, SIGINT */ @@ -418,15 +414,15 @@ SIGVAL GiveUp(sig) int sig; { + int olderrno = errno; + dispatchException |= DE_TERMINATE; isItTimeToYield = TRUE; #if defined(SYSV) && defined(X_NOT_POSIX) if (sig) OsSignal(sig, SIG_IGN); #endif -#ifdef AMOEBA - WakeUpMainThread(); -#endif + errno = olderrno; } #if __GNUC__ @@ -439,9 +435,6 @@ AbortServer() OsCleanup(); AbortDDX(); fflush(stderr); -#ifdef AMOEBA - IOPCleanUp(); -#endif if (CoreDump) abort(); exit (1); @@ -451,27 +444,17 @@ void Error(str) char *str; { -#ifdef AMOEBA - mu_lock(&print_lock); -#endif perror(str); -#ifdef AMOEBA - mu_unlock(&print_lock); -#endif } #ifndef DDXTIME CARD32 GetTimeInMillis() { -#ifndef AMOEBA struct timeval tp; X_GETTIMEOFDAY(&tp); return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); -#else - return sys_milli(); -#endif } #endif @@ -504,11 +487,7 @@ AdjustWaitForDelay (waitTime, newdelay) void UseMsg() { #if !defined(AIXrt) && !defined(AIX386) -#ifndef AMOEBA ErrorF("use: X [:<display>] [option]\n"); -#else - ErrorF("use: X [[<host>]:<display>] [option]\n"); -#endif ErrorF("-a # mouse acceleration (pixels)\n"); ErrorF("-ac disable access control restrictions\n"); #ifdef MEMBUG @@ -517,6 +496,7 @@ void UseMsg() ErrorF("-audit int set audit trail level\n"); ErrorF("-auth file select authorization file\n"); ErrorF("bc enable bug compatibility\n"); + ErrorF("-br create root window with black background\n"); ErrorF("+bs enable any backing store support\n"); ErrorF("-bs disable any backing store support\n"); ErrorF("-c turns off key-click\n"); @@ -567,9 +547,6 @@ void UseMsg() #endif ErrorF("-su disable any save under support\n"); ErrorF("-t # mouse threshold (pixels)\n"); -#ifdef AMOEBA - ErrorF("-tcp capability specify TCP/IP server capability\n"); -#endif ErrorF("-terminate terminate at server reset\n"); ErrorF("-to # connection time out\n"); ErrorF("-tst disable testing extensions\n"); @@ -623,10 +600,6 @@ char *argv[]; { int i, skip; -#ifdef AMOEBA - mu_init(&print_lock); -#endif - defaultKeyboardControl.autoRepeat = TRUE; #ifdef PART_NET @@ -651,27 +624,6 @@ char *argv[]; exit(1); } } -#ifdef AMOEBA - else if (strchr(argv[i], ':') != NULL) { - char *p; - - XServerHostName = argv[i]; - if ((p = strchr(argv[i], ':')) != NULL) { - *p++ = '\0'; - display = p; - if( ! VerifyDisplayName( display ) ) { - ErrorF("Bad display name: %s\n", display); - UseMsg(); - exit(1); - } - } - } else if (strcmp( argv[i], "-tcp") == 0) { - if (++i < argc) - XTcpServerName = argv[i]; - else - UseMsg(); - } -#endif /* AMOEBA */ else if ( strcmp( argv[i], "-a") == 0) { if(++i < argc) @@ -708,6 +660,8 @@ char *argv[]; } else if ( strcmp( argv[i], "bc") == 0) permitOldBugs = TRUE; + else if ( strcmp( argv[i], "-br") == 0) + blackRoot = TRUE; else if ( strcmp( argv[i], "+bs") == 0) enableBackingStore = TRUE; else if ( strcmp( argv[i], "-bs") == 0) @@ -840,7 +794,7 @@ char *argv[]; #ifdef SERVER_LOCK else if ( strcmp ( argv[i], "-nolock") == 0) { -#if !defined(WIN32) && !defined(__EMX__) +#if !defined(WIN32) && !defined(__EMX__) && !defined(__CYGWIN__) if (getuid() != 0) ErrorF("Warning: the -nolock option can only be used by root\n"); else @@ -984,6 +938,31 @@ char *argv[]; SyncOn++; } #endif +#ifdef SMART_SCHEDULE + else if ( strcmp( argv[i], "-dumbSched") == 0) + { + 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 { ErrorF("Unrecognized option: %s\n", argv[i]); @@ -1092,7 +1071,7 @@ ExpandCommandLine(pargc, pargv) { int i; -#if !defined(WIN32) && !defined(__EMX__) +#if !defined(WIN32) && !defined(__EMX__) && !defined(__CYGWIN__) if (getuid() != geteuid()) return; #endif @@ -1129,9 +1108,12 @@ pointer client; char hname[1024], *hnameptr; struct hostent *host; int len; +#ifdef XTHREADS_NEEDS_BYNAMEPARAMS + _Xgethostbynameparams hparams; +#endif gethostname(hname, 1024); - host = gethostbyname(hname); + host = _XGethostbyname(hname, hparams); if (host == NULL) hnameptr = hname; else @@ -1174,9 +1156,6 @@ void * Xalloc (amount) unsigned long amount; { -#if !defined(__STDC__) && !defined(AMOEBA) - char *malloc(); -#endif register pointer ptr; if ((long)amount <= 0) { @@ -1206,9 +1185,6 @@ void * XNFalloc (amount) unsigned long amount; { -#if !defined(__STDC__) && !defined(AMOEBA) - char *malloc(); -#endif register pointer ptr; if ((long)amount <= 0) @@ -1268,11 +1244,6 @@ Xrealloc (ptr, amount) register pointer ptr; unsigned long amount; { -#if !defined(__STDC__) && !defined(AMOEBA) - char *malloc(); - char *realloc(); -#endif - #ifdef MEMBUG if (!Must_have_memory && Memory_fail && ((random() % MEM_FAIL_SCALE) < Memory_fail)) @@ -1374,13 +1345,9 @@ XNFstrdup(const char *s) void AuditPrefix(f) - char *f; + const char *f; { -#ifdef X_NOT_STDC_ENV - long tm; -#else time_t tm; -#endif char *autime, *s; if (*f != ' ') { @@ -1396,59 +1363,32 @@ AuditPrefix(f) } } -/*VARARGS1*/ void -AuditF( -#if NeedVarargsPrototypes - const char * f, ...) -#else - f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ - char *f; - char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; -#endif +AuditF(const char * f, ...) { -#if NeedVarargsPrototypes va_list args; -#endif AuditPrefix(f); -#if NeedVarargsPrototypes va_start(args, f); VErrorF(f, args); va_end(args); -#else - ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); -#endif } -/*VARARGS1*/ void -FatalError( -#if NeedVarargsPrototypes - const char *f, ...) -#else -f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ - const char *f; - char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; -#endif +FatalError(const char *f, ...) { -#if NeedVarargsPrototypes va_list args; -#endif - static beenhere = 0; + static Bool beenhere = FALSE; if (beenhere) ErrorF("\nFatalError re-entered, aborting\n"); else ErrorF("\nFatal server error:\n"); -#if NeedVarargsPrototypes + va_start(args, f); VErrorF(f, args); va_end(args); -#else - ErrorF(f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); -#endif ErrorF("\n"); #ifdef DDXOSFATALERROR if (!beenhere) @@ -1457,14 +1397,14 @@ f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ #ifdef ABORTONFATALERROR abort(); #endif - if (!beenhere) + if (!beenhere) { + beenhere = TRUE; AbortServer(); - else + } else abort(); /*NOTREACHED*/ } -#if NeedVarargsPrototypes void VErrorF(f, args) const char *f; @@ -1496,37 +1436,160 @@ VFatalError(const char *msg, va_list args) AbortServer(); /*NOTREACHED*/ } -#endif /* NeedVarargsPrototypes */ -/*VARARGS1*/ void -ErrorF( -#if NeedVarargsPrototypes - const char * f, ...) -#else - f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) /* limit of ten args */ - char *f; - char *s0, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9; -#endif +ErrorF(const char * f, ...) { -#if NeedVarargsPrototypes va_list args; va_start(args, f); VErrorF(f, args); va_end(args); +} + +#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 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) +{ + int olderrno = errno; + + SmartScheduleTime += SmartScheduleInterval; + if (SmartScheduleIdle) + { + SmartScheduleStopTimer (); + } + errno = olderrno; +} +#endif + +Bool +SmartScheduleInit (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + struct sigaction act; + + if (SmartScheduleDisable) + return TRUE; + + bzero ((char *) &act, sizeof(struct sigaction)); + + /* Set up the timer signal function */ + act.sa_handler = SmartScheduleTimer; + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); + if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) + { + perror ("sigaction for smart scheduler"); + return FALSE; + } + /* Set up the virtual timer */ + if (!SmartScheduleStartTimer ()) + { + perror ("scheduling timer"); + return FALSE; + } + /* stop the timer and wait for WaitForSomething to start it */ + SmartScheduleStopTimer (); + return TRUE; #else -#ifdef AIXV3 - if (SyncOn) - sync(); -#else /* not AIXV3 */ -#ifdef AMOEBA - mu_lock(&print_lock); + return FALSE; #endif - fprintf( stderr, f, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9); -#ifdef AMOEBA - mu_unlock(&print_lock); +} #endif -#endif /* AIXV3 */ + +#ifdef SIG_BLOCK +static sigset_t PreviousSignalMask; +static int BlockedSignalCount; +#endif + +void +OsBlockSignals (void) +{ +#ifdef SIG_BLOCK + if (BlockedSignalCount++ == 0) + { + sigset_t set; + + sigemptyset (&set); +#ifdef SIGALRM + sigaddset (&set, SIGALRM); +#endif +#ifdef SIGVTALRM + sigaddset (&set, SIGVTALRM); +#endif +#ifdef SIGWINCH + sigaddset (&set, SIGWINCH); +#endif +#ifdef SIGIO + sigaddset (&set, SIGIO); +#endif +#ifdef SIGTSTP + sigaddset (&set, SIGTSTP); +#endif +#ifdef SIGTTIN + sigaddset (&set, SIGTTIN); +#endif +#ifdef SIGTTOU + sigaddset (&set, SIGTTOU); +#endif + sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); + } +#endif +} + +void +OsReleaseSignals (void) +{ +#ifdef SIG_BLOCK + if (--BlockedSignalCount == 0) + { + sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); + } #endif } @@ -1536,6 +1599,9 @@ ErrorF( * all privs before running a command. * * This is based on the code in FreeBSD 2.2 libc. + * + * XXX It'd be good to redirect stderr so that it ends up in the log file + * as well. As it is now, xkbcomp messages don't end up in the log file. */ int @@ -1543,7 +1609,9 @@ System(command) char *command; { int pid, p; - void (*csig)(); +#ifdef SIGCHLD + void (*csig)(int); +#endif int status; if (!command) @@ -1553,7 +1621,9 @@ System(command) csig = signal(SIGCHLD, SIG_DFL); #endif +#ifdef DEBUG ErrorF("System: `%s'\n", command); +#endif switch (pid = fork()) { case -1: /* error */ @@ -1591,7 +1661,6 @@ Popen(command, type) struct pid *cur; FILE *iop; int pdes[2], pid; - void (*csig)(); if (command == NULL || type == NULL) return NULL; @@ -1635,6 +1704,9 @@ Popen(command, type) _exit(127); } + /* Avoid EINTR during stdio calls */ + OsBlockSignals (); + /* parent */ if (*type == 'r') { iop = fdopen(pdes[0], type); @@ -1649,7 +1721,7 @@ Popen(command, type) cur->next = pidlist; pidlist = cur; -#if 0 +#ifdef DEBUG ErrorF("Popen: `%s', fp = %p\n", command, iop); #endif @@ -1661,11 +1733,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 @@ -1687,6 +1758,274 @@ Pclose(iop) last->next = cur->next; xfree(cur); + /* allow EINTR again */ + OsReleaseSignals (); + 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 + +/* + * Disallow stdout or stderr as pipes? It's possible to block the X server + * when piping stdout+stderr to a pipe. + * + * Don't enable this because it looks like it's going to cause problems. + */ +#ifndef NO_OUTPUT_PIPES +#define NO_OUTPUT_PIPES 0 +#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, + OutputIsPipe, + 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 + } + } + } +#if NO_OUTPUT_PIPES + if (!bad) { + struct stat buf; + + if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode)) + bad = OutputIsPipe; + if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode)) + bad = OutputIsPipe; + } +#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 OutputIsPipe: + ErrorF("Stdout and/or stderr is a pipe\n"); + 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"); +} + +/* + * CheckUserAuthorization: check if the user is allowed to start the + * X server. This usually means some sort of PAM checking, and it is + * usually only done for setuid servers (uid != euid). + */ + +#ifdef USE_PAM +#include <security/pam_appl.h> +#include <security/pam_misc.h> +#include <pwd.h> +#endif /* USE_PAM */ + +void +CheckUserAuthorization() +{ +#ifdef USE_PAM + static struct pam_conv conv = { + misc_conv, + NULL + }; + + pam_handle_t *pamh = NULL; + struct passwd *pw; + int retval; + + if (getuid() != geteuid()) { + pw = getpwuid(getuid()); + if (pw == NULL) + FatalError("getpwuid() failed for uid %d\n", getuid()); + + retval = pam_start("xserver", pw->pw_name, &conv, &pamh); + if (retval != PAM_SUCCESS) + FatalError("pam_start() failed.\n" + "\tMissing or mangled PAM config file or module?\n"); + + retval = pam_authenticate(pamh, 0); + if (retval != PAM_SUCCESS) { + pam_end(pamh, retval); + FatalError("PAM authentication failed, cannot start X server.\n" + "\tPerhaps you do not have console ownership?\n"); + } + + retval = pam_acct_mgmt(pamh, 0); + if (retval != PAM_SUCCESS) { + pam_end(pamh, retval); + FatalError("PAM authentication failed, cannot start X server.\n" + "\tPerhaps you do not have console ownership?\n"); + } + + /* this is not a session, so do not do session management */ + pam_end(pamh, PAM_SUCCESS); + } +#endif +} |