From dfb681901d3575dbf1f177a97604dfa2b37fba70 Mon Sep 17 00:00:00 2001 From: kevans Date: Thu, 2 Jan 2020 23:07:45 +0000 Subject: [PATCH] capsicum_helpers: split stream cap bits out of caph_limit_stream() The goal here is to make it so applications can take the rights one would normally get by calling caph_limit_stream() on a descriptor and build on them as needed. The tentatively planned use-case is an application that takes a socket and hooks it up to std{err,out,in} for a fork()d child. It may be feasible to apply limitations to such descriptors as long as it's a superset of those normally applied to stdio. Reviewed by: markj, oshobo (prior version; sans manpage addition) Differential Revision: https://reviews.freebsd.org/D22993 --- lib/libcapsicum/Makefile | 1 + lib/libcapsicum/capsicum_helpers.3 | 15 +++++++++++-- lib/libcapsicum/capsicum_helpers.h | 36 +++++++++++++++++++----------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/libcapsicum/Makefile b/lib/libcapsicum/Makefile index b30bb5990878..c3c6330cbcbd 100644 --- a/lib/libcapsicum/Makefile +++ b/lib/libcapsicum/Makefile @@ -6,6 +6,7 @@ MAN+= capsicum_helpers.3 MLINKS+=capsicum_helpers.3 caph_enter.3 MLINKS+=capsicum_helpers.3 caph_enter_casper.3 +MLINKS+=capsicum_helpers.3 caph_stream_rights.3 MLINKS+=capsicum_helpers.3 caph_rights_limit.3 MLINKS+=capsicum_helpers.3 caph_fcntls_limit.3 MLINKS+=capsicum_helpers.3 caph_ioctls_limit.3 diff --git a/lib/libcapsicum/capsicum_helpers.3 b/lib/libcapsicum/capsicum_helpers.3 index e3d3cd7e9abb..1c43fdffd882 100644 --- a/lib/libcapsicum/capsicum_helpers.3 +++ b/lib/libcapsicum/capsicum_helpers.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 21, 2019 +.Dd January 2, 2020 .Dt CAPSICUM_HELPERS 3 .Os .Sh NAME @@ -33,6 +33,7 @@ .Nm caph_limit_stderr , .Nm caph_limit_stdout , .Nm caph_limit_stdio , +.Nm caph_stream_rights , .Nm caph_cache_tzdata , .Nm caph_cache_catpages , .Nm caph_enter , @@ -50,7 +51,7 @@ .Ft int .Fn caph_enter_casper "void" .Ft int -.Fn caph_rights_limit "int fd" "const cap_righst_t *rights" +.Fn caph_rights_limit "int fd" "const cap_rights_t *rights" .Ft int .Fn caph_ioctls_limit "int fd" "const unsigned long *cmds" "size_t ncmds" .Ft int @@ -66,6 +67,8 @@ .Ft int .Fn caph_limit_stdio "void" .Ft void +.Fn caph_stream_rights "cap_rights_t *" "int flags" +.Ft void .Fn caph_cache_tzdata "void" .Ft void .Fn caph_cache_catpages "void" @@ -129,6 +132,14 @@ function. .Fn caph_limit_stdio limits stdin, stderr and stdout. .Pp +.Nm caph_stream_rights +may be used to initialize +.Fa rights +with the same rights that a stream would be limited to, as if +.Fn caph_limit_stream +had been invoked using the same +.Fa flags . +.Pp .Fn caph_cache_tzdata precaches all timezone data needed to use .Li libc diff --git a/lib/libcapsicum/capsicum_helpers.h b/lib/libcapsicum/capsicum_helpers.h index d1c46e74f388..99ece1abfbcd 100644 --- a/lib/libcapsicum/capsicum_helpers.h +++ b/lib/libcapsicum/capsicum_helpers.h @@ -48,32 +48,42 @@ __BEGIN_DECLS +static const unsigned long caph_stream_cmds[] = + { TIOCGETA, TIOCGWINSZ, FIODTYPE }; +static const uint32_t caph_stream_fcntls = CAP_FCNTL_GETFL; + +static __inline void +caph_stream_rights(cap_rights_t *rights, int flags) +{ + + cap_rights_init(rights, CAP_EVENT, CAP_FCNTL, CAP_FSTAT, + CAP_IOCTL, CAP_SEEK); + + if ((flags & CAPH_READ) != 0) + cap_rights_set(rights, CAP_READ); + if ((flags & CAPH_WRITE) != 0) + cap_rights_set(rights, CAP_WRITE); + if ((flags & CAPH_LOOKUP) != 0) + cap_rights_set(rights, CAP_LOOKUP); +} + static __inline int caph_limit_stream(int fd, int flags) { cap_rights_t rights; - unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ, FIODTYPE }; - - cap_rights_init(&rights, CAP_EVENT, CAP_FCNTL, CAP_FSTAT, - CAP_IOCTL, CAP_SEEK); - - if ((flags & CAPH_READ) != 0) - cap_rights_set(&rights, CAP_READ); - if ((flags & CAPH_WRITE) != 0) - cap_rights_set(&rights, CAP_WRITE); - if ((flags & CAPH_LOOKUP) != 0) - cap_rights_set(&rights, CAP_LOOKUP); + caph_stream_rights(&rights, flags); if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { if (errno == EBADF && (flags & CAPH_IGNORE_EBADF) != 0) return (0); return (-1); } - if (cap_ioctls_limit(fd, cmds, nitems(cmds)) < 0 && errno != ENOSYS) + if (cap_ioctls_limit(fd, caph_stream_cmds, + nitems(caph_stream_cmds)) < 0 && errno != ENOSYS) return (-1); - if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) + if (cap_fcntls_limit(fd, caph_stream_fcntls) < 0 && errno != ENOSYS) return (-1); return (0);