summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/os/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/os/utils.c')
-rw-r--r--xc/programs/Xserver/os/utils.c270
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");
+}
+
+