This is bugfix patch number 1 for XFree86 3.3.2. This patch fixes the following problems: - xterm utmp handling problem. - exploitable buffer overflows in xterm related to the preeditType, inputMethod and *Keymap resources. - fix xterm's mishandling of the -vb command line option. - fix an invisible cursor problem with xterm. - exploitable buffer overflows in setuid programs using the Xaw library which are related to the preeditType and inputMethod resources. Credits: Richard Braakman xterm security fixes. Tom Dickey intergrate xterm security fixes, and fix other xterm problems. Paulo Cesar Pereira de Andrade Xaw security fixes. This patch applies to the XFree86 3.3.2 source. To apply the patch, run the following from the directory containing the xc source directory: patch -p0 -E < this-file ---------------------------------------------------------------------------- Index: xc/programs/xterm/Tekproc.c diff -c xc/programs/xterm/Tekproc.c:3.13.2.2 xc/programs/xterm/Tekproc.c:3.13.2.4 *** xc/programs/xterm/Tekproc.c:3.13.2.2 Mon Feb 16 03:09:55 1998 --- xc/programs/xterm/Tekproc.c Wed Apr 29 21:18:06 1998 *************** *** 1,6 **** /* * $XConsortium: Tekproc.c /main/120 1996/11/29 10:33:20 swick $ ! * $XFree86: xc/programs/xterm/Tekproc.c,v 3.13.2.2 1998/02/15 16:09:55 hohndel Exp $ * * Warning, there be crufty dragons here. */ --- 1,6 ---- /* * $XConsortium: Tekproc.c /main/120 1996/11/29 10:33:20 swick $ ! * $XFree86: xc/programs/xterm/Tekproc.c,v 3.13.2.4 1998/04/29 11:18:06 dawes Exp $ * * Warning, there be crufty dragons here. */ *************** *** 74,79 **** --- 74,82 ---- #include #include #include + + #include "xterm.h" + #include "Tekparse.h" #include "data.h" #include "error.h" *************** *** 121,128 **** extern long time(); /* included in by Xos.h */ #endif - #include "xterm.h" - #define DefaultGCID XGContextFromGC(DefaultGC(screen->display, DefaultScreen(screen->display))) /* Tek defines */ --- 124,129 ---- *************** *** 1723,1730 **** --- 1724,1733 ---- #ifndef X_NOT_POSIX + #ifndef linux #define HAS_WAITPID #endif + #endif #ifdef HAS_WAITPID #include *************** *** 1742,1748 **** int pid; #ifndef HAS_WAITPID int waited; ! int (*chldfunc)(); chldfunc = signal(SIGCHLD, SIG_DFL); #endif --- 1745,1751 ---- int pid; #ifndef HAS_WAITPID int waited; ! SIGNAL_T (*chldfunc) PROTO((int n)); chldfunc = signal(SIGCHLD, SIG_DFL); #endif Index: xc/programs/xterm/charproc.c diff -c xc/programs/xterm/charproc.c:3.42.2.5 xc/programs/xterm/charproc.c:3.42.2.7 *** xc/programs/xterm/charproc.c:3.42.2.5 Mon Feb 16 03:09:58 1998 --- xc/programs/xterm/charproc.c Wed Apr 29 20:51:58 1998 *************** *** 1,6 **** /* * $XConsortium: charproc.c /main/196 1996/12/03 16:52:46 swick $ ! * $XFree86: xc/programs/xterm/charproc.c,v 3.42.2.5 1998/02/15 16:09:58 hohndel Exp $ */ /* --- 1,6 ---- /* * $XConsortium: charproc.c /main/196 1996/12/03 16:52:46 swick $ ! * $XFree86: xc/programs/xterm/charproc.c,v 3.42.2.7 1998/04/29 10:51:58 dawes Exp $ */ /* *************** *** 4030,4036 **** *s, *ns, *end, - tmp[1024], buf[32]; XIM xim = (XIM) NULL; XIMStyles *xim_styles; --- 4030,4035 ---- *************** *** 4045,4061 **** if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL); } else { ! strcpy(tmp, term->misc.input_method); ! for(ns=s=tmp; ns && *s;) { while (*s && isspace(*s)) s++; if (!*s) break; if ((ns = end = strchr(s, ',')) == 0) end = s + strlen(s); while (isspace(*end)) end--; - *end = '\0'; strcpy(buf, "@im="); ! strcat(buf, s); if ((p = XSetLocaleModifiers(buf)) != NULL && *p && (xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL)) != NULL) break; --- 4044,4061 ---- if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL); } else { ! for(ns=s=term->misc.input_method; ns && *s;) { while (*s && isspace(*s)) s++; if (!*s) break; if ((ns = end = strchr(s, ',')) == 0) end = s + strlen(s); while (isspace(*end)) end--; strcpy(buf, "@im="); ! if (end - (s + (sizeof(buf) - 5)) > 0) ! end = s + (sizeof(buf) - 5); ! strncat(buf, s, end - s); ! if ((p = XSetLocaleModifiers(buf)) != NULL && *p && (xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL)) != NULL) break; *************** *** 4080,4087 **** } found = False; ! strcpy(tmp, term->misc.preedit_type); ! for(s = tmp; s && !found;) { while (*s && isspace(*s)) s++; if (!*s) break; if ((ns = end = strchr(s, ',')) != 0) --- 4080,4086 ---- } found = False; ! for(s = term->misc.preedit_type; s && !found;) { while (*s && isspace(*s)) s++; if (!*s) break; if ((ns = end = strchr(s, ',')) != 0) *************** *** 4089,4101 **** else end = s + strlen(s); while (isspace(*end)) end--; - *end = '\0'; ! if (!strcmp(s, "OverTheSpot")) { input_style = (XIMPreeditPosition | XIMStatusArea); ! } else if (!strcmp(s, "OffTheSpot")) { input_style = (XIMPreeditArea | XIMStatusArea); ! } else if (!strcmp(s, "Root")) { input_style = (XIMPreeditNothing | XIMStatusNothing); } for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) --- 4088,4099 ---- else end = s + strlen(s); while (isspace(*end)) end--; ! if (!strncmp(s, "OverTheSpot", end - s)) { input_style = (XIMPreeditPosition | XIMStatusArea); ! } else if (!strncmp(s, "OffTheSpot", end - s)) { input_style = (XIMPreeditArea | XIMStatusArea); ! } else if (!strncmp(s, "Root", end - s)) { input_style = (XIMPreeditNothing | XIMStatusNothing); } for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) *************** *** 4646,4652 **** XtOverrideTranslations(w, original); return; } ! (void) sprintf( mapName, "%sKeymap", params[0] ); (void) strcpy( mapClass, mapName ); if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]); XtGetSubresources( w, (XtPointer)&keymap, mapName, mapClass, --- 4644,4650 ---- XtOverrideTranslations(w, original); return; } ! (void) sprintf( mapName, "%.*sKeymap", (int)sizeof(mapName) - 10, params[0] ); (void) strcpy( mapClass, mapName ); if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]); XtGetSubresources( w, (XtPointer)&keymap, mapName, mapClass, *************** *** 5075,5081 **** * not be set before the widget's realized, so it's tested separately). */ if(screen->colorMode) { ! if (TextWindow(screen) != 0 && (cc != bg)) { /* we might have a colored foreground/background later */ xgcv.font = screen->fnt_norm->fid; mask = (GCForeground | GCBackground | GCFont); --- 5073,5079 ---- * not be set before the widget's realized, so it's tested separately). */ if(screen->colorMode) { ! if (TextWindow(screen) != 0 && (cc != bg) && (cc != fg)) { /* we might have a colored foreground/background later */ xgcv.font = screen->fnt_norm->fid; mask = (GCForeground | GCBackground | GCFont); Index: xc/programs/xterm/data.c diff -c xc/programs/xterm/data.c:3.2.4.2 xc/programs/xterm/data.c:3.2.4.3 *** xc/programs/xterm/data.c:3.2.4.2 Mon Feb 16 03:10:03 1998 --- xc/programs/xterm/data.c Wed Apr 29 14:18:39 1998 *************** *** 1,6 **** /* * $XConsortium: data.c,v 1.12 95/04/05 19:58:47 kaleb Exp $ ! * $XFree86: xc/programs/xterm/data.c,v 3.2.4.2 1998/02/15 16:10:03 hohndel Exp $ */ /* --- 1,6 ---- /* * $XConsortium: data.c,v 1.12 95/04/05 19:58:47 kaleb Exp $ ! * $XFree86: xc/programs/xterm/data.c,v 3.2.4.3 1998/04/29 04:18:39 dawes Exp $ */ /* *************** *** 101,107 **** #endif int am_slave = 0; /* set to 1 if running as a slave process */ - int done_setuid = 0; /* set to 1 after resetting setuid */ int max_plus1; fd_set Select_mask; fd_set X_mask; --- 101,106 ---- Index: xc/programs/xterm/data.h diff -c xc/programs/xterm/data.h:3.3.2.1 xc/programs/xterm/data.h:3.3.2.2 *** xc/programs/xterm/data.h:3.3.2.1 Mon Feb 16 03:10:03 1998 --- xc/programs/xterm/data.h Wed Apr 29 14:18:39 1998 *************** *** 1,6 **** /* * $XConsortium: data.h /main/13 1996/11/24 17:35:40 rws $ ! * $XFree86: xc/programs/xterm/data.h,v 3.3.2.1 1998/02/15 16:10:03 hohndel Exp $ */ /* * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. --- 1,6 ---- /* * $XConsortium: data.h /main/13 1996/11/24 17:35:40 rws $ ! * $XFree86: xc/programs/xterm/data.h,v 3.3.2.2 1998/04/29 04:18:39 dawes Exp $ */ /* * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. *************** *** 71,77 **** #endif extern Char buffer[]; extern int am_slave; - extern int done_setuid; extern int bcnt; #ifdef DEBUG extern int debug; --- 71,76 ---- Index: xc/programs/xterm/main.c diff -c xc/programs/xterm/main.c:3.47.2.8 xc/programs/xterm/main.c:3.47.2.10 *** xc/programs/xterm/main.c:3.47.2.8 Fri Feb 27 12:29:29 1998 --- xc/programs/xterm/main.c Wed Apr 29 20:52:00 1998 *************** *** 64,70 **** ******************************************************************/ ! /* $XFree86: xc/programs/xterm/main.c,v 3.47.2.8 1998/02/27 01:29:29 dawes Exp $ */ /* main.c */ --- 64,70 ---- ******************************************************************/ ! /* $XFree86: xc/programs/xterm/main.c,v 3.47.2.10 1998/04/29 10:52:00 dawes Exp $ */ /* main.c */ *************** *** 979,984 **** --- 979,990 ---- "will be started. Options that start with a plus sign (+) restore the default.", NULL}; + static int abbrev (char *tst, char *cmp) + { + size_t len = strlen(tst); + return ((len >= 2) && (!strncmp(tst, cmp, len))); + } + static void Syntax (badOption) char *badOption; { *************** *** 1118,1126 **** /* Do these first, since we may not be able to open the display */ ProgramName = argv[0]; if (argc > 1) { ! if (!strncmp(argv[1], "-v", 2)) Version(); ! if (!strncmp(argv[1], "-h", 2) && strncmp(argv[1], "-hc", 3)) Help(); } --- 1124,1132 ---- /* Do these first, since we may not be able to open the display */ ProgramName = argv[0]; if (argc > 1) { ! if (abbrev(argv[1], "-version")) Version(); ! if (abbrev(argv[1], "-help")) Help(); } *************** *** 1728,1737 **** XSetErrorHandler(xerror); XSetIOErrorHandler(xioerror); - (void) setuid (screen->uid); /* we're done with privileges... */ - (void) setgid (screen->gid); - done_setuid = 1; - #ifdef ALLOWLOGGING if (term->misc.log_on) { StartLog(screen); --- 1734,1739 ---- *************** *** 3547,3553 **** int i, n, ncap; errstat err; struct caplist *cl; ! char buf[64], numbuf[12]; struct caplist *capvnew; int ttythread(); int xwatchdogthread(); --- 3549,3555 ---- int i, n, ncap; errstat err; struct caplist *cl; ! char buf[64]; struct caplist *capvnew; int ttythread(); int xwatchdogthread(); Index: xc/programs/xterm/misc.c diff -c xc/programs/xterm/misc.c:3.17.2.3 xc/programs/xterm/misc.c:3.17.2.4 *** xc/programs/xterm/misc.c:3.17.2.3 Wed Feb 25 00:54:37 1998 --- xc/programs/xterm/misc.c Wed Apr 29 14:18:45 1998 *************** *** 1,6 **** /* * $XConsortium: misc.c /main/112 1996/11/29 10:34:07 swick $ ! * $XFree86: xc/programs/xterm/misc.c,v 3.17.2.3 1998/02/24 13:54:37 hohndel Exp $ */ /* --- 1,6 ---- /* * $XConsortium: misc.c /main/112 1996/11/29 10:34:07 swick $ ! * $XFree86: xc/programs/xterm/misc.c,v 3.17.2.4 1998/04/29 04:18:45 dawes Exp $ */ /* *************** *** 48,60 **** #include #include #include "VTparse.h" #include "data.h" #include "error.h" #include "menu.h" - #include "xterm.h" - #if XtSpecificationRelease < 6 #ifndef X_GETTIMEOFDAY #define X_GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *)0) --- 48,60 ---- #include #include + #include "xterm.h" + #include "VTparse.h" #include "data.h" #include "error.h" #include "menu.h" #if XtSpecificationRelease < 6 #ifndef X_GETTIMEOFDAY #define X_GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *)0) *************** *** 534,541 **** --- 534,543 ---- #if defined(ALLOWLOGGING) || defined(DEBUG) #ifndef X_NOT_POSIX + #ifndef linux #define HAS_WAITPID #endif + #endif /* * create a file only if we could with the permissions of the real user id. *************** *** 559,576 **** int pid; #ifndef HAS_WAITPID int waited; ! int (*chldfunc)(); chldfunc = signal(SIGCHLD, SIG_DFL); #endif - - if (done_setuid) { - fd = open(pathname, O_WRONLY|O_CREAT|O_APPEND, mode); - if (fd >= 0) { - close(fd); - } - return; - } pid = fork(); switch (pid) --- 561,570 ---- int pid; #ifndef HAS_WAITPID int waited; ! SIGNAL_T (*chldfunc)(); chldfunc = signal(SIGCHLD, SIG_DFL); #endif pid = fork(); switch (pid) Index: xc/programs/xterm/os2main.c diff -c xc/programs/xterm/os2main.c:3.5.2.3 xc/programs/xterm/os2main.c:3.5.2.5 *** xc/programs/xterm/os2main.c:3.5.2.3 Sun Feb 22 12:28:30 1998 --- xc/programs/xterm/os2main.c Wed Apr 29 20:52:01 1998 *************** *** 5,11 **** #ifndef lint static char *rid="$XConsortium: main.c,v 1.227.1.2 95/06/29 18:13:15 kaleb Exp $"; #endif /* lint */ ! /* $XFree86: xc/programs/xterm/os2main.c,v 3.5.2.3 1998/02/22 01:28:30 robin Exp $ */ /*********************************************************** --- 5,11 ---- #ifndef lint static char *rid="$XConsortium: main.c,v 1.227.1.2 95/06/29 18:13:15 kaleb Exp $"; #endif /* lint */ ! /* $XFree86: xc/programs/xterm/os2main.c,v 3.5.2.5 1998/04/29 10:52:01 dawes Exp $ */ /*********************************************************** *************** *** 518,523 **** --- 518,529 ---- "will be started. Options that start with a plus sign (+) restore the default.", NULL}; + static int abbrev (char *tst, char *cmp) + { + size_t len = strlen(tst); + return ((len >= 2) && (!strncmp(tst, cmp, len))); + } + static void Syntax (badOption) char *badOption; { *************** *** 770,778 **** /* Do these first, since we may not be able to open the display */ ProgramName = argv[0]; if (argc > 1) { ! if (!strncmp(argv[1], "-v", 2)) Version(); ! if (!strncmp(argv[1], "-h", 2) && strncmp(argv[1], "-hc", 3)) Help(); } --- 776,784 ---- /* Do these first, since we may not be able to open the display */ ProgramName = argv[0]; if (argc > 1) { ! if (abbrev(argv[1], "-version")) Version(); ! if (abbrev(argv[1], "-help")) Help(); } *************** *** 1064,1073 **** #endif /* DEBUG */ XSetErrorHandler(xerror); XSetIOErrorHandler(xioerror); - - (void) setuid (screen->uid); /* we're done with privileges... */ - (void) setgid (screen->gid); - done_setuid = 1; #ifdef ALLOWLOGGING if (term->misc.log_on) { --- 1070,1075 ---- Index: xc/programs/xterm/print.c diff -c xc/programs/xterm/print.c:1.3.2.1 xc/programs/xterm/print.c:1.3.2.3 *** xc/programs/xterm/print.c:1.3.2.1 Mon Feb 16 03:10:08 1998 --- xc/programs/xterm/print.c Wed Apr 29 21:18:07 1998 *************** *** 1,5 **** /* ! * $XFree86: xc/programs/xterm/print.c,v 1.3.2.1 1998/02/15 16:10:08 hohndel Exp $ */ /************************************************************ --- 1,5 ---- /* ! * $XFree86: xc/programs/xterm/print.c,v 1.3.2.3 1998/04/29 11:18:07 dawes Exp $ */ /************************************************************ *************** *** 42,47 **** --- 42,48 ---- #include "ptyx.h" #include "data.h" + #include "error.h" #include "xterm.h" #define Strlen(a) strlen((char *)a) *************** *** 172,179 **** { static int initialized; if (!initialized) { register TScreen *screen = &term->screen; ! Printer = popen(screen->printer_command, "w"); initialized++; } if (Printer != 0) { --- 173,205 ---- { static int initialized; if (!initialized) { + FILE *input; + int my_pipe[2]; + int my_pid; + int c; register TScreen *screen = &term->screen; ! ! if (pipe(my_pipe)) ! SysError (ERROR_FORK); ! if ((my_pid = fork()) < 0) ! SysError (ERROR_FORK); ! ! if (my_pid == 0) { ! close(my_pipe[1]); /* printer is silent */ ! setgid (screen->gid); ! setuid (screen->uid); ! Printer = popen(screen->printer_command, "w"); ! input = fdopen(my_pipe[0], "r"); ! while ((c = fgetc(input)) != EOF) { ! fputc(c, Printer); ! if (chr == '\r' || chr == '\n' || chr == '\f') ! fflush(Printer); ! } ! exit(0); ! } else { ! close(my_pipe[0]); /* won't read from printer */ ! Printer = fdopen(my_pipe[1], "w"); ! } initialized++; } if (Printer != 0) { Index: xc/programs/xterm/version.h diff -c xc/programs/xterm/version.h:3.2.2.3 xc/programs/xterm/version.h:3.2.2.5 *** xc/programs/xterm/version.h:3.2.2.3 Tue Mar 3 23:51:03 1998 --- xc/programs/xterm/version.h Wed Apr 29 14:18:47 1998 *************** *** 1,4 **** ! /* $XFree86: xc/programs/xterm/version.h,v 3.2.2.3 1998/03/03 12:51:03 dawes Exp $ */ /* * This is the string that's printed in response to "xterm -version", or --- 1,4 ---- ! /* $XFree86: xc/programs/xterm/version.h,v 3.2.2.5 1998/04/29 04:18:47 dawes Exp $ */ /* * This is the string that's printed in response to "xterm -version", or *************** *** 6,9 **** * version of xterm has been built. The number in parentheses is my patch * number (T.Dickey). */ ! #define XTERM_VERSION "XFree86 3.9Ad(68)" --- 6,9 ---- * version of xterm has been built. The number in parentheses is my patch * number (T.Dickey). */ ! #define XTERM_VERSION "XFree86 3.3.2.1" Index: xc/lib/Xaw/XawIm.c diff -c xc/lib/Xaw/XawIm.c:1.1.1.4 xc/lib/Xaw/XawIm.c:1.1.1.4.2.1 *** xc/lib/Xaw/XawIm.c:1.1.1.4 Sun Dec 22 14:18:35 1996 --- xc/lib/Xaw/XawIm.c Fri May 1 14:02:42 1998 *************** *** 53,58 **** --- 53,59 ---- in this Software without prior written authorization from the X Consortium. */ + /* $XFree86: xc/lib/Xaw/XawIm.c,v 1.1.1.4.2.1 1998/05/01 04:02:42 dawes Exp $ */ #include #include *************** *** 452,458 **** } else { for (i = 0; i < ve->im.im_list_num; i++) { strcpy(modifiers, "@im="); ! strcat(modifiers, ve->im.im_list[i]); if ((p = XSetLocaleModifiers(modifiers)) != NULL && *p && (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL) break; --- 453,459 ---- } else { for (i = 0; i < ve->im.im_list_num; i++) { strcpy(modifiers, "@im="); ! strncat(modifiers, ve->im.im_list[i], sizeof(modifiers) - 5/*strlen("@im=")*/); if ((p = XSetLocaleModifiers(modifiers)) != NULL && *p && (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL) break; *************** *** 1354,1360 **** strcpy(s, p); save_s = s; ! while(1) { list[i] = s; ss = index(s, ','); if (!ss) { --- 1355,1361 ---- strcpy(s, p); save_s = s; ! while(i < (sizeof(list) / sizeof(list[0]))) { list[i] = s; ss = index(s, ','); if (!ss) { *************** *** 1645,1654 **** if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) && ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) { ! return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer, keysym_return, status_return)); } ! ret = XLookupString( event, tmp_buf, 64, keysym_return, (XComposeStatus*) status_return ); for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) { *buf_p++ = _Xaw_atowc(*tmp_p++); --- 1646,1655 ---- if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) && ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) { ! return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer/sizeof(wchar_t), keysym_return, status_return)); } ! ret = XLookupString( event, tmp_buf, sizeof(tmp_buf), keysym_return, (XComposeStatus*) status_return ); for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) { *buf_p++ = _Xaw_atowc(*tmp_p++);