diff options
author | pjd <pjd@FreeBSD.org> | 2013-07-18 22:11:27 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2013-07-18 22:11:27 +0000 |
commit | f2d723e2cd0338fca77bf3cf31dde28ecb13132e (patch) | |
tree | 0f6de20368efa8f2b5cbc5ec320d452ecd6f2b65 /usr.bin/uniq/uniq.c | |
parent | 1018d5b890d93ddbe1e307fbbfd090c3a883c428 (diff) | |
download | FreeBSD-src-f2d723e2cd0338fca77bf3cf31dde28ecb13132e.zip FreeBSD-src-f2d723e2cd0338fca77bf3cf31dde28ecb13132e.tar.gz |
Close uniq(1) in the capability mode sandbox and limit descriptors using
capability rights.
Diffstat (limited to 'usr.bin/uniq/uniq.c')
-rw-r--r-- | usr.bin/uniq/uniq.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/usr.bin/uniq/uniq.c b/usr.bin/uniq/uniq.c index 1077307..d34b0c0 100644 --- a/usr.bin/uniq/uniq.c +++ b/usr.bin/uniq/uniq.c @@ -44,15 +44,20 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ +#include <sys/capability.h> + #include <ctype.h> #include <err.h> +#include <errno.h> #include <limits.h> #include <locale.h> +#include <nl_types.h> #include <stdint.h> #define _WITH_GETLINE #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <termios.h> #include <unistd.h> #include <wchar.h> #include <wctype.h> @@ -68,6 +73,17 @@ static wchar_t *skip(wchar_t *); static void obsolete(char *[]); static void usage(void); +static void +strerror_init(void) +{ + + /* + * Cache NLS data before entering capability mode. + * XXXPJD: There should be strerror_init() and strsignal_init() in libc. + */ + (void)catopen("libc", NL_CAT_LOCALE); +} + int main (int argc, char *argv[]) { @@ -77,6 +93,7 @@ main (int argc, char *argv[]) size_t prevbuflen, thisbuflen, b1; char *prevline, *thisline, *p; const char *ifn; + cap_rights_t rights; (void) setlocale(LC_ALL, ""); @@ -128,8 +145,34 @@ main (int argc, char *argv[]) ofp = stdout; if (argc > 0 && strcmp(argv[0], "-") != 0) ifp = file(ifn = argv[0], "r"); + if (cap_rights_limit(fileno(ifp), CAP_FSTAT | CAP_READ) < 0 && + errno != ENOSYS) { + err(1, "unable to limit rights for %s", ifn); + } + rights = CAP_FSTAT | CAP_WRITE; if (argc > 1) ofp = file(argv[1], "w"); + else + rights |= CAP_IOCTL; + if (cap_rights_limit(fileno(ofp), rights) < 0 && errno != ENOSYS) { + err(1, "unable to limit rights for %s", + argc > 1 ? argv[1] : "stdout"); + } + if ((rights & CAP_IOCTL) != 0) { + unsigned long cmd; + + cmd = TIOCGETA; /* required by isatty(3) in printf(3) */ + + if (cap_ioctls_limit(fileno(ofp), &cmd, 1) < 0 && + errno != ENOSYS) { + err(1, "unable to limit ioctls for %s", + argc > 1 ? argv[1] : "stdout"); + } + } + + strerror_init(); + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); prevbuflen = thisbuflen = 0; prevline = thisline = NULL; |