svn commit: r252605 - head/usr.sbin/rwhod

Pawel Jakub Dawidek pjd at FreeBSD.org
Wed Jul 3 21:07:02 UTC 2013


Author: pjd
Date: Wed Jul  3 21:07:02 2013
New Revision: 252605
URL: http://svnweb.freebsd.org/changeset/base/252605

Log:
  Sandbox rwhod(8) receiver process using capability mode and Capsicum
  capabilities.
  
  rwhod(8) receiver can now only receive packages, write to /var/rwho/ directory
  and log to syslog.
  
  Submitted by:	Mariusz Zaborski <oshogbo at FreeBSD.org>
  Sponsored by:	Google Summer of Code 2013
  Reviewed by:	pjd
  MFC after:	1 month

Modified:
  head/usr.sbin/rwhod/rwhod.c

Modified: head/usr.sbin/rwhod/rwhod.c
==============================================================================
--- head/usr.sbin/rwhod/rwhod.c	Wed Jul  3 21:05:35 2013	(r252604)
+++ head/usr.sbin/rwhod/rwhod.c	Wed Jul  3 21:07:02 2013	(r252605)
@@ -43,6 +43,7 @@ static char sccsid[] = "@(#)rwhod.c	8.1 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/capability.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -220,7 +221,7 @@ main(int argc, char *argv[])
 	daemon(1, 0);
 #endif
 	(void) signal(SIGHUP, getboottime);
-	openlog("rwhod", LOG_PID, LOG_DAEMON);
+	openlog("rwhod", LOG_PID | LOG_NDELAY, LOG_DAEMON);
 	sp = getservbyname("who", "udp");
 	if (sp == NULL) {
 		syslog(LOG_ERR, "who/udp: unknown service");
@@ -342,12 +343,27 @@ receiver_process(void)
 	struct sockaddr_in from;
 	struct stat st;
 	char path[64];
+	int dirfd;
 	struct whod wd;
 	socklen_t len;
 	int cc, whod;
 	time_t t;
 
 	len = sizeof(from);
+	dirfd = open(".", O_RDONLY | O_DIRECTORY);
+	if (dirfd < 0) {
+		syslog(LOG_WARNING, "%s: %m", _PATH_RWHODIR);
+		exit(1);
+	}
+	if (cap_rights_limit(dirfd, CAP_CREATE | CAP_WRITE | CAP_FTRUNCATE |
+	    CAP_SEEK | CAP_LOOKUP | CAP_FSTAT) < 0 && errno != ENOSYS) {
+		syslog(LOG_WARNING, "cap_rights_limit: %m");
+		exit(1);
+	}
+	if (cap_enter() < 0 && errno != ENOSYS) {
+		syslog(LOG_ERR, "cap_enter: %m");
+		exit(1);
+	}
 	for (;;) {
 		cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from,
 		    &len);
@@ -380,11 +396,16 @@ receiver_process(void)
 		 * Rather than truncating and growing the file each time,
 		 * use ftruncate if size is less than previous size.
 		 */
-		whod = open(path, O_WRONLY | O_CREAT, 0644);
+		whod = openat(dirfd, path, O_WRONLY | O_CREAT, 0644);
 		if (whod < 0) {
 			syslog(LOG_WARNING, "%s: %m", path);
 			continue;
 		}
+		if (cap_rights_limit(whod, CAP_WRITE | CAP_FTRUNCATE |
+		    CAP_FSTAT) < 0 && errno != ENOSYS) {
+			syslog(LOG_WARNING, "cap_rights_limit: %m");
+			exit(1);
+		}
 #if ENDIAN != BIG_ENDIAN
 		{
 			struct whoent *we;
@@ -412,6 +433,7 @@ receiver_process(void)
 			ftruncate(whod, cc);
 		(void) close(whod);
 	}
+	(void) close(dirfd);
 }
 
 void


More information about the svn-src-head mailing list