cat: capsicumize it

Reviewed by:	markj, arichardson
Differential Revision:	https://reviews.freebsd.org/D28083
This commit is contained in:
Mariusz Zaborski 2021-01-15 21:22:29 +01:00
parent f64329bcdc
commit aefe30c543
3 changed files with 93 additions and 4 deletions

View File

@ -15,4 +15,11 @@ CFLAGS+=-DBOOTSTRAP_CAT
HAS_TESTS= HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests SUBDIR.${MK_TESTS}+= tests
.if ${MK_CASPER} != "no" && !defined(RESCUE) && !defined(BOOTSTRAPPING)
LIBADD+= casper
LIBADD+= cap_fileargs
LIBADD+= cap_net
CFLAGS+=-DWITH_CASPER
.endif
.include <bsd.prog.mk> .include <bsd.prog.mk>

View File

@ -48,6 +48,7 @@ static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifndef NO_UDOM_SUPPORT #ifndef NO_UDOM_SUPPORT
@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <netdb.h> #include <netdb.h>
#endif #endif
#include <capsicum_helpers.h>
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
@ -68,9 +70,14 @@ __FBSDID("$FreeBSD$");
#include <wchar.h> #include <wchar.h>
#include <wctype.h> #include <wctype.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
#include <casper/cap_net.h>
static int bflag, eflag, lflag, nflag, sflag, tflag, vflag; static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
static int rval; static int rval;
static const char *filename; static const char *filename;
static fileargs_t *fa;
static void usage(void) __dead2; static void usage(void) __dead2;
static void scanfiles(char *argv[], int cooked); static void scanfiles(char *argv[], int cooked);
@ -80,6 +87,8 @@ static void cook_cat(FILE *);
static void raw_cat(int); static void raw_cat(int);
#ifndef NO_UDOM_SUPPORT #ifndef NO_UDOM_SUPPORT
static cap_channel_t *capnet;
static int udom_open(const char *path, int flags); static int udom_open(const char *path, int flags);
#endif #endif
@ -112,6 +121,53 @@ static int udom_open(const char *path, int flags);
#define SUPPORTED_FLAGS "belnstuv" #define SUPPORTED_FLAGS "belnstuv"
#endif #endif
#ifndef NO_UDOM_SUPPORT
static void
init_casper_net(cap_channel_t *casper)
{
cap_net_limit_t *limit;
int familylimit;
capnet = cap_service_open(casper, "system.net");
if (capnet == NULL)
err(EXIT_FAILURE, "unable to create network service");
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR |
CAPNET_CONNECTDNS);
if (limit == NULL)
err(EXIT_FAILURE, "unable to create limits");
familylimit = AF_LOCAL;
cap_net_limit_name2addr_family(limit, &familylimit, 1);
if (cap_net_limit(limit) < 0)
err(EXIT_FAILURE, "unable to apply limits");
}
#endif
static void
init_casper(int argc, char *argv[])
{
cap_channel_t *casper;
cap_rights_t rights;
casper = cap_init();
if (casper == NULL)
err(EXIT_FAILURE, "unable to create Casper");
fa = fileargs_cinit(casper, argc, argv, O_RDONLY, 0,
cap_rights_init(&rights, CAP_READ | CAP_FSTAT | CAP_FCNTL),
FA_OPEN | FA_REALPATH);
if (fa == NULL)
err(EXIT_FAILURE, "unable to create fileargs");
#ifndef NO_UDOM_SUPPORT
init_casper_net(casper);
#endif
cap_close(casper);
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -150,6 +206,7 @@ main(int argc, char *argv[])
usage(); usage();
} }
argv += optind; argv += optind;
argc -= optind;
if (lflag) { if (lflag) {
stdout_lock.l_len = 0; stdout_lock.l_len = 0;
@ -160,6 +217,13 @@ main(int argc, char *argv[])
err(EXIT_FAILURE, "stdout"); err(EXIT_FAILURE, "stdout");
} }
init_casper(argc, argv);
caph_cache_catpages();
if (caph_enter_casper() < 0)
err(EXIT_FAILURE, "capsicum");
if (bflag || eflag || nflag || sflag || tflag || vflag) if (bflag || eflag || nflag || sflag || tflag || vflag)
scanfiles(argv, 1); scanfiles(argv, 1);
else else
@ -196,7 +260,7 @@ scanfiles(char *argv[], int cooked __unused)
fd = STDIN_FILENO; fd = STDIN_FILENO;
} else { } else {
filename = path; filename = path;
fd = open(path, O_RDONLY); fd = fileargs_open(fa, path);
#ifndef NO_UDOM_SUPPORT #ifndef NO_UDOM_SUPPORT
if (fd < 0 && errno == EOPNOTSUPP) if (fd < 0 && errno == EOPNOTSUPP)
fd = udom_open(path, O_RDONLY); fd = udom_open(path, O_RDONLY);
@ -366,20 +430,25 @@ udom_open(const char *path, int flags)
char rpath[PATH_MAX]; char rpath[PATH_MAX];
int fd = -1; int fd = -1;
int error; int error;
cap_rights_t rights;
/* /*
* Construct the unix domain socket address and attempt to connect. * Construct the unix domain socket address and attempt to connect.
*/ */
bzero(&hints, sizeof(hints)); bzero(&hints, sizeof(hints));
hints.ai_family = AF_LOCAL; hints.ai_family = AF_LOCAL;
if (realpath(path, rpath) == NULL)
if (fileargs_realpath(fa, path, rpath) == NULL)
return (-1); return (-1);
error = getaddrinfo(rpath, NULL, &hints, &res0);
error = cap_getaddrinfo(capnet, rpath, NULL, &hints, &res0);
if (error) { if (error) {
warn("%s", gai_strerror(error)); warn("%s", gai_strerror(error));
errno = EINVAL; errno = EINVAL;
return (-1); return (-1);
} }
cap_rights_init(&rights, CAP_CONNECT, CAP_READ, CAP_WRITE,
CAP_SHUTDOWN, CAP_FSTAT, CAP_FCNTL);
for (res = res0; res != NULL; res = res->ai_next) { for (res = res0; res != NULL; res = res->ai_next) {
fd = socket(res->ai_family, res->ai_socktype, fd = socket(res->ai_family, res->ai_socktype,
res->ai_protocol); res->ai_protocol);
@ -387,7 +456,11 @@ udom_open(const char *path, int flags)
freeaddrinfo(res0); freeaddrinfo(res0);
return (-1); return (-1);
} }
error = connect(fd, res->ai_addr, res->ai_addrlen); if (caph_rights_limit(fd, &rights) < 0) {
close(fd);
return (-1);
}
error = cap_connect(capnet, fd, res->ai_addr, res->ai_addrlen);
if (error == 0) if (error == 0)
break; break;
else { else {
@ -403,16 +476,24 @@ udom_open(const char *path, int flags)
if (fd >= 0) { if (fd >= 0) {
switch(flags & O_ACCMODE) { switch(flags & O_ACCMODE) {
case O_RDONLY: case O_RDONLY:
cap_rights_clear(&rights, CAP_WRITE);
if (shutdown(fd, SHUT_WR) == -1) if (shutdown(fd, SHUT_WR) == -1)
warn(NULL); warn(NULL);
break; break;
case O_WRONLY: case O_WRONLY:
cap_rights_clear(&rights, CAP_READ);
if (shutdown(fd, SHUT_RD) == -1) if (shutdown(fd, SHUT_RD) == -1)
warn(NULL); warn(NULL);
break; break;
default: default:
break; break;
} }
cap_rights_clear(&rights, CAP_CONNECT, CAP_SHUTDOWN);
if (caph_rights_limit(fd, &rights) < 0) {
close(fd);
return (-1);
}
} }
return (fd); return (fd);
} }

View File

@ -202,6 +202,7 @@ CLEANFILES+= subr_capability.c
.endif .endif
CASPERINC+= ${SRCTOP}/lib/libcasper/services/cap_fileargs/cap_fileargs.h CASPERINC+= ${SRCTOP}/lib/libcasper/services/cap_fileargs/cap_fileargs.h
CASPERINC+= ${SRCTOP}/lib/libcasper/services/cap_net/cap_net.h
.if empty(SRCS) .if empty(SRCS)
SRCS= dummy.c SRCS= dummy.c