diff options
author | pjd <pjd@FreeBSD.org> | 2013-07-03 20:42:10 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2013-07-03 20:42:10 +0000 |
commit | 716e644161e76825d721875595bb765848678cb5 (patch) | |
tree | 86df3e61b28a03e140057076bd3773a8d5227557 | |
parent | 328ede385d1197187e0d5b813d421943c826958c (diff) | |
download | FreeBSD-src-716e644161e76825d721875595bb765848678cb5.zip FreeBSD-src-716e644161e76825d721875595bb765848678cb5.tar.gz |
Sandbox rwho(1) using capability mode and Capsicum capabilities.
rwho(1) gets only read-only access to /var/rwho/ directory.
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.bin/rwho/rwho.c | 26 |
1 files changed, 23 insertions, 3 deletions
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 <oshogbo@FreeBSD.org> * 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 <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/capability.h> #include <sys/param.h> #include <sys/file.h> @@ -49,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include <dirent.h> #include <err.h> +#include <errno.h> #include <langinfo.h> #include <locale.h> #include <stdio.h> @@ -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); |