Index: usr.bin/ident/ident.c =================================================================== --- usr.bin/ident/ident.c +++ usr.bin/ident/ident.c @@ -28,15 +28,18 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include #include +#include #include #include #include #include +#include #include typedef enum { @@ -201,9 +204,13 @@ int main(int argc, char **argv) { + cap_rights_t rights; + unsigned long cmd; bool quiet = false; - int ch, i; + int ch, i, *fds, fd; int ret = EXIT_SUCCESS; + uint32_t fcntls; + size_t nfds; FILE *fp; while ((ch = getopt(argc, argv, "qV")) != -1) { @@ -223,17 +230,67 @@ argc -= optind; argv += optind; - if (argc == 0) - return (scan(stdin, NULL, quiet)); + /* Required for printf(3)/std input, via isatty(3). */ + cmd = TIOCGETA; - for (i = 0; i < argc; i++) { - fp = fopen(argv[i], "r"); + cap_rights_init(&rights, CAP_FSTAT, CAP_IOCTL, CAP_WRITE); + if ((cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) || + (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) || + (cap_ioctls_limit(STDOUT_FILENO, &cmd, 1) < 0 && errno != ENOSYS) || + (cap_ioctls_limit(STDERR_FILENO, &cmd, 1) < 0 && errno != ENOSYS)) + err(EXIT_FAILURE, "unable to limit ioctls/rights for stdout/stderr"); + + /* Need fcntl for fdopen. */ + fcntls = CAP_FCNTL_GETFL; + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_READ); + if ((cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) || + (cap_ioctls_limit(STDIN_FILENO, &cmd, 1) < 0 && errno != ENOSYS) || + (cap_fcntls_limit(STDIN_FILENO, fcntls) < 0 && errno != ENOSYS)) + err(EXIT_FAILURE, "unable to limit fcntls/ioctls/rights for stdin"); + + if (argc == 0) { + nfds = 1; + fds = malloc(sizeof(*fds)); + if (fds == NULL) + err(EXIT_FAILURE, "unable to allocate fds array"); + fds[0] = STDIN_FILENO; + } else { + nfds = argc; + fds = malloc(sizeof(*fds) * nfds); + if (fds == NULL) + err(EXIT_FAILURE, "unable to allocate fds array"); + + cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_READ); + for (i = 0; i < argc; i++) { + fds[i] = fd = open(argv[i], O_RDONLY); + if (fd < 0) { + warn("%s", argv[i]); + ret = EXIT_FAILURE; + continue; + } + if ((cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) || + (cap_fcntls_limit(fd, fcntls) < 0 && errno != ENOSYS)) + err(EXIT_FAILURE, + "unable to limit fcntls/rights for %s", + argv[i]); + } + } + + /* Enter Capsicum sandbox. */ + if (cap_enter() < 0 && errno != ENOSYS) + err(EXIT_FAILURE, "unable to enter capability mode"); + + for (i = 0; i < (int)nfds; i++) { + if (fds[i] < 0) + continue; + + fp = fdopen(fds[i], "r"); if (fp == NULL) { warn("%s", argv[i]); ret = EXIT_FAILURE; continue; } - if (scan(fp, argv[i], quiet) != EXIT_SUCCESS) + if (scan(fp, argc == 0 ? NULL : argv[i], quiet) != EXIT_SUCCESS) ret = EXIT_FAILURE; fclose(fp); }