--- mailx-8.1.1.orig/aux.c +++ mailx-8.1.1/aux.c @@ -280,16 +280,22 @@ * Copy a string, lowercasing it as we go. */ void -istrcpy(dest, src) +istrcpy(dest, src, size) register char *dest, *src; + int size; { + register char *max; - do { - if (isupper(*src)) + max=dest+size-1; + while (dest<=max) { + if (isupper(*src)) { *dest++ = tolower(*src); - else + } else { *dest++ = *src; - } while (*src++ != 0); + } + if (*src++ == 0) + break; + } } /* @@ -606,10 +612,13 @@ break; cp++; if (first) { - strcpy(namebuf, cp); + strncpy(namebuf, cp, LINESIZE); first = 0; - } else - strcpy(rindex(namebuf, '!')+1, cp); + } else { + cp2=rindex(namebuf, '!')+1; + strncpy(cp2, cp, (namebuf+LINESIZE)-cp2); + } + namebuf[LINESIZE-2]='\0'; strcat(namebuf, "!"); goto newname; } @@ -691,7 +700,8 @@ * Lower-case the string, so that "Status" and "status" * will hash to the same place. */ - istrcpy(realfld, field); + istrcpy(realfld, field, BUFSIZ); + realfld[BUFSIZ-1]='\0'; if (ignore[1].i_count > 0) return (!member(realfld, ignore + 1)); else --- mailx-8.1.1.orig/cmd1.c +++ mailx-8.1.1/cmd1.c @@ -465,7 +465,7 @@ char dirname[BUFSIZ]; char *cmd; - if (getfold(dirname) < 0) { + if (getfold(dirname, BUFSIZ) < 0) { printf("No value set for \"folder\"\n"); return 1; } --- mailx-8.1.1.orig/cmd2.c +++ mailx-8.1.1/cmd2.c @@ -496,7 +496,8 @@ if (*list == NOSTR) return igshow(tab, which); for (ap = list; *ap != 0; ap++) { - istrcpy(field, *ap); + istrcpy(field, *ap, BUFSIZ); + field[BUFSIZ-1]='\0'; if (member(field, tab)) continue; h = hash(field); --- mailx-8.1.1.orig/cmd3.c +++ mailx-8.1.1/cmd3.c @@ -65,8 +65,9 @@ char *shell; char cmd[BUFSIZ]; - (void) strcpy(cmd, str); - if (bangexp(cmd) < 0) + (void) strncpy(cmd, str, BUFSIZ); + cmd[BUFSIZ-1]='\0'; + if (bangexp(cmd, BUFSIZ) < 0) return 1; if ((shell = value("SHELL")) == NOSTR) shell = _PATH_CSHELL; @@ -103,8 +104,9 @@ char lastbang[128]; int -bangexp(str) +bangexp(str, size) char *str; + int size; { char bangbuf[BUFSIZ]; register char *cp, *cp2; @@ -144,7 +146,8 @@ printf("!%s\n", bangbuf); fflush(stdout); } - strcpy(str, bangbuf); + strncpy(str, bangbuf, size); + str[size-1]='\0'; strncpy(lastbang, bangbuf, 128); lastbang[127] = 0; return(0); --- mailx-8.1.1.orig/collect.c +++ mailx-8.1.1/collect.c @@ -52,6 +52,11 @@ #include "rcv.h" #include "extern.h" +#ifdef IOSAFE +/* to interact betzeen interrupt handlers and IO routines in fio.c */ +int got_interrupt; + +#endif /* * Read a message from standard output and return a read file to it * or NULL on error. @@ -143,6 +148,9 @@ escape = ESCAPE; eofcount = 0; hadintr = 0; +#ifdef IOSAFE + got_interrupt = 0; +#endif if (!setjmp(colljmp)) { if (getsub) @@ -166,6 +174,12 @@ for (;;) { colljmp_p = 1; c = readline(stdin, linebuf, LINESIZE); +#ifdef IOSAFE + if (got_interrupt) { + got_interrupt = 0; + longjmp(colljmp,1); + } +#endif colljmp_p = 0; if (c < 0) { if (value("interactive") != NOSTR && @@ -268,7 +282,8 @@ hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); break; case 'd': - strcpy(linebuf + 2, getdeadletter()); + strncpy(linebuf + 2, getdeadletter(), LINESIZE - 2); + linebuf[LINESIZE-1]='\0'; /* fall into . . . */ case 'r': case '<': @@ -392,7 +407,11 @@ sigemptyset(&nset); sigaddset(&nset, SIGINT); sigaddset(&nset, SIGHUP); +#ifndef OLDBUG + sigprocmask(SIG_BLOCK, &nset, NULL); +#else sigprocmask(SIG_BLOCK, &nset, &oset); +#endif signal(SIGINT, saveint); signal(SIGHUP, savehup); signal(SIGTSTP, savetstp); @@ -427,6 +446,8 @@ fprintf(stderr, "File exists\n"); return(-1); } + /* FIXME: Fopen with "w" will currently prevent writing to an existig file + (/dev/null), for now I am not sure this would even marginally useful to allow */ if ((of = Fopen(name, "w")) == NULL) { perror(NOSTR); return(-1); @@ -589,10 +610,16 @@ if (colljmp_p) { colljmp_p = 0; hadintr = 0; +#ifdef IOSAFE + got_interrupt = s; +#else longjmp(colljmp, 1); +#endif + } } + /* * On interrupt, come here to save the partial message in ~/dead.letter. * Then jump out of the collection loop. @@ -613,7 +640,12 @@ return; } hadintr = 1; +#ifdef IOSAFE + got_interrupt = s; + return; +#else longjmp(colljmp, 1); +#endif } rewind(collf); if (value("nosave") == NOSTR) --- mailx-8.1.1.orig/dotlock.c +++ mailx-8.1.1/dotlock.c @@ -48,11 +48,33 @@ #include <signal.h> #include "extern.h" +#include "rcv.h" #ifndef O_SYNC #define O_SYNC 0 #endif +/* + * Set the gid if the path is in the normal mail spool + */ +static int perhaps_setgid (name, gid) +char *name; +gid_t gid; +{ + char safelist[] = _PATH_MAILDIR; + char *safepath, *p = safelist; + int len; + + while ((safepath = strtok(p, ":"))) { + p = 0; + len = strlen(safepath); + if (strncmp (name, safepath, len) == 0 && name[len] == '/') + return (setgid (gid)); + } + return 0; +} + + static int create_exclusive __P((const char *)); /* * Create a unique file. O_EXCL does not really work over NFS so we follow @@ -69,11 +91,12 @@ const char *fname; { char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN]; + char apid[40]; /* sufficient for storign 128 bits pids */ const char *ptr; struct timeval tv; pid_t pid; size_t ntries, cookie; - int fd, serrno; + int fd, serrno, cc; struct stat st; (void) gettimeofday(&tv, NULL); @@ -93,12 +116,17 @@ (void) snprintf(path, sizeof(path), "%.*s.%s.%x", ptr - fname, fname, hostname, cookie); + /* * We try to create the unique filename. */ for (ntries = 0; ntries < 5; ntries++) { + perhaps_setgid(path, effectivegid); fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_SYNC, 0); + setgid(realgid); if (fd != -1) { + sprintf(apid,"%d",getpid()); + write(fd, apid, strlen(apid)); (void) close(fd); break; } @@ -107,11 +135,14 @@ else return -1; } - /* * We link the path to the name */ - if (link(path, fname) == -1) + perhaps_setgid(fname, effectivegid); + cc = link(path, fname); + setgid(realgid); + + if (cc == -1) goto bad; /* @@ -121,7 +152,9 @@ if (stat(path, &st) == -1) goto bad; + perhaps_setgid(fname, effectivegid); (void) unlink(path); + setgid(realgid); /* * If the number of links was two (one for the unique file and one @@ -149,6 +182,7 @@ { char path[MAXPATHLEN]; sigset_t nset, oset; + int i; sigemptyset(&nset); sigaddset(&nset, SIGHUP); @@ -162,7 +196,7 @@ (void) snprintf(path, sizeof(path), "%s.lock", fname); - for (;;) { + for (i=0;i<15;i++) { (void) sigprocmask(SIG_BLOCK, &nset, &oset); if (create_exclusive(path) != -1) { (void) sigprocmask(SIG_SETMASK, &oset, NULL); @@ -185,6 +219,8 @@ sleep(pollinterval); } } + fprintf(stderr,"%s seems a stale lock? Need to be removed by hand?\n",path); + return -1; } void @@ -194,5 +230,7 @@ char path[MAXPATHLEN]; (void) snprintf(path, sizeof(path), "%s.lock", fname); + perhaps_setgid(path, effectivegid); (void) unlink(path); + setgid(realgid); } --- mailx-8.1.1.orig/edit.c +++ mailx-8.1.1/edit.c @@ -159,7 +159,7 @@ struct stat statb; extern char *tempEdit; - if ((t = creat(tempEdit, readonly ? 0400 : 0600)) < 0) { + if ((t = open(tempEdit, O_CREAT|O_WRONLY|O_EXCL, readonly ? 0400 : 0600)) < 0) { perror(tempEdit); goto out; } --- mailx-8.1.1.orig/extern.h +++ mailx-8.1.1/extern.h @@ -50,6 +50,7 @@ struct name *put __P((struct name *, struct name *)); struct name *tailof __P((struct name *)); struct name *usermap __P((struct name *)); +FILE *safe_fopen __P((char *, char *)); FILE *Fdopen __P((int, char *)); FILE *Fopen __P((char *, char *)); FILE *Popen __P((char *, char *)); @@ -79,7 +80,7 @@ char *username __P((void)); char *value __P((char [])); char *vcopy __P((char [])); -char *yankword __P((char *, char [])); +char *yankword __P((char *, char [], int)); int Fclose __P((FILE *)); int More __P((void *)); int Pclose __P((FILE *)); @@ -94,7 +95,7 @@ int append __P((struct message *, FILE *)); int argcount __P((char **)); void assign __P((char [], char [])); -int bangexp __P((char *)); +int bangexp __P((char *, int)); int blankline __P((char [])); void brokpipe __P((int)); int charcount __P((char *, int)); @@ -130,7 +131,7 @@ int file __P((void *)); struct grouphead * findgroup __P((char [])); -void findmail __P((char *, char *)); +void findmail __P((char *, char *, int)); int first __P((int, int)); void fixhead __P((struct header *, struct name *)); void fmt __P((char *, struct name *, FILE *, int)); @@ -139,7 +140,7 @@ void free_child __P((int)); int from __P((void *)); off_t fsize __P((FILE *)); -int getfold __P((char *)); +int getfold __P((char *, int)); int gethfield __P((FILE *, char [], int, char **)); int getmsglist __P((char *, int *, int)); int getrawlist __P((char [], char **, int)); @@ -164,7 +165,7 @@ int ishead __P((char [])); int isign __P((char *, struct ignoretab [])); int isprefix __P((char *, char *)); -void istrcpy __P((char *, char *)); +void istrcpy __P((char *, char *, int)); const struct cmd * lex __P((char [])); void load __P((char *)); --- mailx-8.1.1.orig/fio.c +++ mailx-8.1.1/fio.c @@ -74,7 +74,7 @@ char linebuf[LINESIZE]; /* Get temporary file. */ - (void)sprintf(linebuf, "%s/mail.XXXXXX", tmpdir); + (void)snprintf(linebuf,LINESIZE,"%s/mail.XXXXXX", tmpdir); if ((c = mkstemp(linebuf)) == -1 || (mestmp = Fdopen(c, "r+")) == NULL) { (void)fprintf(stderr, "mail: can't open %s\n", linebuf); @@ -178,14 +178,54 @@ char *linebuf; int linesize; { - register int n; - + register int n,oldfl; + char *res; clearerr(ibuf); - if (fgets(linebuf, linesize, ibuf) == NULL) - return -1; +#ifdef IOSAFE + /* we want to be able to get interrupts while waiting user-input + we cannot to safely inside a stdio call, so we first ensure there + is now data in the stdio buffer by doing the stdio call with the descriptor + in non-blocking state and then do a select. + Hope it is safe (the libc should not break on a EAGAIN) + lprylli@graville.fdn.fr*/ + n = 0; /* number of caracters already read */ + while (n < linesize - 1) { + errno = 0; + oldfl = fcntl(fileno(ibuf),F_GETFL); + fcntl(fileno(ibuf),F_SETFL,oldfl | O_NONBLOCK); + res = fgets(linebuf + n, linesize-n, ibuf); + fcntl(fileno(ibuf),F_SETFL,oldfl); + if (res != NULL) { + n = strlen(linebuf); + if (n > 0 && linebuf[n-1] == '\n') + break; + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + clearerr(ibuf); + } else { + /* probably EOF one the file descriptors */ + if (n > 0) + break; + else + return -1; + + }{ + extern int got_interrupt; + fd_set rds; + FD_ZERO(&rds); + FD_SET(fileno(ibuf),&rds); + select(fileno(ibuf)+1,&rds,NULL,NULL,NULL); + /* if an interrupt occur drops the current line and returns */ + if (got_interrupt) + return -1; + } + } +#else + if (fgets(linebuf, linesize, ibuf) == NULL) + return -1; +#endif n = strlen(linebuf); if (n > 0 && linebuf[n - 1] == '\n') - linebuf[--n] = '\0'; + linebuf[--n] = '\0'; return n; } @@ -336,7 +376,7 @@ */ switch (*name) { case '%': - findmail(name[1] ? name + 1 : myname, xname); + findmail(name[1] ? name + 1 : myname, xname, PATHSIZE); return savestr(xname); case '#': if (name[1] != 0) @@ -351,13 +391,13 @@ name = "~/mbox"; /* fall through */ } - if (name[0] == '+' && getfold(cmdbuf) >= 0) { - sprintf(xname, "%s/%s", cmdbuf, name + 1); + if (name[0] == '+' && getfold(cmdbuf, PATHSIZE) >= 0) { + snprintf(xname, PATHSIZE, "%s/%s", cmdbuf, name + 1); name = savestr(xname); } /* catch the most common shell meta character */ if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) { - sprintf(xname, "%s%s", homedir, name + 1); + snprintf(xname, PATHSIZE, "%s%s", homedir, name + 1); name = savestr(xname); } if (!anyof(name, "~{[*?$`'\"\\")) @@ -366,7 +406,7 @@ perror("pipe"); return name; } - sprintf(cmdbuf, "echo %s", name); + snprintf(cmdbuf, PATHSIZE, "echo %s", name); if ((shell = value("SHELL")) == NOSTR) shell = _PATH_CSHELL; pid = start_command(shell, 0, -1, pivec[1], "-c", cmdbuf, NOSTR); @@ -376,21 +416,22 @@ return NOSTR; } close(pivec[1]); - l = read(pivec[0], xname, BUFSIZ); + l = read(pivec[0], xname, PATHSIZE); + if (l < 0) { + perror("read"); + close(pivec[0]); + return NOSTR; + } close(pivec[0]); if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) { fprintf(stderr, "\"%s\": Expansion failed.\n", name); return NOSTR; } - if (l < 0) { - perror("read"); - return NOSTR; - } if (l == 0) { fprintf(stderr, "\"%s\": No match.\n", name); return NOSTR; } - if (l == BUFSIZ) { + if (l == PATHSIZE) { fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name); return NOSTR; } @@ -409,17 +450,20 @@ * Determine the current folder directory name. */ int -getfold(name) +getfold(name, size) char *name; + int size; { char *folder; if ((folder = value("folder")) == NOSTR) return (-1); - if (*folder == '/') - strcpy(name, folder); - else - sprintf(name, "%s/%s", homedir, folder); + if (*folder == '/') { + strncpy(name, folder, size); + name[size-1]='\0'; + } else { + snprintf(name, size, "%s/%s", homedir, folder); + } return (0); } @@ -436,7 +480,7 @@ else if (*cp != '/') { char buf[PATHSIZE]; - (void) sprintf(buf, "~/%s", cp); + (void) snprintf(buf, PATHSIZE, "~/%s", cp); cp = expand(buf); } return cp; --- mailx-8.1.1.orig/glob.h +++ mailx-8.1.1/glob.h @@ -83,6 +83,8 @@ int screenheight; /* Screen height, or best guess, for "header" command */ int realscreenheight; /* the real screen height */ +gid_t effectivegid; /* Saved from when we started up */ +gid_t realgid; /* Saved from when we started up */ #include <setjmp.h> --- mailx-8.1.1.orig/head.c +++ mailx-8.1.1/head.c @@ -73,10 +73,13 @@ fail(linebuf, "No from or date field"); return (0); } + /* be very tolerant about the date */ +#if 0 if (!isdate(hl.l_date)) { fail(linebuf, "Date field not legal date"); return (0); } +#endif /* * I guess we got it! */ --- mailx-8.1.1.orig/lex.c +++ mailx-8.1.1/lex.c @@ -134,16 +134,19 @@ } shudclob = 1; edit = isedit; - strcpy(prevfile, mailname); - if (name != mailname) - strcpy(mailname, name); + strncpy(prevfile, mailname, PATHSIZE); + prevfile[PATHSIZE-1]='\0'; + if (name != mailname) { + strncpy(mailname, name, PATHSIZE); + mailname[PATHSIZE-1]='\0'; + } mailsize = fsize(ibuf); - if ((otf = fopen(tempMesg, "w")) == NULL) { + if ((otf = safe_fopen(tempMesg, "w")) == NULL) { perror(tempMesg); exit(1); } (void) fcntl(fileno(otf), F_SETFD, 1); - if ((itf = fopen(tempMesg, "r")) == NULL) { + if ((itf = safe_fopen(tempMesg, "r")) == NULL) { perror(tempMesg); exit(1); } @@ -616,10 +619,10 @@ s++; } ename = mailname; - if (getfold(fname) >= 0) { + if (getfold(fname, BUFSIZ-1) >= 0) { strcat(fname, "/"); if (strncmp(fname, mailname, strlen(fname)) == 0) { - sprintf(zname, "+%s", mailname + strlen(fname)); + snprintf(zname, BUFSIZ, "+%s", mailname + strlen(fname)); ename = zname; } } --- mailx-8.1.1.orig/list.c +++ mailx-8.1.1/list.c @@ -515,7 +515,8 @@ int quotec; if (regretp >= 0) { - strcpy(lexstring, string_stack[regretp]); + strncpy(lexstring, string_stack[regretp], STRINGLEN); + lexstring[STRINGLEN-1]='\0'; lexnumber = numberstack[regretp]; return(regretstack[regretp--]); } @@ -695,10 +696,12 @@ register char *cp, *cp2, *backup; str++; - if (strlen(str) == 0) + if (strlen(str) == 0) { str = lastscan; - else - strcpy(lastscan, str); + } else { + strncpy(lastscan, str, 128); + lastscan[127]='\0'; + } mp = &message[mesg-1]; /* --- mailx-8.1.1.orig/main.c +++ mailx-8.1.1/main.c @@ -48,6 +48,12 @@ #endif #endif /* not lint */ +/* + * Most strcpy/sprintf functions have been changed to strncpy/snprintf to + * correct several buffer overruns (at least one ot them was exploitable). + * Sat Jun 20 04:58:09 CEST 1998 Alvaro Martinez Echevarria <alvaro@lander.es> + */ + #include "rcv.h" #include <fcntl.h> #include <sys/ioctl.h> @@ -70,9 +76,24 @@ struct name *to, *cc, *bcc, *smopts; char *subject; char *ef; + char* cmd; char nosrc = 0; sig_t prevint; + /* + * Absolutely the first thing we do is save our egid + * and set it to the rgid, so that we can safely run + * setgid. We use the sgid (saved set-gid) to allow ourselves + * to revert to the egid if we want (temporarily) to become + * priveliged. + */ + effectivegid = getegid(); + realgid = getgid(); + if (setgid (realgid) < 0) { + perror("setgid"); + exit(1); + } + /* * Set up a reasonable environment. * Figure out whether we are being run interactively, @@ -81,6 +102,26 @@ (void) signal(SIGCHLD, sigchild); if (isatty(0)) assign("interactive", ""); + + /* + * Grab some stuff from the environment we might use + */ + + if (cmd = getenv("PAGER")) + assign("PAGER", cmd); + if (cmd = getenv("LISTER")) + assign("LISTER", cmd); + if (cmd = getenv("SHELL")) + assign("SHELL", cmd); + if (cmd = getenv("EDITOR")) + assign("EDITOR", cmd); + if (cmd = getenv("VISUAL")) + assign("VISUAL", cmd); + if (cmd = getenv("MBOX")) + assign("MBOX", cmd); + if (cmd = getenv("DEAD")) + assign("DEAD", cmd); + image = -1; /* * Now, determine how we are being used. @@ -287,12 +328,12 @@ if (ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) ws.ws_col = ws.ws_row = 0; if (tcgetattr(1, &tbuf) < 0) - ospeed = 9600; + ospeed = B9600; else ospeed = cfgetospeed(&tbuf); - if (ospeed < 1200) + if (ospeed < B1200) screenheight = 9; - else if (ospeed == 1200) + else if (ospeed == B1200) screenheight = 14; else if (ws.ws_row != 0) screenheight = ws.ws_row; --- mailx-8.1.1.orig/names.c +++ mailx-8.1.1/names.c @@ -108,7 +108,7 @@ top = NIL; np = NIL; cp = line; - while ((cp = yankword(cp, nbuf)) != NOSTR) { + while ((cp = yankword(cp, nbuf, BUFSIZ)) != NOSTR) { t = nalloc(nbuf, ntype); if (top == NIL) top = t; @@ -171,10 +171,12 @@ * Throw away things between ()'s, and take anything between <>. */ char * -yankword(ap, wbuf) +yankword(ap, wbuf, maxsize) char *ap, wbuf[]; + int maxsize; { register char *cp, *cp2; + int used = 0; cp = ap; for (;;) { @@ -201,10 +203,11 @@ break; } if (*cp == '<') - for (cp2 = wbuf; *cp && (*cp2++ = *cp++) != '>';) + /* Pre-increment "used" so we leave room for the trailing zero */ + for (cp2 = wbuf; *cp && (++used < maxsize) && (*cp2++ = *cp++) != '>';) ; else - for (cp2 = wbuf; *cp && !index(" \t,(", *cp); *cp2++ = *cp++) + for (cp2 = wbuf; *cp && (++used < maxsize) && !index(" \t,(", *cp); *cp2++ = *cp++) ; *cp2 = '\0'; return cp; @@ -253,7 +256,8 @@ */ if (image < 0) { - if ((fout = Fopen(tempEdit, "a")) == NULL) { + /* hopefully we always create the file, so I change the "a" to "w" the line below */ + if ((fout = Fopen(tempEdit, "w")) == NULL) { perror(tempEdit); senderr++; goto cant; --- mailx-8.1.1.orig/quit.c +++ mailx-8.1.1/quit.c @@ -266,7 +266,8 @@ if (mp->m_flag & MBOX) if (send(mp, obuf, saveignore, NOSTR) < 0) { perror(mbox); - Fclose(ibuf); + if (ibuf) + Fclose(ibuf); Fclose(obuf); Fclose(fbuf); dot_unlock(mailname); --- mailx-8.1.1.orig/tty.c +++ mailx-8.1.1/tty.c @@ -50,6 +50,8 @@ #include "rcv.h" #include "extern.h" +#include <errno.h> +#include <fcntl.h> #include <sys/ioctl.h> static cc_t c_erase; /* Current erase char */ @@ -60,6 +62,10 @@ static int ttyset; /* We must now do erase/kill */ #endif +#ifdef IOSAFE +static int got_interrupt; +#endif + /* * Read all relevant header fields. */ @@ -104,8 +110,15 @@ if ((savequit = signal(SIGQUIT, SIG_IGN)) == SIG_DFL) signal(SIGQUIT, SIG_DFL); #else - if (setjmp(intjmp)) +#ifdef IOSAFE + got_interrupt = 0; +#endif + if (setjmp(intjmp)) { + /* avoid garbled output with C-c */ + printf("\n"); + fflush(stdout); goto out; + } saveint = signal(SIGINT, ttyint); #endif if (gflags & GTO) { @@ -207,14 +220,26 @@ cp2 = cp; if (setjmp(rewrite)) goto redo; +#ifdef IOSAFE + got_interrupt = 0; +#endif signal(SIGTSTP, ttystop); signal(SIGTTOU, ttystop); signal(SIGTTIN, ttystop); clearerr(stdin); while (cp2 < canonb + BUFSIZ) { +#ifdef IOSAFE + c = safegetc(stdin); + /* this is full of ACE but hopefully, interrupts will only occur in the above read */ + if (got_interrupt == SIGINT) + longjmp(intjmp,1); + else if (got_interrupt) + longjmp(rewrite,1); +#else c = getc(stdin); +#endif if (c == EOF || c == '\n') - break; + break; *cp2++ = c; } *cp2 = 0; @@ -280,6 +305,9 @@ kill(0, s); sigprocmask(SIG_UNBLOCK, &nset, NULL); signal(s, old_action); +#ifdef IOSAFE + got_interrupt = s; +#endif longjmp(rewrite, 1); } @@ -288,5 +316,40 @@ ttyint(s) int s; { +#ifdef IOSAFE + got_interrupt = s; +#else longjmp(intjmp, 1); +#endif +} + +#ifdef IOSAFE +/* it is very awful, but only way I see to be able to do a interruptable stdio call */ +int safegetc(FILE *ibuf) +{ + int oldfl; + int res; + while (1) { + errno = 0; + oldfl = fcntl(fileno(ibuf),F_GETFL); + fcntl(fileno(ibuf),F_SETFL,oldfl | O_NONBLOCK); + res = getc(ibuf); + fcntl(fileno(ibuf),F_SETFL,oldfl); + if (res != EOF) + return res; + else if (errno == EAGAIN || errno == EWOULDBLOCK) { + fd_set rds; + clearerr(ibuf); + FD_ZERO(&rds); + FD_SET(fileno(ibuf),&rds); + select(fileno(ibuf)+1,&rds,NULL,NULL,NULL); + /* if an interrupt occur drops the current line and returns */ + if (got_interrupt) + return EOF; + } else { + /* probably EOF one the file descriptors */ + return EOF; + } + } } +#endif --- mailx-8.1.1.orig/v7.local.c +++ mailx-8.1.1/v7.local.c @@ -60,15 +60,26 @@ * mail is queued). */ void -findmail(user, buf) +findmail(user, buf, size) char *user, *buf; + int size; { char *mbox; - if (!(mbox = getenv("MAIL"))) - (void)sprintf(buf, "%s/%s", _PATH_MAILDIR, user); - else - (void)strcpy(buf, mbox); + if (!(mbox = getenv("MAIL"))) { + char safelist[] = _PATH_MAILDIR; + char *safepath, *p = safelist; + while ((safepath = strtok(p, ":"))) { + p = 0; + (void)snprintf(buf, size, "%s/%s", safepath, user); + if (access(buf, F_OK) == 0) + break; + } + } else { + (void)strncpy(buf, mbox, size); + buf[size-1]='\0'; + } + } /* --- mailx-8.1.1.orig/vars.c +++ mailx-8.1.1/vars.c @@ -83,7 +83,7 @@ vfree(cp) char *cp; { - if (*cp) + if (cp && *cp) free(cp); } @@ -99,6 +99,8 @@ char *new; unsigned len; + if (str == NULL) + return NULL; if (*str == '\0') return ""; len = strlen(str) + 1; @@ -120,7 +122,7 @@ register struct var *vp; if ((vp = lookup(name)) == NOVAR) - return(getenv(name)); + return NULL; return(vp->v_value); } --- mailx-8.1.1.orig/popen.c +++ mailx-8.1.1/popen.c @@ -45,6 +45,7 @@ #include "rcv.h" #include <sys/wait.h> #include <fcntl.h> +#include <errno.h> #include "extern.h" #define READ 0 @@ -71,12 +72,42 @@ static int file_pid __P((FILE *)); FILE * +safe_fopen(file, mode) + char *file, *mode; +{ + int omode, fd; + + if (!strcmp(mode, "r")) { + omode = O_RDONLY; + } else if (!strcmp(mode, "w")) { + omode = O_WRONLY | O_CREAT | O_EXCL; + } else if (!strcmp(mode, "a")) { + omode = O_WRONLY | O_APPEND | O_CREAT; + } else if (!strcmp(mode, "a+")) { + omode = O_RDWR | O_APPEND; + } else if (!strcmp(mode, "r+")) { + omode = O_RDWR; + } else if (!strcmp(mode, "w+")) { + omode = O_RDWR | O_CREAT | O_EXCL; + } else { + fprintf(stderr, + "Internal error: bad stdio open mode %s\n", mode); + errno = EINVAL; + return NULL; + } + + if ((fd = open(file, omode, 0666)) < 0) + return NULL; + return fdopen(fd, mode); +} + +FILE * Fopen(file, mode) char *file, *mode; { FILE *fp; - if ((fp = fopen(file, mode)) != NULL) { + if ((fp = safe_fopen(file, mode)) != NULL) { register_file(fp, 0, 0); (void) fcntl(fileno(fp), F_SETFD, 1); }