Index: usr.bin/head/head.c =================================================================== --- usr.bin/head/head.c +++ usr.bin/head/head.c @@ -41,10 +41,13 @@ #include __FBSDID("$FreeBSD$"); +#include #include +#include #include #include +#include #include #include #include @@ -57,20 +60,41 @@ * Bill Joy UCB August 24, 1977 */ +static const char *abspath(const char *); static void head(FILE *, int); static void head_bytes(FILE *, off_t); static void obsolete(char *[]); static void usage(void); +static char cwd[PATH_MAX]; +static size_t cwdlen; + int main(int argc, char *argv[]) { - int ch; + int ch, rootfd, fd; FILE *fp; int first, linecnt = -1, eval = 0; off_t bytecnt = -1; char *ep; + if (getcwd(cwd, sizeof(cwd)) == NULL) + err(1, "getcwd"); + cwdlen = strlen(cwd); + + rootfd = open("/", O_RDONLY); + if (rootfd < 0) + err(1, "open"); + + /* + * Cache NLS data, for strerror, for err(3), before entering capability + * mode. + */ + caph_cache_catpages(); + if (caph_limit_stream(rootfd, CAPH_READ | CAPH_LOOKUP) < 0 || + caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS)) + err(1, "unable to enter capability mode"); + obsolete(argv); while ((ch = getopt(argc, argv, "n:c:")) != -1) switch(ch) { @@ -95,13 +119,22 @@ errx(1, "can't combine line and byte counts"); if (linecnt == -1 ) linecnt = 10; + if (*argv) { for (first = 1; *argv; ++argv) { - if ((fp = fopen(*argv, "r")) == NULL) { + fd = openat(rootfd, abspath(*argv), O_RDONLY); + if (fd < 0) { warn("%s", *argv); eval = 1; continue; } + if (caph_limit_stream(fd, CAPH_READ) < 0) + err(1, "caph_limit_stream"); + if ((fp = fdopen(fd, "r")) == NULL) { + warn("fdopen"); + eval = 1; + continue; + } if (argc > 1) { (void)printf("%s==> %s <==\n", first ? "" : "\n", *argv); @@ -121,6 +154,20 @@ exit(eval); } +static const char * +abspath(const char *path) +{ + + if (*path == '/') + return (&path[1]); + if (cwdlen == sizeof(cwd) - 1 || + cwdlen + 1 + strlen(path) >= sizeof(cwd)) + err(1, "path too long"); + cwd[cwdlen] = '/'; + strlcpy(&cwd[cwdlen + 1], path, sizeof(cwd) - cwdlen - 1); + return (&cwd[1]); +} + static void head(FILE *fp, int cnt) {