Date: Tue, 28 May 2013 21:25:29 +0000 (UTC) From: Pawel Jakub Dawidek <pjd@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r251073 - head/usr.bin/kdump Message-ID: <201305282125.r4SLPTSw051502@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: pjd Date: Tue May 28 21:25:28 2013 New Revision: 251073 URL: http://svnweb.freebsd.org/changeset/base/251073 Log: 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 Modified: head/usr.bin/kdump/kdump.c Modified: head/usr.bin/kdump/kdump.c ============================================================================== --- head/usr.bin/kdump/kdump.c Tue May 28 21:21:46 2013 (r251072) +++ head/usr.bin/kdump/kdump.c Tue May 28 21:25:28 2013 (r251073) @@ -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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305282125.r4SLPTSw051502>