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 <osho...@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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to