diff --git a/usr.bin/wall/ttymsg.c b/usr.bin/wall/ttymsg.c --- a/usr.bin/wall/ttymsg.c +++ b/usr.bin/wall/ttymsg.c @@ -29,18 +29,20 @@ * SUCH DAMAGE. */ - - #include +#include #include + +#include #include +#include #include #include #include #include #include -#include #include +#include #include #include "ttymsg.h" @@ -61,9 +63,8 @@ char device[MAXNAMLEN] = _PATH_DEV; static char errbuf[1024]; char *p; - int forked; + cap_rights_t rights; - forked = 0; if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0]))) return ("too many iov's (change code in wall/ttymsg.c)"); @@ -73,8 +74,8 @@ p += 4; if (strchr(p, '/') != NULL) { /* A slash is an attempt to break security... */ - (void) snprintf(errbuf, sizeof(errbuf), - "Too many '/' in \"%s\"", device); + (void)snprintf(errbuf, sizeof(errbuf), "Too many '/' in \"%s\"", + device); return (errbuf); } @@ -82,14 +83,18 @@ * open will fail on slip lines or exclusive-use lines * if not running as root; not an error. */ - if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { + if ((fd = open(device, O_WRONLY | O_NONBLOCK, 0)) < 0) { if (errno == EBUSY || errno == EACCES) return (NULL); - (void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device, + (void)snprintf(errbuf, sizeof(errbuf), "%s: %s", device, strerror(errno)); return (errbuf); } + cap_rights_init(&rights, CAP_WRITE); + if (caph_rights_limit(fd, &rights) == -1) + err(1, "unable to limit capability rights"); + for (cnt = 0, left = 0; cnt < iovcnt; ++cnt) left += iov[cnt].iov_len; @@ -100,7 +105,7 @@ if (wret >= 0) { left -= wret; if (iov != localiov) { - bcopy(iov, localiov, + bcopy(iov, localiov, iovcnt * sizeof(struct iovec)); iov = localiov; } @@ -115,31 +120,28 @@ } continue; } + if (caph_enter() < 0) + err(1, "unable to enter capability mode"); if (errno == EWOULDBLOCK) { int cpid; - if (forked) { - (void) close(fd); - _exit(1); - } - cpid = fork(); + cpid = pdfork(&fd, 0); if (cpid < 0) { - (void) snprintf(errbuf, sizeof(errbuf), + (void)snprintf(errbuf, sizeof(errbuf), "fork: %s", strerror(errno)); - (void) close(fd); + (void)close(fd); return (errbuf); } - if (cpid) { /* parent */ - (void) close(fd); + if (cpid) { /* parent */ + (void)close(fd); return (NULL); } - forked++; /* wait at most tmout seconds */ - (void) signal(SIGALRM, SIG_DFL); - (void) signal(SIGTERM, SIG_DFL); /* XXX */ - (void) sigsetmask(0); - (void) alarm((u_int)tmout); - (void) fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */ + (void)signal(SIGALRM, SIG_DFL); + (void)signal(SIGTERM, SIG_DFL); /* XXX */ + (void)sigsetmask(0); + (void)alarm((u_int)tmout); + (void)fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */ continue; } /* @@ -148,16 +150,12 @@ */ if (errno == ENODEV || errno == EIO) break; - (void) close(fd); - if (forked) - _exit(1); - (void) snprintf(errbuf, sizeof(errbuf), - "%s: %s", device, strerror(errno)); + (void)close(fd); + (void)snprintf(errbuf, sizeof(errbuf), "%s: %s", device, + strerror(errno)); return (errbuf); } - (void) close(fd); - if (forked) - _exit(0); + (void)close(fd); return (NULL); } diff --git a/usr.bin/wall/wall.c b/usr.bin/wall/wall.c --- a/usr.bin/wall/wall.c +++ b/usr.bin/wall/wall.c @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -60,8 +61,8 @@ static struct wallgroup { struct wallgroup *next; - char *name; - gid_t gid; + char *name; + gid_t gid; } *grouplist; static int nobanner; static int mbufsize; @@ -95,6 +96,12 @@ (void)setlocale(LC_CTYPE, ""); + /* + * Cache NLS data, for strerror, for err(3), before entering capability + * mode. + */ + caph_cache_catpages(); + while ((ch = getopt(argc, argv, "g:n")) != -1) switch (ch) { case 'n': @@ -148,7 +155,8 @@ ingroup = 1; else if ((grp = getgrgid(g->gid)) != NULL) { for (np = grp->gr_mem; *np; np++) { - if (strcmp(*np, utmp->ut_user) == 0) { + if (strcmp(*np, + utmp->ut_user) == 0) { ingroup = 1; break; } @@ -158,7 +166,7 @@ if (ingroup == 0) continue; } - if ((p = ttymsg(&iov, 1, utmp->ut_line, 60*5)) != NULL) + if ((p = ttymsg(&iov, 1, utmp->ut_line, 60 * 5)) != NULL) warnx("%s", p); } exit(0); @@ -212,13 +220,12 @@ * in column 80, but that can't be helped. */ (void)fwprintf(fp, L"\r%79s\r\n", " "); - (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t), - L"Broadcast Message from %s@%s", - whom, hostname); + (void)swprintf(lbuf, sizeof(lbuf) / sizeof(wchar_t), + L"Broadcast Message from %s@%s", whom, hostname); (void)fwprintf(fp, L"%-79.79S\007\007\r\n", lbuf); - (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t), - L" (%s) at %d:%02d %s...", tty, - lt->tm_hour, lt->tm_min, lt->tm_zone); + (void)swprintf(lbuf, sizeof(lbuf) / sizeof(wchar_t), + L" (%s) at %d:%02d %s...", tty, lt->tm_hour, + lt->tm_min, lt->tm_zone); (void)fwprintf(fp, L"%-79.79S\r\n", lbuf); } (void)fwprintf(fp, L"%79s\r\n", " "); @@ -232,7 +239,7 @@ err(1, "setegid failed"); } cnt = 0; - while (fgetws(lbuf, sizeof(lbuf)/sizeof(wchar_t), stdin)) { + while (fgetws(lbuf, sizeof(lbuf) / sizeof(wchar_t), stdin)) { for (p = lbuf; (ch = *p) != L'\0'; ++p, ++cnt) { if (ch == L'\r') { putwc(L'\r', fp); @@ -250,10 +257,13 @@ putwc(L'\n', fp); cnt = 0; } - if (iswprint(ch) || iswspace(ch) || ch == L'\a' || ch == L'\b') { + if (iswprint(ch) || iswspace(ch) || ch == L'\a' || + ch == L'\b') { putwc(ch, fp); } else { - (void)swprintf(codebuf, sizeof(codebuf)/sizeof(wchar_t), L"<0x%X>", ch); + (void)swprintf(codebuf, + sizeof(codebuf) / sizeof(wchar_t), + L"<0x%X>", ch); for (tmp = codebuf; *tmp != L'\0'; ++tmp) { putwc(*tmp, fp); if (++cnt == 79) {