diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c index 1f3a181a91cb..b4fedb402b43 100644 --- a/sys/kern/subr_capability.c +++ b/sys/kern/subr_capability.c @@ -1,426 +1,381 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2013 FreeBSD Foundation * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include /* * Note that this file is compiled into the kernel and into libc. */ #include #include #ifdef _KERNEL #include #include #include #else /* !_KERNEL */ #include #include #include #include #include #endif #ifdef _KERNEL #define assert(exp) KASSERT((exp), ("%s:%u", __func__, __LINE__)) -__read_mostly cap_rights_t cap_accept_rights; -__read_mostly cap_rights_t cap_bind_rights; -__read_mostly cap_rights_t cap_chflags_rights; -__read_mostly cap_rights_t cap_connect_rights; -__read_mostly cap_rights_t cap_event_rights; -__read_mostly cap_rights_t cap_fchdir_rights; -__read_mostly cap_rights_t cap_fchflags_rights; -__read_mostly cap_rights_t cap_fchmod_rights; -__read_mostly cap_rights_t cap_fchown_rights; -__read_mostly cap_rights_t cap_fcntl_rights; -__read_mostly cap_rights_t cap_fexecve_rights; -__read_mostly cap_rights_t cap_flock_rights; -__read_mostly cap_rights_t cap_fpathconf_rights; -__read_mostly cap_rights_t cap_fstat_rights; -__read_mostly cap_rights_t cap_fstatfs_rights; -__read_mostly cap_rights_t cap_fsync_rights; -__read_mostly cap_rights_t cap_ftruncate_rights; -__read_mostly cap_rights_t cap_futimes_rights; -__read_mostly cap_rights_t cap_getpeername_rights; -__read_mostly cap_rights_t cap_getsockopt_rights; -__read_mostly cap_rights_t cap_getsockname_rights; -__read_mostly cap_rights_t cap_ioctl_rights; -__read_mostly cap_rights_t cap_listen_rights; -__read_mostly cap_rights_t cap_linkat_source_rights; -__read_mostly cap_rights_t cap_linkat_target_rights; -__read_mostly cap_rights_t cap_mmap_rights; -__read_mostly cap_rights_t cap_mkdirat_rights; -__read_mostly cap_rights_t cap_mkfifoat_rights; -__read_mostly cap_rights_t cap_mknodat_rights; -__read_mostly cap_rights_t cap_pdgetpid_rights; -__read_mostly cap_rights_t cap_pdkill_rights; -__read_mostly cap_rights_t cap_pread_rights; -__read_mostly cap_rights_t cap_pwrite_rights; -__read_mostly cap_rights_t cap_read_rights; -__read_mostly cap_rights_t cap_recv_rights; -__read_mostly cap_rights_t cap_renameat_source_rights; -__read_mostly cap_rights_t cap_renameat_target_rights; -__read_mostly cap_rights_t cap_seek_rights; -__read_mostly cap_rights_t cap_send_rights; -__read_mostly cap_rights_t cap_send_connect_rights; -__read_mostly cap_rights_t cap_setsockopt_rights; -__read_mostly cap_rights_t cap_shutdown_rights; -__read_mostly cap_rights_t cap_symlinkat_rights; -__read_mostly cap_rights_t cap_unlinkat_rights; -__read_mostly cap_rights_t cap_write_rights; -__read_mostly cap_rights_t cap_no_rights; - -static void -cap_rights_sysinit(void *arg) -{ - cap_rights_init_one(&cap_accept_rights, CAP_ACCEPT); - cap_rights_init_one(&cap_bind_rights, CAP_BIND); - cap_rights_init_one(&cap_connect_rights, CAP_CONNECT); - cap_rights_init_one(&cap_event_rights, CAP_EVENT); - cap_rights_init_one(&cap_fchdir_rights, CAP_FCHDIR); - cap_rights_init_one(&cap_fchflags_rights, CAP_FCHFLAGS); - cap_rights_init_one(&cap_fchmod_rights, CAP_FCHMOD); - cap_rights_init_one(&cap_fchown_rights, CAP_FCHOWN); - cap_rights_init_one(&cap_fcntl_rights, CAP_FCNTL); - cap_rights_init_one(&cap_fexecve_rights, CAP_FEXECVE); - cap_rights_init_one(&cap_flock_rights, CAP_FLOCK); - cap_rights_init_one(&cap_fpathconf_rights, CAP_FPATHCONF); - cap_rights_init_one(&cap_fstat_rights, CAP_FSTAT); - cap_rights_init_one(&cap_fstatfs_rights, CAP_FSTATFS); - cap_rights_init_one(&cap_fsync_rights, CAP_FSYNC); - cap_rights_init_one(&cap_ftruncate_rights, CAP_FTRUNCATE); - cap_rights_init_one(&cap_futimes_rights, CAP_FUTIMES); - cap_rights_init_one(&cap_getpeername_rights, CAP_GETPEERNAME); - cap_rights_init_one(&cap_getsockname_rights, CAP_GETSOCKNAME); - cap_rights_init_one(&cap_getsockopt_rights, CAP_GETSOCKOPT); - cap_rights_init_one(&cap_ioctl_rights, CAP_IOCTL); - cap_rights_init_one(&cap_linkat_source_rights, CAP_LINKAT_SOURCE); - cap_rights_init_one(&cap_linkat_target_rights, CAP_LINKAT_TARGET); - cap_rights_init_one(&cap_listen_rights, CAP_LISTEN); - cap_rights_init_one(&cap_mkdirat_rights, CAP_MKDIRAT); - cap_rights_init_one(&cap_mkfifoat_rights, CAP_MKFIFOAT); - cap_rights_init_one(&cap_mknodat_rights, CAP_MKNODAT); - cap_rights_init_one(&cap_mmap_rights, CAP_MMAP); - cap_rights_init_one(&cap_pdgetpid_rights, CAP_PDGETPID); - cap_rights_init_one(&cap_pdkill_rights, CAP_PDKILL); - cap_rights_init_one(&cap_pread_rights, CAP_PREAD); - cap_rights_init_one(&cap_pwrite_rights, CAP_PWRITE); - cap_rights_init_one(&cap_read_rights, CAP_READ); - cap_rights_init_one(&cap_recv_rights, CAP_RECV); - cap_rights_init_one(&cap_renameat_source_rights, CAP_RENAMEAT_SOURCE); - cap_rights_init_one(&cap_renameat_target_rights, CAP_RENAMEAT_TARGET); - cap_rights_init_one(&cap_seek_rights, CAP_SEEK); - cap_rights_init_one(&cap_send_rights, CAP_SEND); - cap_rights_init(&cap_send_connect_rights, CAP_SEND, CAP_CONNECT); - cap_rights_init_one(&cap_setsockopt_rights, CAP_SETSOCKOPT); - cap_rights_init_one(&cap_shutdown_rights, CAP_SHUTDOWN); - cap_rights_init_one(&cap_symlinkat_rights, CAP_SYMLINKAT); - cap_rights_init_one(&cap_unlinkat_rights, CAP_UNLINKAT); - cap_rights_init_one(&cap_write_rights, CAP_WRITE); - cap_rights_init(&cap_no_rights); -} -SYSINIT(cap_rights_sysinit, SI_SUB_COPYRIGHT, SI_ORDER_ANY, cap_rights_sysinit, - NULL); - +const cap_rights_t cap_accept_rights = CAP_RIGHTS_INITIALIZER(CAP_ACCEPT); +const cap_rights_t cap_bind_rights = CAP_RIGHTS_INITIALIZER(CAP_BIND); +const cap_rights_t cap_connect_rights = CAP_RIGHTS_INITIALIZER(CAP_CONNECT); +const cap_rights_t cap_event_rights = CAP_RIGHTS_INITIALIZER(CAP_EVENT); +const cap_rights_t cap_fchdir_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHDIR); +const cap_rights_t cap_fchflags_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHFLAGS); +const cap_rights_t cap_fchmod_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHMOD); +const cap_rights_t cap_fchown_rights = CAP_RIGHTS_INITIALIZER(CAP_FCHOWN); +const cap_rights_t cap_fcntl_rights = CAP_RIGHTS_INITIALIZER(CAP_FCNTL); +const cap_rights_t cap_fexecve_rights = CAP_RIGHTS_INITIALIZER(CAP_FEXECVE); +const cap_rights_t cap_flock_rights = CAP_RIGHTS_INITIALIZER(CAP_FLOCK); +const cap_rights_t cap_fpathconf_rights = CAP_RIGHTS_INITIALIZER(CAP_FPATHCONF); +const cap_rights_t cap_fstat_rights = CAP_RIGHTS_INITIALIZER(CAP_FSTAT); +const cap_rights_t cap_fstatfs_rights = CAP_RIGHTS_INITIALIZER(CAP_FSTATFS); +const cap_rights_t cap_fsync_rights = CAP_RIGHTS_INITIALIZER(CAP_FSYNC); +const cap_rights_t cap_ftruncate_rights = CAP_RIGHTS_INITIALIZER(CAP_FTRUNCATE); +const cap_rights_t cap_futimes_rights = CAP_RIGHTS_INITIALIZER(CAP_FUTIMES); +const cap_rights_t cap_getpeername_rights = + CAP_RIGHTS_INITIALIZER(CAP_GETPEERNAME); +const cap_rights_t cap_getsockopt_rights = + CAP_RIGHTS_INITIALIZER(CAP_GETSOCKOPT); +const cap_rights_t cap_getsockname_rights = + CAP_RIGHTS_INITIALIZER(CAP_GETSOCKNAME); +const cap_rights_t cap_ioctl_rights = CAP_RIGHTS_INITIALIZER(CAP_IOCTL); +const cap_rights_t cap_listen_rights = CAP_RIGHTS_INITIALIZER(CAP_LISTEN); +const cap_rights_t cap_linkat_source_rights = + CAP_RIGHTS_INITIALIZER(CAP_LINKAT_SOURCE); +const cap_rights_t cap_linkat_target_rights = + CAP_RIGHTS_INITIALIZER(CAP_LINKAT_TARGET); +const cap_rights_t cap_mmap_rights = CAP_RIGHTS_INITIALIZER(CAP_MMAP); +const cap_rights_t cap_mkdirat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKDIRAT); +const cap_rights_t cap_mkfifoat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKFIFOAT); +const cap_rights_t cap_mknodat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKNODAT); +const cap_rights_t cap_pdgetpid_rights = CAP_RIGHTS_INITIALIZER(CAP_PDGETPID); +const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL); +const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD); +const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE); +const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ); +const cap_rights_t cap_recv_rights = CAP_RIGHTS_INITIALIZER(CAP_RECV); +const cap_rights_t cap_renameat_source_rights = + CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_SOURCE); +const cap_rights_t cap_renameat_target_rights = + CAP_RIGHTS_INITIALIZER(CAP_RENAMEAT_TARGET); +const cap_rights_t cap_seek_rights = CAP_RIGHTS_INITIALIZER(CAP_SEEK); +const cap_rights_t cap_send_rights = CAP_RIGHTS_INITIALIZER(CAP_SEND); +const cap_rights_t cap_send_connect_rights = + CAP_RIGHTS_INITIALIZER2(CAP_SEND, CAP_CONNECT); +const cap_rights_t cap_setsockopt_rights = + CAP_RIGHTS_INITIALIZER(CAP_SETSOCKOPT); +const cap_rights_t cap_shutdown_rights = CAP_RIGHTS_INITIALIZER(CAP_SHUTDOWN); +const cap_rights_t cap_symlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_SYMLINKAT); +const cap_rights_t cap_unlinkat_rights = CAP_RIGHTS_INITIALIZER(CAP_UNLINKAT); +const cap_rights_t cap_write_rights = CAP_RIGHTS_INITIALIZER(CAP_WRITE); +const cap_rights_t cap_no_rights = CAP_RIGHTS_INITIALIZER(0ULL); #endif #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2) #define CAPARSIZE_MAX (CAP_RIGHTS_VERSION + 2) static __inline int right_to_index(uint64_t right) { static const int bit2idx[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; int idx; idx = CAPIDXBIT(right); assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0])); return (bit2idx[idx]); } static void cap_rights_vset(cap_rights_t *rights, va_list ap) { uint64_t right; int i, n __unused; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); n = CAPARSIZE(rights); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; assert(CAPRVER(right) == 0); i = right_to_index(right); assert(i >= 0); assert(i < n); assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); rights->cr_rights[i] |= right; assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); } } static void cap_rights_vclear(cap_rights_t *rights, va_list ap) { uint64_t right; int i, n __unused; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); n = CAPARSIZE(rights); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; assert(CAPRVER(right) == 0); i = right_to_index(right); assert(i >= 0); assert(i < n); assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL); assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); } } static bool cap_rights_is_vset(const cap_rights_t *rights, va_list ap) { uint64_t right; int i, n __unused; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); n = CAPARSIZE(rights); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; assert(CAPRVER(right) == 0); i = right_to_index(right); assert(i >= 0); assert(i < n); assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right)); if ((rights->cr_rights[i] & right) != right) return (false); } return (true); } cap_rights_t * __cap_rights_init(int version, cap_rights_t *rights, ...) { unsigned int n __unused; va_list ap; assert(version == CAP_RIGHTS_VERSION_00); n = version + 2; assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); CAP_NONE(rights); va_start(ap, rights); cap_rights_vset(rights, ap); va_end(ap); return (rights); } cap_rights_t * __cap_rights_set(cap_rights_t *rights, ...) { va_list ap; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); va_start(ap, rights); cap_rights_vset(rights, ap); va_end(ap); return (rights); } cap_rights_t * __cap_rights_clear(cap_rights_t *rights, ...) { va_list ap; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); va_start(ap, rights); cap_rights_vclear(rights, ap); va_end(ap); return (rights); } bool __cap_rights_is_set(const cap_rights_t *rights, ...) { va_list ap; bool ret; assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); va_start(ap, rights); ret = cap_rights_is_vset(rights, ap); va_end(ap); return (ret); } bool cap_rights_is_empty(const cap_rights_t *rights) { #ifndef _KERNEL cap_rights_t cap_no_rights; cap_rights_init(&cap_no_rights); #endif assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); assert(CAPVER(&cap_no_rights) == CAP_RIGHTS_VERSION_00); for (int i = 0; i < CAPARSIZE(rights); i++) { if (rights->cr_rights[i] != cap_no_rights.cr_rights[i]) return (false); } return (true); } bool cap_rights_is_valid(const cap_rights_t *rights) { cap_rights_t allrights; int i, j; if (CAPVER(rights) != CAP_RIGHTS_VERSION_00) return (false); if (CAPARSIZE(rights) < CAPARSIZE_MIN || CAPARSIZE(rights) > CAPARSIZE_MAX) { return (false); } CAP_ALL(&allrights); if (!cap_rights_contains(&allrights, rights)) return (false); for (i = 0; i < CAPARSIZE(rights); i++) { j = right_to_index(rights->cr_rights[i]); if (i != j) return (false); if (i > 0) { if (CAPRVER(rights->cr_rights[i]) != 0) return (false); } } return (true); } cap_rights_t * cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src) { unsigned int i, n; assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); assert(CAPVER(dst) == CAPVER(src)); assert(cap_rights_is_valid(src)); assert(cap_rights_is_valid(dst)); n = CAPARSIZE(dst); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (i = 0; i < n; i++) dst->cr_rights[i] |= src->cr_rights[i]; assert(cap_rights_is_valid(src)); assert(cap_rights_is_valid(dst)); return (dst); } cap_rights_t * cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src) { unsigned int i, n; assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00); assert(CAPVER(src) == CAP_RIGHTS_VERSION_00); assert(CAPVER(dst) == CAPVER(src)); assert(cap_rights_is_valid(src)); assert(cap_rights_is_valid(dst)); n = CAPARSIZE(dst); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (i = 0; i < n; i++) { dst->cr_rights[i] &= ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL); } assert(cap_rights_is_valid(src)); assert(cap_rights_is_valid(dst)); return (dst); } #ifndef _KERNEL bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) { unsigned int i, n; assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); assert(CAPVER(big) == CAPVER(little)); n = CAPARSIZE(big); assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); for (i = 0; i < n; i++) { if ((big->cr_rights[i] & little->cr_rights[i]) != little->cr_rights[i]) { return (false); } } return (true); } #endif diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h index 32ae05172e24..b2fb2898437a 100644 --- a/sys/sys/caprights.h +++ b/sys/sys/caprights.h @@ -1,108 +1,108 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2013 FreeBSD Foundation * * This software was developed by Pawel Jakub Dawidek under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _SYS_CAPRIGHTS_H_ #define _SYS_CAPRIGHTS_H_ /* * The top two bits in the first element of the cr_rights[] array contain * total number of elements in the array - 2. This means if those two bits are * equal to 0, we have 2 array elements. * The top two bits in all remaining array elements should be 0. * The next five bits contain array index. Only one bit is used and bit position * in this five-bits range defines array index. This means there can be at most * five array elements. */ #define CAP_RIGHTS_VERSION_00 0 /* #define CAP_RIGHTS_VERSION_01 1 #define CAP_RIGHTS_VERSION_02 2 #define CAP_RIGHTS_VERSION_03 3 */ #define CAP_RIGHTS_VERSION CAP_RIGHTS_VERSION_00 struct cap_rights { uint64_t cr_rights[CAP_RIGHTS_VERSION + 2]; }; #ifndef _CAP_RIGHTS_T_DECLARED #define _CAP_RIGHTS_T_DECLARED typedef struct cap_rights cap_rights_t; #endif #ifdef _KERNEL -extern cap_rights_t cap_accept_rights; -extern cap_rights_t cap_bind_rights; -extern cap_rights_t cap_connect_rights; -extern cap_rights_t cap_event_rights; -extern cap_rights_t cap_fchdir_rights; -extern cap_rights_t cap_fchflags_rights; -extern cap_rights_t cap_fchmod_rights; -extern cap_rights_t cap_fchown_rights; -extern cap_rights_t cap_fcntl_rights; -extern cap_rights_t cap_fexecve_rights; -extern cap_rights_t cap_flock_rights; -extern cap_rights_t cap_fpathconf_rights; -extern cap_rights_t cap_fstat_rights; -extern cap_rights_t cap_fstatfs_rights; -extern cap_rights_t cap_fsync_rights; -extern cap_rights_t cap_ftruncate_rights; -extern cap_rights_t cap_futimes_rights; -extern cap_rights_t cap_getpeername_rights; -extern cap_rights_t cap_getsockopt_rights; -extern cap_rights_t cap_getsockname_rights; -extern cap_rights_t cap_ioctl_rights; -extern cap_rights_t cap_linkat_source_rights; -extern cap_rights_t cap_linkat_target_rights; -extern cap_rights_t cap_listen_rights; -extern cap_rights_t cap_mkdirat_rights; -extern cap_rights_t cap_mkfifoat_rights; -extern cap_rights_t cap_mknodat_rights; -extern cap_rights_t cap_mmap_rights; -extern cap_rights_t cap_no_rights; -extern cap_rights_t cap_pdgetpid_rights; -extern cap_rights_t cap_pdkill_rights; -extern cap_rights_t cap_pread_rights; -extern cap_rights_t cap_pwrite_rights; -extern cap_rights_t cap_read_rights; -extern cap_rights_t cap_recv_rights; -extern cap_rights_t cap_renameat_source_rights; -extern cap_rights_t cap_renameat_target_rights; -extern cap_rights_t cap_seek_rights; -extern cap_rights_t cap_send_rights; -extern cap_rights_t cap_send_connect_rights; -extern cap_rights_t cap_setsockopt_rights; -extern cap_rights_t cap_shutdown_rights; -extern cap_rights_t cap_symlinkat_rights; -extern cap_rights_t cap_unlinkat_rights; -extern cap_rights_t cap_write_rights; +extern const cap_rights_t cap_accept_rights; +extern const cap_rights_t cap_bind_rights; +extern const cap_rights_t cap_connect_rights; +extern const cap_rights_t cap_event_rights; +extern const cap_rights_t cap_fchdir_rights; +extern const cap_rights_t cap_fchflags_rights; +extern const cap_rights_t cap_fchmod_rights; +extern const cap_rights_t cap_fchown_rights; +extern const cap_rights_t cap_fcntl_rights; +extern const cap_rights_t cap_fexecve_rights; +extern const cap_rights_t cap_flock_rights; +extern const cap_rights_t cap_fpathconf_rights; +extern const cap_rights_t cap_fstat_rights; +extern const cap_rights_t cap_fstatfs_rights; +extern const cap_rights_t cap_fsync_rights; +extern const cap_rights_t cap_ftruncate_rights; +extern const cap_rights_t cap_futimes_rights; +extern const cap_rights_t cap_getpeername_rights; +extern const cap_rights_t cap_getsockopt_rights; +extern const cap_rights_t cap_getsockname_rights; +extern const cap_rights_t cap_ioctl_rights; +extern const cap_rights_t cap_linkat_source_rights; +extern const cap_rights_t cap_linkat_target_rights; +extern const cap_rights_t cap_listen_rights; +extern const cap_rights_t cap_mkdirat_rights; +extern const cap_rights_t cap_mkfifoat_rights; +extern const cap_rights_t cap_mknodat_rights; +extern const cap_rights_t cap_mmap_rights; +extern const cap_rights_t cap_no_rights; +extern const cap_rights_t cap_pdgetpid_rights; +extern const cap_rights_t cap_pdkill_rights; +extern const cap_rights_t cap_pread_rights; +extern const cap_rights_t cap_pwrite_rights; +extern const cap_rights_t cap_read_rights; +extern const cap_rights_t cap_recv_rights; +extern const cap_rights_t cap_renameat_source_rights; +extern const cap_rights_t cap_renameat_target_rights; +extern const cap_rights_t cap_seek_rights; +extern const cap_rights_t cap_send_rights; +extern const cap_rights_t cap_send_connect_rights; +extern const cap_rights_t cap_setsockopt_rights; +extern const cap_rights_t cap_shutdown_rights; +extern const cap_rights_t cap_symlinkat_rights; +extern const cap_rights_t cap_unlinkat_rights; +extern const cap_rights_t cap_write_rights; #endif #endif /* !_SYS_CAPRIGHTS_H_ */ diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h index 405a7af419bf..9dd34cff943a 100644 --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -1,518 +1,536 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2008-2010, 2015 Robert N. M. Watson * Copyright (c) 2012 FreeBSD Foundation * All rights reserved. * * This software was developed at the University of Cambridge Computer * Laboratory with support from a grant from Google, Inc. * * Portions of this software were developed by Pawel Jakub Dawidek under * sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Definitions for FreeBSD capabilities facility. */ #ifndef _SYS_CAPSICUM_H_ #define _SYS_CAPSICUM_H_ #include #include #include #include #include #ifndef _KERNEL #include #endif #define CAPRIGHT(idx, bit) ((1ULL << (57 + (idx))) | (bit)) /* * Possible rights on capabilities. * * Notes: * Some system calls don't require a capability in order to perform an * operation on an fd. These include: close, dup, dup2. * * sendfile is authorized using CAP_READ on the file and CAP_WRITE on the * socket. * * mmap() and aio*() system calls will need special attention as they may * involve reads or writes depending a great deal on context. */ /* INDEX 0 */ /* * General file I/O. */ /* Allows for openat(O_RDONLY), read(2), readv(2). */ #define CAP_READ CAPRIGHT(0, 0x0000000000000001ULL) /* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */ #define CAP_WRITE CAPRIGHT(0, 0x0000000000000002ULL) /* Allows for lseek(fd, 0, SEEK_CUR). */ #define CAP_SEEK_TELL CAPRIGHT(0, 0x0000000000000004ULL) /* Allows for lseek(2). */ #define CAP_SEEK (CAP_SEEK_TELL | 0x0000000000000008ULL) /* Allows for aio_read(2), pread(2), preadv(2). */ #define CAP_PREAD (CAP_SEEK | CAP_READ) /* * Allows for aio_write(2), openat(O_WRONLY) (without O_APPEND), pwrite(2), * pwritev(2). */ #define CAP_PWRITE (CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_NONE). */ #define CAP_MMAP CAPRIGHT(0, 0x0000000000000010ULL) /* Allows for mmap(PROT_READ). */ #define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ) /* Allows for mmap(PROT_WRITE). */ #define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE) /* Allows for mmap(PROT_EXEC). */ #define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000020ULL) /* Allows for mmap(PROT_READ | PROT_WRITE). */ #define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W) /* Allows for mmap(PROT_READ | PROT_EXEC). */ #define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X) /* Allows for mmap(PROT_WRITE | PROT_EXEC). */ #define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X) /* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */ #define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X) /* Allows for openat(O_CREAT). */ #define CAP_CREATE CAPRIGHT(0, 0x0000000000000040ULL) /* Allows for openat(O_EXEC) and fexecve(2) in turn. */ #define CAP_FEXECVE CAPRIGHT(0, 0x0000000000000080ULL) /* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2), aio_fsync(2). */ #define CAP_FSYNC CAPRIGHT(0, 0x0000000000000100ULL) /* Allows for openat(O_TRUNC), ftruncate(2). */ #define CAP_FTRUNCATE CAPRIGHT(0, 0x0000000000000200ULL) /* Lookups - used to constrain *at() calls. */ #define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL) /* VFS methods. */ /* Allows for fchdir(2). */ #define CAP_FCHDIR CAPRIGHT(0, 0x0000000000000800ULL) /* Allows for fchflags(2). */ #define CAP_FCHFLAGS CAPRIGHT(0, 0x0000000000001000ULL) /* Allows for fchflags(2) and chflagsat(2). */ #define CAP_CHFLAGSAT (CAP_FCHFLAGS | CAP_LOOKUP) /* Allows for fchmod(2). */ #define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL) /* Allows for fchmod(2) and fchmodat(2). */ #define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP) /* Allows for fchown(2). */ #define CAP_FCHOWN CAPRIGHT(0, 0x0000000000004000ULL) /* Allows for fchown(2) and fchownat(2). */ #define CAP_FCHOWNAT (CAP_FCHOWN | CAP_LOOKUP) /* Allows for fcntl(2). */ #define CAP_FCNTL CAPRIGHT(0, 0x0000000000008000ULL) /* * Allows for flock(2), openat(O_SHLOCK), openat(O_EXLOCK), * fcntl(F_SETLK_REMOTE), fcntl(F_SETLKW), fcntl(F_SETLK), fcntl(F_GETLK). */ #define CAP_FLOCK CAPRIGHT(0, 0x0000000000010000ULL) /* Allows for fpathconf(2). */ #define CAP_FPATHCONF CAPRIGHT(0, 0x0000000000020000ULL) /* Allows for UFS background-fsck operations. */ #define CAP_FSCK CAPRIGHT(0, 0x0000000000040000ULL) /* Allows for fstat(2). */ #define CAP_FSTAT CAPRIGHT(0, 0x0000000000080000ULL) /* Allows for fstat(2), fstatat(2) and faccessat(2). */ #define CAP_FSTATAT (CAP_FSTAT | CAP_LOOKUP) /* Allows for fstatfs(2). */ #define CAP_FSTATFS CAPRIGHT(0, 0x0000000000100000ULL) /* Allows for futimens(2) and futimes(2). */ #define CAP_FUTIMES CAPRIGHT(0, 0x0000000000200000ULL) /* Allows for futimens(2), futimes(2), futimesat(2) and utimensat(2). */ #define CAP_FUTIMESAT (CAP_FUTIMES | CAP_LOOKUP) /* Allows for linkat(2) (target directory descriptor). */ #define CAP_LINKAT_TARGET (CAP_LOOKUP | 0x0000000000400000ULL) /* Allows for mkdirat(2). */ #define CAP_MKDIRAT (CAP_LOOKUP | 0x0000000000800000ULL) /* Allows for mkfifoat(2). */ #define CAP_MKFIFOAT (CAP_LOOKUP | 0x0000000001000000ULL) /* Allows for mknodat(2). */ #define CAP_MKNODAT (CAP_LOOKUP | 0x0000000002000000ULL) /* Allows for renameat(2) (source directory descriptor). */ #define CAP_RENAMEAT_SOURCE (CAP_LOOKUP | 0x0000000004000000ULL) /* Allows for symlinkat(2). */ #define CAP_SYMLINKAT (CAP_LOOKUP | 0x0000000008000000ULL) /* * Allows for unlinkat(2) and renameat(2) if destination object exists and * will be removed. */ #define CAP_UNLINKAT (CAP_LOOKUP | 0x0000000010000000ULL) /* Socket operations. */ /* Allows for accept(2) and accept4(2). */ #define CAP_ACCEPT CAPRIGHT(0, 0x0000000020000000ULL) /* Allows for bind(2). */ #define CAP_BIND CAPRIGHT(0, 0x0000000040000000ULL) /* Allows for connect(2). */ #define CAP_CONNECT CAPRIGHT(0, 0x0000000080000000ULL) /* Allows for getpeername(2). */ #define CAP_GETPEERNAME CAPRIGHT(0, 0x0000000100000000ULL) /* Allows for getsockname(2). */ #define CAP_GETSOCKNAME CAPRIGHT(0, 0x0000000200000000ULL) /* Allows for getsockopt(2). */ #define CAP_GETSOCKOPT CAPRIGHT(0, 0x0000000400000000ULL) /* Allows for listen(2). */ #define CAP_LISTEN CAPRIGHT(0, 0x0000000800000000ULL) /* Allows for sctp_peeloff(2). */ #define CAP_PEELOFF CAPRIGHT(0, 0x0000001000000000ULL) #define CAP_RECV CAP_READ #define CAP_SEND CAP_WRITE /* Allows for setsockopt(2). */ #define CAP_SETSOCKOPT CAPRIGHT(0, 0x0000002000000000ULL) /* Allows for shutdown(2). */ #define CAP_SHUTDOWN CAPRIGHT(0, 0x0000004000000000ULL) /* Allows for bindat(2) on a directory descriptor. */ #define CAP_BINDAT (CAP_LOOKUP | 0x0000008000000000ULL) /* Allows for connectat(2) on a directory descriptor. */ #define CAP_CONNECTAT (CAP_LOOKUP | 0x0000010000000000ULL) /* Allows for linkat(2) (source directory descriptor). */ #define CAP_LINKAT_SOURCE (CAP_LOOKUP | 0x0000020000000000ULL) /* Allows for renameat(2) (target directory descriptor). */ #define CAP_RENAMEAT_TARGET (CAP_LOOKUP | 0x0000040000000000ULL) #define CAP_SOCK_CLIENT \ (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \ CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN) #define CAP_SOCK_SERVER \ (CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \ CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \ CAP_SETSOCKOPT | CAP_SHUTDOWN) /* All used bits for index 0. */ #define CAP_ALL0 CAPRIGHT(0, 0x000007FFFFFFFFFFULL) /* Available bits for index 0. */ #define CAP_UNUSED0_44 CAPRIGHT(0, 0x0000080000000000ULL) /* ... */ #define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL) /* INDEX 1 */ /* Mandatory Access Control. */ /* Allows for mac_get_fd(3). */ #define CAP_MAC_GET CAPRIGHT(1, 0x0000000000000001ULL) /* Allows for mac_set_fd(3). */ #define CAP_MAC_SET CAPRIGHT(1, 0x0000000000000002ULL) /* Methods on semaphores. */ #define CAP_SEM_GETVALUE CAPRIGHT(1, 0x0000000000000004ULL) #define CAP_SEM_POST CAPRIGHT(1, 0x0000000000000008ULL) #define CAP_SEM_WAIT CAPRIGHT(1, 0x0000000000000010ULL) /* Allows select(2) and poll(2) on descriptor. */ #define CAP_EVENT CAPRIGHT(1, 0x0000000000000020ULL) /* Allows for kevent(2) on kqueue descriptor with eventlist != NULL. */ #define CAP_KQUEUE_EVENT CAPRIGHT(1, 0x0000000000000040ULL) /* Strange and powerful rights that should not be given lightly. */ /* Allows for ioctl(2). */ #define CAP_IOCTL CAPRIGHT(1, 0x0000000000000080ULL) #define CAP_TTYHOOK CAPRIGHT(1, 0x0000000000000100ULL) /* Process management via process descriptors. */ /* Allows for pdgetpid(2). */ #define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL) /* * Allows for pdwait4(2). * * XXX: this constant was imported unused, but is targeted to be implemented * in the future (bug 235871). */ #define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL) /* Allows for pdkill(2). */ #define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) /* Extended attributes. */ /* Allows for extattr_delete_fd(2). */ #define CAP_EXTATTR_DELETE CAPRIGHT(1, 0x0000000000001000ULL) /* Allows for extattr_get_fd(2). */ #define CAP_EXTATTR_GET CAPRIGHT(1, 0x0000000000002000ULL) /* Allows for extattr_list_fd(2). */ #define CAP_EXTATTR_LIST CAPRIGHT(1, 0x0000000000004000ULL) /* Allows for extattr_set_fd(2). */ #define CAP_EXTATTR_SET CAPRIGHT(1, 0x0000000000008000ULL) /* Access Control Lists. */ /* Allows for acl_valid_fd_np(3). */ #define CAP_ACL_CHECK CAPRIGHT(1, 0x0000000000010000ULL) /* Allows for acl_delete_fd_np(3). */ #define CAP_ACL_DELETE CAPRIGHT(1, 0x0000000000020000ULL) /* Allows for acl_get_fd(3) and acl_get_fd_np(3). */ #define CAP_ACL_GET CAPRIGHT(1, 0x0000000000040000ULL) /* Allows for acl_set_fd(3) and acl_set_fd_np(3). */ #define CAP_ACL_SET CAPRIGHT(1, 0x0000000000080000ULL) /* Allows for kevent(2) on kqueue descriptor with changelist != NULL. */ #define CAP_KQUEUE_CHANGE CAPRIGHT(1, 0x0000000000100000ULL) #define CAP_KQUEUE (CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE) /* All used bits for index 1. */ #define CAP_ALL1 CAPRIGHT(1, 0x00000000001FFFFFULL) /* Available bits for index 1. */ #define CAP_UNUSED1_22 CAPRIGHT(1, 0x0000000000200000ULL) /* ... */ #define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL) /* Backward compatibility. */ #define CAP_POLL_EVENT CAP_EVENT #define CAP_ALL(rights) do { \ (rights)->cr_rights[0] = \ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAP_ALL0; \ (rights)->cr_rights[1] = CAP_ALL1; \ } while (0) #define CAP_NONE(rights) do { \ (rights)->cr_rights[0] = \ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAPRIGHT(0, 0ULL); \ (rights)->cr_rights[1] = CAPRIGHT(1, 0ULL); \ } while (0) #define CAPRVER(right) ((int)((right) >> 62)) #define CAPVER(rights) CAPRVER((rights)->cr_rights[0]) #define CAPARSIZE(rights) (CAPVER(rights) + 2) #define CAPIDXBIT(right) ((int)(((right) >> 57) & 0x1F)) /* * Allowed fcntl(2) commands. */ #define CAP_FCNTL_GETFL (1 << F_GETFL) #define CAP_FCNTL_SETFL (1 << F_SETFL) #define CAP_FCNTL_GETOWN (1 << F_GETOWN) #define CAP_FCNTL_SETOWN (1 << F_SETOWN) #define CAP_FCNTL_ALL (CAP_FCNTL_GETFL | CAP_FCNTL_SETFL | \ CAP_FCNTL_GETOWN | CAP_FCNTL_SETOWN) #define CAP_IOCTLS_ALL SSIZE_MAX __BEGIN_DECLS #define cap_rights_init(...) \ __cap_rights_init(CAP_RIGHTS_VERSION, __VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_init(int version, cap_rights_t *rights, ...); #define cap_rights_set(...) \ __cap_rights_set(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_set(cap_rights_t *rights, ...); #define cap_rights_clear(...) \ __cap_rights_clear(__VA_ARGS__, 0ULL) cap_rights_t *__cap_rights_clear(cap_rights_t *rights, ...); #define cap_rights_is_set(...) \ __cap_rights_is_set(__VA_ARGS__, 0ULL) bool __cap_rights_is_set(const cap_rights_t *rights, ...); bool cap_rights_is_empty(const cap_rights_t *rights); bool cap_rights_is_valid(const cap_rights_t *rights); cap_rights_t *cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); cap_rights_t *cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); #ifdef _KERNEL /* * We only support one size to reduce branching. */ _Static_assert(CAP_RIGHTS_VERSION == CAP_RIGHTS_VERSION_00, "unsupported version of capsicum rights"); #define cap_rights_init_zero(r) ({ \ cap_rights_t *_r = (r); \ CAP_NONE(_r); \ _r; \ }) #define cap_rights_init_one(r, right) ({ \ CTASSERT(CAPRVER(right) == CAP_RIGHTS_VERSION); \ cap_rights_t *_r = (r); \ CAP_NONE(_r); \ _r->cr_rights[CAPIDXBIT(right) - 1] |= right; \ _r; \ }) #define cap_rights_set_one(r, right) ({ \ CTASSERT(CAPRVER(right) == CAP_RIGHTS_VERSION); \ cap_rights_t *_r = (r); \ _r->cr_rights[CAPIDXBIT(right) - 1] |= right; \ _r; \ }) +#define _CAP_RIGHTS_WORD_INITIALIZER(i, r) \ + (CAPIDXBIT(r) == (i) + 1 ? (r) : 0ULL) + +/* + * Define a set of up to two rights at compile time. + */ +#define CAP_RIGHTS_INITIALIZER2(r1, r2) ((struct cap_rights){ \ + .cr_rights = { \ + [0] = ((uint64_t)CAP_RIGHTS_VERSION << 62) | \ + _CAP_RIGHTS_WORD_INITIALIZER(0, r1) | \ + _CAP_RIGHTS_WORD_INITIALIZER(0, r2), \ + [1] = _CAP_RIGHTS_WORD_INITIALIZER(1, r1) | \ + _CAP_RIGHTS_WORD_INITIALIZER(1, r2), \ + }, \ +}) +#define CAP_RIGHTS_INITIALIZER(r) \ + CAP_RIGHTS_INITIALIZER2(r, 0ULL) + /* * Allow checking caps which are possibly getting modified at the same time. * The caller is expected to determine whether the result is legitimate via * other means, see fget_unlocked for an example. */ static inline bool cap_rights_contains_transient(const cap_rights_t *big, const cap_rights_t *little) { if (__predict_true( (big->cr_rights[0] & little->cr_rights[0]) == little->cr_rights[0] && (big->cr_rights[1] & little->cr_rights[1]) == little->cr_rights[1])) return (true); return (false); } #define cap_rights_contains cap_rights_contains_transient int cap_check_failed_notcapable(const cap_rights_t *havep, const cap_rights_t *needp); static inline int cap_check_inline(const cap_rights_t *havep, const cap_rights_t *needp) { if (__predict_false(!cap_rights_contains(havep, needp))) return (cap_check_failed_notcapable(havep, needp)); return (0); } static inline int cap_check_inline_transient(const cap_rights_t *havep, const cap_rights_t *needp) { if (__predict_false(!cap_rights_contains(havep, needp))) return (1); return (0); } #else bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); #endif __END_DECLS #ifdef _KERNEL #include #include #ifdef KTRACE #define CAP_TRACING(td) KTRPOINT((td), KTR_CAPFAIL) #else #define CAP_TRACING(td) 0 #endif #define IN_CAPABILITY_MODE(td) (((td)->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0) struct filedesc; struct filedescent; /* * Test whether a capability grants the requested rights. */ int cap_check(const cap_rights_t *havep, const cap_rights_t *needp); /* * Convert capability rights into VM access flags. */ vm_prot_t cap_rights_to_vmprot(const cap_rights_t *havep); /* * For the purposes of procstat(1) and similar tools, allow kern_descrip.c to * extract the rights from a capability. * * Dereferencing fdep requires filedesc.h, but including it would cause * significant pollution. Instead add a macro for consumers which want it, * most notably kern_descrip.c. */ #define cap_rights_fde_inline(fdep) (&(fdep)->fde_rights) const cap_rights_t *cap_rights_fde(const struct filedescent *fde); const cap_rights_t *cap_rights(struct filedesc *fdp, int fd); int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd); int cap_fcntl_check_fde(struct filedescent *fde, int cmd); int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd); extern bool trap_enotcap; #else /* !_KERNEL */ __BEGIN_DECLS /* * cap_enter(): Cause the process to enter capability mode, which will * prevent it from directly accessing global namespaces. System calls will * be limited to process-local, process-inherited, or file descriptor * operations. If already in capability mode, a no-op. */ int cap_enter(void); /* * Are we sandboxed (in capability mode)? * This is a libc wrapper around the cap_getmode(2) system call. */ bool cap_sandboxed(void); /* * cap_getmode(): Are we in capability mode? */ int cap_getmode(u_int *modep); /* * Limits capability rights for the given descriptor (CAP_*). */ int cap_rights_limit(int fd, const cap_rights_t *rights); /* * Returns capability rights for the given descriptor. */ #define cap_rights_get(fd, rights) \ __cap_rights_get(CAP_RIGHTS_VERSION, (fd), (rights)) int __cap_rights_get(int version, int fd, cap_rights_t *rights); /* * Limits allowed ioctls for the given descriptor. */ int cap_ioctls_limit(int fd, const cap_ioctl_t *cmds, size_t ncmds); /* * Returns array of allowed ioctls for the given descriptor. * If all ioctls are allowed, the cmds array is not populated and * the function returns CAP_IOCTLS_ALL. */ ssize_t cap_ioctls_get(int fd, cap_ioctl_t *cmds, size_t maxcmds); /* * Limits allowed fcntls for the given descriptor (CAP_FCNTL_*). */ int cap_fcntls_limit(int fd, uint32_t fcntlrights); /* * Returns bitmask of allowed fcntls for the given descriptor. */ int cap_fcntls_get(int fd, uint32_t *fcntlrightsp); __END_DECLS #endif /* !_KERNEL */ #endif /* !_SYS_CAPSICUM_H_ */