summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2013-07-03 21:07:02 +0000
committerpjd <pjd@FreeBSD.org>2013-07-03 21:07:02 +0000
commit9256efca5e1c834cea4f307b2f9a54f095eb1753 (patch)
tree0376b5c366c0ea133a23c4a94099a3a18fa2ac2d
parent22651ea46d39aca94adcd29f086934b568eedff6 (diff)
downloadFreeBSD-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
-rw-r--r--usr.sbin/rwhod/rwhod.c26
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
OpenPOWER on IntegriCloud