svn commit: r251073 - head/usr.bin/kdump

Pawel Jakub Dawidek pjd at FreeBSD.org
Tue May 28 21:25:29 UTC 2013


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)
 {


More information about the svn-src-all mailing list