From owner-svn-src-all@FreeBSD.ORG Tue May 28 21:25:29 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 83CC7147; Tue, 28 May 2013 21:25:29 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 76621AA2; Tue, 28 May 2013 21:25:29 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r4SLPTn2051503; Tue, 28 May 2013 21:25:29 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r4SLPTSw051502; Tue, 28 May 2013 21:25:29 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <201305282125.r4SLPTSw051502@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Tue, 28 May 2013 21:25:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r251073 - head/usr.bin/kdump X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 May 2013 21:25:29 -0000 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 #undef _KERNEL #include +#include #include #define _KERNEL #include @@ -73,10 +74,12 @@ extern int errno; #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -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) {