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
This commit is contained in:
parent
223eee088f
commit
6f691f7ee1
@ -43,6 +43,7 @@ static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93";
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/capability.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -220,7 +221,7 @@ main(int argc, char *argv[])
|
|||||||
daemon(1, 0);
|
daemon(1, 0);
|
||||||
#endif
|
#endif
|
||||||
(void) signal(SIGHUP, getboottime);
|
(void) signal(SIGHUP, getboottime);
|
||||||
openlog("rwhod", LOG_PID, LOG_DAEMON);
|
openlog("rwhod", LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||||
sp = getservbyname("who", "udp");
|
sp = getservbyname("who", "udp");
|
||||||
if (sp == NULL) {
|
if (sp == NULL) {
|
||||||
syslog(LOG_ERR, "who/udp: unknown service");
|
syslog(LOG_ERR, "who/udp: unknown service");
|
||||||
@ -342,12 +343,27 @@ receiver_process(void)
|
|||||||
struct sockaddr_in from;
|
struct sockaddr_in from;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char path[64];
|
char path[64];
|
||||||
|
int dirfd;
|
||||||
struct whod wd;
|
struct whod wd;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
int cc, whod;
|
int cc, whod;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
len = sizeof(from);
|
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 (;;) {
|
for (;;) {
|
||||||
cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from,
|
cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from,
|
||||||
&len);
|
&len);
|
||||||
@ -380,11 +396,16 @@ receiver_process(void)
|
|||||||
* Rather than truncating and growing the file each time,
|
* Rather than truncating and growing the file each time,
|
||||||
* use ftruncate if size is less than previous size.
|
* 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) {
|
if (whod < 0) {
|
||||||
syslog(LOG_WARNING, "%s: %m", path);
|
syslog(LOG_WARNING, "%s: %m", path);
|
||||||
continue;
|
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
|
#if ENDIAN != BIG_ENDIAN
|
||||||
{
|
{
|
||||||
struct whoent *we;
|
struct whoent *we;
|
||||||
@ -412,6 +433,7 @@ receiver_process(void)
|
|||||||
ftruncate(whod, cc);
|
ftruncate(whod, cc);
|
||||||
(void) close(whod);
|
(void) close(whod);
|
||||||
}
|
}
|
||||||
|
(void) close(dirfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user