Prereq: public-patch-25 *** /tmp/da20646 Wed Nov 3 20:04:26 1993 --- mit/bug-report Wed Nov 3 20:04:25 1993 *************** *** 2,8 **** Subject: [area]: [synopsis] [replace with actual area and short description] VERSION: ! R5, public-patch-25 [MIT public patches will edit this line to indicate the patch level] CLIENT MACHINE and OPERATING SYSTEM: --- 2,8 ---- Subject: [area]: [synopsis] [replace with actual area and short description] VERSION: ! R5, public-patch-26 [MIT public patches will edit this line to indicate the patch level] CLIENT MACHINE and OPERATING SYSTEM: *** /tmp/da21897 Thu Nov 4 08:57:24 1993 --- mit/clients/xterm/misc.c Thu Nov 4 08:57:23 1993 *************** *** 1,5 **** /* ! * $XConsortium: misc.c,v 1.92 92/03/13 17:02:08 gildea Exp $ */ /* --- 1,5 ---- /* ! * $XConsortium: misc.c,v 1.95.1.1 93/11/04 08:56:48 gildea Exp $ */ /* *************** *** 444,449 **** --- 444,518 ---- } } + #if defined(ALLOWLOGGING) || defined(DEBUG) + + #ifndef X_NOT_POSIX + #define HAS_WAITPID + #endif + + /* + * create a file only if we could with the permissions of the real user id. + * We could emulate this with careful use of access() and following + * symbolic links, but that is messy and has race conditions. + * Forking is messy, too, but we can't count on setreuid() or saved set-uids + * being available. + */ + void + creat_as(uid, gid, pathname, mode) + int uid; + int gid; + char *pathname; + int mode; + { + int fd; + int waited; + int pid; + #ifndef HAS_WAITPID + int (*chldfunc)(); + + chldfunc = signal(SIGCHLD, SIG_DFL); + #endif + pid = fork(); + switch (pid) + { + case 0: /* child */ + setgid(gid); + setuid(uid); + fd = open(pathname, O_WRONLY|O_CREAT|O_APPEND, mode); + if (fd >= 0) { + close(fd); + _exit(0); + } else + _exit(1); + case -1: /* error */ + return; + default: /* parent */ + #ifdef HAS_WAITPID + waitpid(pid, NULL, 0); + #else + waited = wait(NULL); + signal(SIGCHLD, chldfunc); + /* + Since we had the signal handler uninstalled for a while, + we might have missed the termination of our screen child. + If we can check for this possibility without hanging, do so. + */ + do + if (waited == term->screen.pid) + Cleanup(0); + while ( (waited=nonblocking_wait()) > 0); + #endif + } + } + #endif + + #ifdef ALLOWLOGGING + /* + * logging is a security hole, since it allows a setuid program to + * write arbitrary data to an arbitrary file. So it is disabled + * by default. + */ + StartLog(screen) register TScreen *screen; { *************** *** 530,551 **** return; #endif } else { ! if(access(screen->logfile, F_OK) == 0) { ! if(access(screen->logfile, W_OK) < 0) ! return; ! } else if(cp = rindex(screen->logfile, '/')) { ! *cp = 0; ! i = access(screen->logfile, W_OK); ! *cp = '/'; ! if(i < 0) ! return; ! } else if(access(".", W_OK) < 0) return; ! if((screen->logfd = open(screen->logfile, O_WRONLY | O_APPEND | ! O_CREAT, 0644)) < 0) ! return; ! chown(screen->logfile, screen->uid, screen->gid); } screen->logstart = screen->TekEmu ? Tbptr : bptr; screen->logging = TRUE; --- 599,618 ---- return; #endif } else { ! if(access(screen->logfile, F_OK) != 0) { ! if (errno == ENOENT) ! creat_as(screen->uid, screen->gid, ! screen->logfile, 0644); ! else return; ! } + if(access(screen->logfile, F_OK) != 0 + || access(screen->logfile, W_OK) != 0) + return; + if((screen->logfd = open(screen->logfile, O_WRONLY | O_APPEND, + 0644)) < 0) + return; } screen->logstart = screen->TekEmu ? Tbptr : bptr; screen->logging = TRUE; *************** *** 587,592 **** --- 654,660 ---- CloseLog(screen); } #endif /* ALLOWLOGFILEEXEC */ + #endif /* ALLOWLOGGING */ do_osc(func) *************** *** 626,631 **** --- 694,700 ---- Changetitle(buf); break; + #ifdef ALLOWLOGGING case 46: /* new log file */ #ifdef ALLOWLOGFILECHANGES /* *************** *** 643,648 **** --- 712,718 ---- Bell(); #endif break; + #endif /* ALLOWLOGGING */ case 50: SetVTFont (fontMenu_fontescape, True, buf, NULL); *************** *** 903,912 **** --- 973,984 ---- register TScreen *screen = &term->screen; if (screen->TekEmu) { + #ifdef ALLOWLOGGING if (screen->logging) { FlushLog (screen); screen->logstart = buffer; } + #endif longjmp(Tekend, 1); } return; *************** *** 917,926 **** --- 989,1000 ---- register TScreen *screen = &term->screen; if (!screen->TekEmu) { + #ifdef ALLOWLOGGING if(screen->logging) { FlushLog(screen); screen->logstart = Tbuffer; } + #endif screen->TekEmu = TRUE; longjmp(VTend, 1); } *** /tmp/da17839 Wed Nov 3 18:16:38 1993 --- mit/clients/xterm/Tekproc.c Wed Nov 3 18:16:37 1993 *************** *** 1,5 **** /* ! * $XConsortium: Tekproc.c,v 1.107 91/06/25 19:49:48 gildea Exp $ * * Warning, there be crufty dragons here. */ --- 1,5 ---- /* ! * $XConsortium: Tekproc.c,v 1.112 93/02/25 17:17:40 gildea Exp $ * * Warning, there be crufty dragons here. */ *************** *** 46,51 **** --- 46,52 ---- #include #include #include + #include /* * Check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX *************** *** 74,80 **** #define TekColormap DefaultColormap( screen->display, \ DefaultScreen(screen->display) ) ! #define DefaultGCID DefaultGC(screen->display, DefaultScreen(screen->display))->gid /* Tek defines */ --- 75,81 ---- #define TekColormap DefaultColormap( screen->display, \ DefaultScreen(screen->display) ) ! #define DefaultGCID XGContextFromGC(DefaultGC(screen->display, DefaultScreen(screen->display))) /* Tek defines */ *************** *** 188,194 **** --- 189,197 ---- /* menu actions */ { "allow-send-events", HandleAllowSends }, { "set-visual-bell", HandleSetVisualBell }, + #ifdef ALLOWLOGGING { "set-logging", HandleLogging }, + #endif { "redraw", HandleRedraw }, { "send-signal", HandleSendSignal }, { "quit", HandleQuit }, *************** *** 335,342 **** register int c, x, y; char ch; ! for( ; ; ) ! switch(Tparsestate[c = input()]) { case CASE_REPORT: /* report address */ if(screen->TekGIN) { --- 338,346 ---- register int c, x, y; char ch; ! for( ; ; ) { ! c = input(); ! switch(Tparsestate[c]) { case CASE_REPORT: /* report address */ if(screen->TekGIN) { *************** *** 356,365 **** --- 360,371 ---- /* special return to vt102 mode */ Tparsestate = curstate; TekRecord->ptr[-1] = NAK; /* remove from recording */ + #ifdef ALLOWLOGGING if(screen->logging) { FlushLog(screen); screen->logstart = buffer; } + #endif return; case CASE_SPT_STATE: *************** *** 626,631 **** --- 632,638 ---- Tparsestate = curstate; break; } + } } static int rcnt; *************** *** 667,675 **** (int *) NULL, &crocktimeout); #endif if(Tselect_mask & pty_mask) { if(screen->logging) FlushLog(screen); ! Tbcnt = read(screen->respond, Tbptr = Tbuffer, BUF_SIZE); if(Tbcnt < 0) { if(errno == EIO) Cleanup (0); --- 674,684 ---- (int *) NULL, &crocktimeout); #endif if(Tselect_mask & pty_mask) { + #ifdef ALLOWLOGGING if(screen->logging) FlushLog(screen); ! #endif ! Tbcnt = read(screen->respond, (char *)(Tbptr = Tbuffer), BUF_SIZE); if(Tbcnt < 0) { if(errno == EIO) Cleanup (0); *************** *** 1150,1157 **** * The following is called the create the tekWidget */ ! static void TekInitialize(request, new) Widget request, new; { /* look for focus related events on the shell, because we need * to care about the shell's border being part of our focus. --- 1159,1168 ---- * The following is called the create the tekWidget */ ! static void TekInitialize(request, new, args, num_args) Widget request, new; + ArgList args; + Cardinal *num_args; { /* look for focus related events on the shell, because we need * to care about the shell's border being part of our focus. *************** *** 1549,1565 **** } /* write copy of screen to a file */ TekCopy() { - register TekLink *Tp; - register int tekcopyfd; register TScreen *screen = &term->screen; register struct tm *tp; long l; char buf[32]; time(&l); tp = localtime(&l); sprintf(buf, "COPY%02d-%02d-%02d.%02d:%02d:%02d", tp->tm_year, --- 1560,1585 ---- } + #ifndef X_NOT_POSIX + #define HAS_WAITPID + #endif + /* write copy of screen to a file */ TekCopy() { register TScreen *screen = &term->screen; register struct tm *tp; long l; char buf[32]; + int waited; + int pid; + #ifndef HAS_WAITPID + int (*chldfunc)(); + chldfunc = signal(SIGCHLD, SIG_DFL); + #endif + time(&l); tp = localtime(&l); sprintf(buf, "COPY%02d-%02d-%02d.%02d:%02d:%02d", tp->tm_year, *************** *** 1573,1593 **** Bell(); return; } ! if((tekcopyfd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { ! Bell(); ! return; ! } ! chown(buf, screen->uid, screen->gid); ! sprintf(buf, "\033%c\033%c", screen->page.fontsize + '8', ! screen->page.linetype + '`'); ! write(tekcopyfd, buf, 4); ! Tp = &Tek0; ! do { write(tekcopyfd, (char *)Tp->data, Tp->count); Tp = Tp->next; ! } while(Tp); ! close(tekcopyfd); } - - - --- 1593,1645 ---- Bell(); return; } ! ! /* Write the file in an unprivileged child process because ! using access before the open still leaves a small window ! of opportunity. */ ! pid = fork(); ! switch (pid) ! { ! case 0: /* child */ ! { ! register int tekcopyfd; ! char initbuf[5]; ! register TekLink *Tp; ! ! setgid(screen->gid); ! setuid(screen->uid); ! tekcopyfd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0666); ! if (tekcopyfd < 0) ! _exit(1); ! sprintf(initbuf, "\033%c\033%c", screen->page.fontsize + '8', ! screen->page.linetype + '`'); ! write(tekcopyfd, initbuf, 4); ! Tp = &Tek0; ! do { write(tekcopyfd, (char *)Tp->data, Tp->count); Tp = Tp->next; ! } while(Tp); ! close(tekcopyfd); ! _exit(0); ! } ! case -1: /* error */ ! Bell(); ! return; ! default: /* parent */ ! #ifdef HAS_WAITPID ! waitpid(pid, NULL, 0); ! #else ! waited = wait(NULL); ! signal(SIGCHLD, chldfunc); ! /* ! Since we had the signal handler uninstalled for a while, ! we might have missed the termination of our screen child. ! If we can check for this possibility without hanging, do so. ! */ ! do ! if (waited == term->screen.pid) ! Cleanup(0); ! while ( (waited=nonblocking_wait()) > 0); ! #endif ! } }