Index: contrib/elftoolchain/common/_elftc.h =================================================================== --- contrib/elftoolchain/common/_elftc.h +++ contrib/elftoolchain/common/_elftc.h @@ -380,6 +380,7 @@ #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN +#define ELFTC_HAVE_CAPSICUM 0 #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 @@ -432,6 +433,11 @@ #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN +#if __FreeBSD_version > 1001510 +#define ELFTC_HAVE_CAPSICUM 1 +#else +#define ELFTC_HAVE_CAPSICUM 0 +#endif #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 #if __FreeBSD_version <= 900000 @@ -454,6 +460,7 @@ #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN +#define ELFTC_HAVE_CAPSICUM 0 #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 #if __NetBSD_Version__ <= 599002100 @@ -473,6 +480,7 @@ #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN +#define ELFTC_HAVE_CAPSICUM 0 #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 Index: contrib/elftoolchain/strings/strings.c =================================================================== --- contrib/elftoolchain/strings/strings.c +++ contrib/elftoolchain/strings/strings.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,10 @@ #include "_elftc.h" +#if ELFTC_HAVE_CAPSICUM +#include +#endif + ELFTC_VCSID("$Id: strings.c 3446 2016-05-03 01:31:17Z emaste $"); enum return_code { @@ -90,11 +95,15 @@ { NULL, 0, NULL, 0 } }; -long getcharacter(void); -int handle_file(const char *); -int handle_elf(const char *, int); -int handle_binary(const char *, int); -int find_strings(const char *, off_t, off_t); +#if ELFTC_HAVE_CAPSICUM +void capsicum_input(FILE *); +void enter_capsicum(void); +#endif +long getcharacter(FILE *); +int handle_file(const char *, FILE *); +int handle_elf(const char *, FILE *); +int handle_binary(const char *, FILE *); +int find_strings(const char *, FILE *, off_t, off_t); void show_version(void); void usage(void); @@ -105,7 +114,8 @@ int main(int argc, char **argv) { - int ch, rc; + FILE **files; + int ch, i, rc; rc = RETURN_OK; min_len = 0; @@ -194,35 +204,96 @@ if (!min_len) min_len = 4; - if (!*argv) - rc = handle_file("{standard input}"); - else while (*argv) { - rc = handle_file(*argv); - argv++; + if (!*argv) { + rc = handle_file("{standard input}", stdin); + } else { + files = calloc(argc, sizeof(FILE *)); + if (files == NULL) + errx(1, "Unable to allocate memory"); + + for (i = 0; i < argc; i++) { + files[i] = fopen(argv[i], "rb"); + if (files[i] == NULL) + warnx("'%s': %s", argv[i], strerror(errno)); +#if ELFTC_HAVE_CAPSICUM + else + capsicum_input(files[i]); +#endif + } + +#if ELFTC_HAVE_CAPSICUM + enter_capsicum(); +#endif + + for (i = 0; i < argc; i++) { + if (files[i] == NULL || fileno(files[i]) < 0) + rc = RETURN_NOINPUT; + else + rc = handle_file(*argv, files[i]); + argv++; + } + + for (i = 0; i < argc; i++) { + fclose(files[i]); + } + + free(files); } return (rc); } +#if ELFTC_HAVE_CAPSICUM +void +capsicum_input(FILE *file) +{ + cap_rights_t rights; + + /* + * We may mmap the file when we've already opened it, allow this. + */ + if (file != stdin) + cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_SEEK, + CAP_MMAP); + else + cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_SEEK); + + if (cap_rights_limit(fileno(file), &rights) < 0 && errno != ENOSYS) + errx(1, "Unable to limit rights for stdin"); +} + +void +enter_capsicum(void) +{ + cap_rights_t rights; + unsigned long cmd; + + cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT, CAP_IOCTL); + if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) + errx(1, "Unable to limit rights for stdout"); + if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) + errx(1, "Unable to limit rights for stderr"); + + cmd = TIOCGETA; + if (cap_ioctls_limit(STDOUT_FILENO, &cmd, 1) < 0 && errno != ENOSYS) + errx(1, "unable to limit ioctls for stdout"); + + if (cap_enter() != 0) + errx(1, "unable to enter capability mode"); +} +#endif + int -handle_file(const char *name) +handle_file(const char *name, FILE *file) { - int fd, rt; + int rt; if (name == NULL) return (RETURN_NOINPUT); - if (strcmp("{standard input}", name) != 0) { - if (freopen(name, "rb", stdin) == NULL) { - warnx("'%s': %s", name, strerror(errno)); - return (RETURN_NOINPUT); - } - } else { - return (find_strings(name, (off_t)0, (off_t)0)); + if (strcmp("{standard input}", name) == 0) { + return (find_strings(name, file, (off_t)0, (off_t)0)); } - fd = fileno(stdin); - if (fd < 0) - return (RETURN_NOINPUT); - rt = handle_elf(name, fd); + rt = handle_elf(name, file); return (rt); } @@ -231,14 +302,14 @@ * treated as a binary file. This would include text file, core dumps ... */ int -handle_binary(const char *name, int fd) +handle_binary(const char *name, FILE *file) { struct stat buf; memset(&buf, 0, sizeof(struct stat)); - (void) lseek(fd, (off_t)0, SEEK_SET); - if (!fstat(fd, &buf)) - return (find_strings(name, (off_t)0, buf.st_size)); + (void) lseek(fileno(file), (off_t)0, SEEK_SET); + if (!fstat(fileno(file), &buf)) + return (find_strings(name, file, (off_t)0, buf.st_size)); return (RETURN_SOFTWARE); } @@ -249,7 +320,7 @@ * different archs as flat binary files(has to overridden using -a). */ int -handle_elf(const char *name, int fd) +handle_elf(const char *name, FILE *file) { GElf_Ehdr elfhdr; GElf_Shdr shdr; @@ -260,13 +331,13 @@ rc = RETURN_OK; /* If entire file is chosen, treat it as a binary file */ if (entire_file) - return (handle_binary(name, fd)); + return (handle_binary(name, file)); - (void) lseek(fd, (off_t)0, SEEK_SET); - elf = elf_begin(fd, ELF_C_READ, NULL); + (void) lseek(fileno(file), (off_t)0, SEEK_SET); + elf = elf_begin(fileno(file), ELF_C_READ, NULL); if (elf_kind(elf) != ELF_K_ELF) { (void) elf_end(elf); - return (handle_binary(name, fd)); + return (handle_binary(name, file)); } if (gelf_getehdr(elf, &elfhdr) == NULL) { @@ -277,7 +348,7 @@ if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { (void) elf_end(elf); - return (handle_binary(name, fd)); + return (handle_binary(name, file)); } else { scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL) { @@ -285,7 +356,7 @@ continue; if (shdr.sh_type != SHT_NOBITS && (shdr.sh_flags & SHF_ALLOC) != 0) { - rc = find_strings(name, shdr.sh_offset, + rc = find_strings(name, file, shdr.sh_offset, shdr.sh_size); } } @@ -299,7 +370,7 @@ * type requested. */ long -getcharacter(void) +getcharacter(FILE *file) { long rt; int i; @@ -307,8 +378,8 @@ rt = EOF; for(i = 0; i < encoding_size; i++) { - c = getc(stdin); - if (feof(stdin)) + c = getc(file); + if (feof(file)) return (EOF); buf[i] = c; } @@ -342,7 +413,7 @@ * characters of >= min_size(default 4) will be displayed. */ int -find_strings(const char *name, off_t offset, off_t size) +find_strings(const char *name, FILE *file, off_t offset, off_t size) { off_t cur_off, start_off; char *obuf; @@ -355,7 +426,7 @@ return (RETURN_SOFTWARE); } - (void) fseeko(stdin, offset, SEEK_SET); + (void) fseeko(file, offset, SEEK_SET); cur_off = offset; start_off = 0; while(1) { @@ -364,8 +435,8 @@ start_off = cur_off; memset(obuf, 0, min_len+1); for(i = 0; i < min_len; i++) { - c = getcharacter(); - if (c == EOF && feof(stdin)) + c = getcharacter(file); + if (c == EOF && feof(file)) goto _exit1; if (PRINTABLE(c)) { obuf[i] = c; @@ -410,7 +481,7 @@ if ((offset + size) && (cur_off >= offset + size)) break; - c = getcharacter(); + c = getcharacter(file); cur_off += encoding_size; if (encoding == ENCODING_8BIT && (uint8_t)c > 127) {