diff options
author | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2013-05-28 21:25:28 +0000 |
---|---|---|
committer | Pawel Jakub Dawidek <pjd@FreeBSD.org> | 2013-05-28 21:25:28 +0000 |
commit | f9b20fc804e13a9c1dcd70817708faf8cff9e29b (patch) | |
tree | 8e2c984a45a4dca0575b697c2cf56f4726dedbf7 /usr.bin | |
parent | 4b0ae5121246c3a840f2e8de140aa271f8ccc292 (diff) | |
download | src-f9b20fc804e13a9c1dcd70817708faf8cff9e29b.tar.gz src-f9b20fc804e13a9c1dcd70817708faf8cff9e29b.zip |
MFp4 @229086:
Make use of Capsicum to protect kdump(1), as it might be used to parse data
from untrusted sources:
- Sandbox kdump(1) using capability mode.
- Limit stdin descriptor (where opened file is moved to) to only
CAP_READ and CAP_FSTAT rights.
- Limit stdout descriptor to only CAP_WRITE, CAP_FSTAT and CAP_IOCTL.
Plus limit allowed ioctls to TIOCGETA only, which is needed for
isatty() to work.
- Limit stderr descriptor to only CAP_WRITE and CAP_FSTAT. In addition
if the -s option is not given, grant CAP_IOCTL right, but allow for
TIOCGWINSZ ioctl only, as we need screen width to dump the data.
- Before entering capability mode call catopen("libc", NL_CAT_LOCALE),
which opens message catalogs and caches data, so that strerror(3)
and strsignal(3) can work in a sandbox.
Sponsored by: The FreeBSD Foundation
Discussed with: rwatson
Notes
Notes:
svn path=/head/; revision=251073
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/kdump/kdump.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index b06b4ab0a4c5..0343a8cabcaf 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -46,6 +46,7 @@ extern int errno; #include <sys/errno.h> #undef _KERNEL #include <sys/param.h> +#include <sys/capability.h> #include <sys/errno.h> #define _KERNEL #include <sys/time.h> @@ -73,10 +74,12 @@ extern int errno; #include <grp.h> #include <inttypes.h> #include <locale.h> +#include <nl_types.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <termios.h> #include <time.h> #include <unistd.h> #include <vis.h> @@ -105,6 +108,7 @@ void ktrstruct(char *, size_t); void ktrcapfail(struct ktr_cap_fail *); void ktrfault(struct ktr_fault *); void ktrfaultend(struct ktr_faultend *); +void limitfd(int fd); void usage(void); void ioctlname(unsigned long, int); @@ -230,6 +234,18 @@ main(int argc, char *argv[]) errx(1, "%s", strerror(ENOMEM)); if (!freopen(tracefile, "r", stdin)) err(1, "%s", tracefile); + + /* + * Cache NLS data before entering capability mode. + * XXXPJD: There should be strerror_init() and strsignal_init() in libc. + */ + (void)catopen("libc", NL_CAT_LOCALE); + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "unable to enter capability mode"); + limitfd(STDIN_FILENO); + limitfd(STDOUT_FILENO); + limitfd(STDERR_FILENO); + TAILQ_INIT(&trace_procs); drop_logged = 0; while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { @@ -331,6 +347,40 @@ main(int argc, char *argv[]) return 0; } +void +limitfd(int fd) +{ + cap_rights_t rights; + unsigned long cmd; + + rights = CAP_FSTAT; + cmd = -1; + + switch (fd) { + case STDIN_FILENO: + rights |= CAP_READ; + break; + case STDOUT_FILENO: + rights |= CAP_IOCTL | CAP_WRITE; + cmd = TIOCGETA; /* required by isatty(3) in printf(3) */ + break; + case STDERR_FILENO: + rights |= CAP_WRITE; + if (!suppressdata) { + rights |= CAP_IOCTL; + cmd = TIOCGWINSZ; + } + break; + default: + abort(); + } + + if (cap_rights_limit(fd, rights) < 0 && errno != ENOSYS) + err(1, "unable to limit rights for descriptor %d", fd); + if (cmd != -1 && cap_ioctls_limit(fd, &cmd, 1) < 0 && errno != ENOSYS) + err(1, "unable to limit ioctls for descriptor %d", fd); +} + int fread_tail(void *buf, int size, int num) { |