Index: usr.bin/head/head.c =================================================================== --- usr.bin/head/head.c +++ usr.bin/head/head.c @@ -41,14 +41,18 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include +#include #include +#include #include #include #include +#include #include /* @@ -70,6 +74,8 @@ int first, linecnt = -1, eval = 0; off_t bytecnt = -1; char *ep; + cap_rights_t rights; + unsigned long cmd; obsolete(argv); while ((ch = getopt(argc, argv, "n:c:")) != -1) @@ -95,6 +101,22 @@ errx(1, "can't combine line and byte counts"); if (linecnt == -1 ) linecnt = 10; + + cap_rights_init(&rights, CAP_FSTAT, CAP_IOCTL, CAP_WRITE); + if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) + err(1, "unable to limit rights for stdout"); + + /* Required for printf(3) via isatty(3). */ + cmd = TIOCGETA; + if (cap_ioctls_limit(STDOUT_FILENO, &cmd, 1) < 0 && errno != ENOSYS) + err(1, "unable to limit ioctls for stdout"); + + /* + * Cache NLS data, for strerror, for err(3), before entering capability + * mode. + */ + (void)catopen("libc", NL_CAT_LOCALE); + if (*argv) { for (first = 1; *argv; ++argv) { if ((fp = fopen(*argv, "r")) == NULL) { @@ -102,6 +124,15 @@ eval = 1; continue; } + cap_rights_init(&rights, CAP_READ, CAP_FSTAT); + if (cap_rights_limit(fileno(fp), &rights) < 0 && + errno != ENOSYS) + err(1, "unable to limit rights for %s", *argv); + /* Enter capsicum sandbox for the final input file. */ + if (argv[1] == NULL) { + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + } if (argc > 1) { (void)printf("%s==> %s <==\n", first ? "" : "\n", *argv); @@ -113,10 +144,19 @@ head_bytes(fp, bytecnt); (void)fclose(fp); } - } else if (bytecnt == -1) - head(stdin, linecnt); - else - head_bytes(stdin, bytecnt); + } else { + cap_rights_init(&rights, CAP_READ, CAP_FSTAT); + if (cap_rights_limit(fileno(stdin), &rights) < 0 && + errno != ENOSYS) + err(1, "unable to limit rights for stdin"); + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + + if (bytecnt == -1) + head(stdin, linecnt); + else + head_bytes(stdin, bytecnt); + } exit(eval); }