diff options
author | pjd <pjd@FreeBSD.org> | 2013-07-03 21:07:02 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2013-07-03 21:07:02 +0000 |
commit | 9256efca5e1c834cea4f307b2f9a54f095eb1753 (patch) | |
tree | 0376b5c366c0ea133a23c4a94099a3a18fa2ac2d /usr.sbin/rwhod | |
parent | 22651ea46d39aca94adcd29f086934b568eedff6 (diff) | |
download | FreeBSD-src-9256efca5e1c834cea4f307b2f9a54f095eb1753.zip FreeBSD-src-9256efca5e1c834cea4f307b2f9a54f095eb1753.tar.gz |
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@FreeBSD.org>
Sponsored by: Google Summer of Code 2013
Reviewed by: pjd
MFC after: 1 month
Diffstat (limited to 'usr.sbin/rwhod')
-rw-r--r-- | usr.sbin/rwhod/rwhod.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c index 0b01f3f..26b0500 100644 --- a/usr.sbin/rwhod/rwhod.c +++ b/usr.sbin/rwhod/rwhod.c @@ -43,6 +43,7 @@ static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93"; #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 |