From 716e644161e76825d721875595bb765848678cb5 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 3 Jul 2013 20:42:10 +0000 Subject: Sandbox rwho(1) using capability mode and Capsicum capabilities. rwho(1) gets only read-only access to /var/rwho/ directory. Submitted by: Mariusz Zaborski Sponsored by: Google Summer of Code 2013 Reviewed by: pjd MFC after: 1 month --- usr.bin/rwho/rwho.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'usr.bin/rwho') diff --git a/usr.bin/rwho/rwho.c b/usr.bin/rwho/rwho.c index 8ae1b3b..0d4dde9 100644 --- a/usr.bin/rwho/rwho.c +++ b/usr.bin/rwho/rwho.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 1983, 1993 The Regents of the University of California. + * Copyright (c) 2013 Mariusz Zaborski * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,6 +43,7 @@ static char sccsid[] = "@(#)rwho.c 8.1 (Berkeley) 6/6/93"; #include __FBSDID("$FreeBSD$"); +#include #include #include @@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -92,6 +95,8 @@ main(int argc, char *argv[]) struct myutmp *mp; int f, n, i; int d_first; + int dfd; + time_t ct; w = &wd; (void) setlocale(LC_TIME, ""); @@ -113,16 +118,31 @@ main(int argc, char *argv[]) if (argc != 0) usage(); - if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) - err(1, "%s", _PATH_RWHODIR); + if (chdir(_PATH_RWHODIR) < 0) + err(1, "chdir(%s)", _PATH_RWHODIR); + if ((dirp = opendir(".")) == NULL) + err(1, "opendir(%s)", _PATH_RWHODIR); + dfd = dirfd(dirp); mp = myutmp; + if (cap_rights_limit(dfd, CAP_READ | CAP_LOOKUP) < 0 && errno != ENOSYS) + err(1, "cap_rights_limit failed: %s", _PATH_RWHODIR); + /* + * Cache files required for time(3) and localtime(3) before entering + * capability mode. + */ + (void) time(&ct); + (void) localtime(&ct); + if (cap_enter() < 0 && errno != ENOSYS) + err(1, "cap_enter"); (void) time(&now); while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0) continue; - f = open(dp->d_name, O_RDONLY); + f = openat(dfd, dp->d_name, O_RDONLY); if (f < 0) continue; + if (cap_rights_limit(f, CAP_READ) < 0 && errno != ENOSYS) + err(1, "cap_rights_limit failed: %s", dp->d_name); cc = read(f, (char *)&wd, sizeof (struct whod)); if (cc < WHDRSIZE) { (void) close(f); -- cgit v1.1