CAP_SYSCTL(3)
π
CAP_SYSCTL(3) β the cap_sysctl(3) library manual, bestie edition
okay so this is the manual for cap_sysctl, and honestly? it's a whole vibe. it's the library for getting or setting system information in capability mode. yes, that capability mode. we love a sandboxed queen π
β¨ NAME β¨
cap_sysctl β library for getting or setting system information in capability mode. that's it, that's the tweet π
π LIBRARY π
library βlibcap_sysctlβ β go ahead and link her, she's ready π«Ά
π SYNOPSIS π
like, include the headers first, obviously:
#include <libcasper.h>
#include <casper/cap_sysctl.h>
and then all the functions, in all their glory:
int
cap_sysctl(cap_channel_t *chan, const int *name, u_int namelen,
void *oldp, size_t *oldlenp, const void *newp, size_t newlen);
int
cap_sysctlbyname(cap_channel_t *chan, const char *name, void *oldp,
size_t *oldlenp, const void *newp, size_t newlen);
int
cap_sysctlnametomib(cap_channel_t *chan, const char *name, int *mibp,
size_t *sizep);
cap_sysctl_limit_t *
cap_sysctl_limit_init(cap_channel_t *chan);
cap_sysctl_limit_t *
cap_sysctl_limit_name(cap_sysctl_limit_t *limit, const char *name,
int flags);
cap_sysctl_limit_t *
cap_sysctl_limit_mib(cap_sysctl_limit_t *limit, const int *mibp,
u_int miblen, int flags);
int
cap_sysctl_limit(cap_sysctl_limit_t *limit);
π DESCRIPTION π
so cap_sysctl(), cap_sysctlbyname() and cap_sysctlnametomib() are literally the same energy as sysctl(3), sysctlbyname(3) and sysctlnametomib(3) β like, same functions, same behaviour β EXCEPT they're implemented by the βsystem.sysctlβ libcasper(3) service and they need a corresponding libcasper(3) capability. no capability, no service, no vibes. periodt.
now listen up, because this is the important part π
all of these functions β with the exceptions of cap_sysctl_limit_init() and cap_sysctl_limit_mib() β are reentrant but not thread-safe. so like, you can call them from separate threads, but only with different cap_channel_t arguments, or with synchronization. do not come for me if you skip the sync, bestie, it's giving undefined chaos π
π LIMITS π
by default, the cap_sysctl capability gives you unrestricted access to the sysctl namespace. the whole thing. no cap. but like, most applications only need a tiny handful of sysctl variables, so the cap_sysctl_limit() interface exists to restrict which sysctls you can touch through the cap_sysctl capability. it's giving β¨boundariesβ¨ and we respect them.
cap_sysctl_limit_init() returns an opaque limit handle that stores a list of permitted sysctls and access rights. and the rights are encoded with these flags:
CAP_SYSCTL_READβ allow reads of the sysctl variableCAP_SYSCTL_WRITEβ allow writes of the sysctl variableCAP_SYSCTL_RDWRβ allow reads and writes of the sysctl variableCAP_RECURSIVEβ permit access to any child of the sysctl variable
so, cap_sysctl_limit_name() adds the sysctl identified by name to the limit list, and cap_sysctl_limit_mib() adds the sysctl identified by mibp to the limit list. the access rights for the sysctl go in the flags parameter, and you must specify at least one of CAP_SYSCTL_READ, CAP_SYSCTL_WRITE and CAP_SYSCTL_RDWR. no flags, no entry, no exceptions π
then cap_sysctl_limit() applies a set of sysctl limits to the capability, denying access to sysctl variables that aren't in the set. it consumes the limit handle. and after either success or failure, you must not access the handle again. like, it's gone, she's moved on, do not text her π
once a set of limits is applied, subsequent calls to cap_sysctl_limit() will fail unless the new set is a subset of the current set. narrowing only, bestie. no take-backs.
and cap_sysctlnametomib() will succeed so long as the named sysctl variable is present in the limit set β regardless of its access rights. when a sysctl variable name is added to a limit set, its MIB identifier is automatically added to the set too. package deal π
π¦ EXAMPLES π¦
okay this example is iconic. it first opens a capability to casper, uses that capability to create the system.sysctl casper service, and then uses the cap_sysctl capability to get the value of kern.trap_enotcap. ate and left no crumbs:
cap_channel_t *capcas, *capsysctl;
const char *name = "kern.trap_enotcap";
void *limit;
size_t size;
bool value;
/* Open capability to Casper. */
capcas = cap_init();
if (capcas == NULL)
err(1, "Unable to contact Casper");
/* Enter capability mode sandbox. */
if (cap_enter() < 0 && errno != ENOSYS)
err(1, "Unable to enter capability mode");
/* Use Casper capability to create capability to the system.sysctl service. */
capsysctl = cap_service_open(capcas, "system.sysctl");
if (capsysctl == NULL)
err(1, "Unable to open system.sysctl service");
/* Close Casper capability, we don't need it anymore. */
cap_close(capcas);
/* Create limit for one MIB with read access only. */
limit = cap_sysctl_limit_init(capsysctl);
(void)cap_sysctl_limit_name(limit, name, CAP_SYSCTL_READ);
/* Limit system.sysctl. */
if (cap_sysctl_limit(limit) < 0)
err(1, "Unable to set limits");
/* Fetch value. */
size = sizeof(value);
if (cap_sysctlbyname(capsysctl, name, &value, &size, NULL, 0) < 0)
err(1, "Unable to get value of sysctl");
printf("The value of %s is %d.\n", name, value);
cap_close(capsysctl);
πΈ RETURN VALUES πΈ
so here's the tea on what each one hands back:
cap_sysctl_limit_init()returns a new limit handle on success, orNULLon failure, and setserrno.cap_sysctl_limit_mib()andcap_sysctl_limit_name()return the modified limit handle on success, orNULLon failure and seterrno. And after failure, the caller must not access the limit handle again. seriously. don't.cap_sysctl_limit()returns-1on failure and setserrno.cap_sysctl(),cap_sysctlbyname(), andcap_sysctlnametomib()have the same return values as their non-capability-mode equivalents as documented insysctl(3). same energy, different sandbox π«Ά
π SEE ALSO π
go read them, iykyk π
β HISTORY β
the cap_sysctl service first appeared in FreeBSD 10.3. a legend from the start π
π AUTHORS π
the cap_sysctl service was implemented by Pawel Jakub Dawidek <pawel@dawidek.net> under sponsorship from the FreeBSD Foundation. slay π
this manual page was written by Mariusz Zaborski <oshogbo@FreeBSD.org>. thank you for your service π
π§ and that's the whole page, bestie! no notes, no cap. now go forth and sysctl responsibly β¨
Debian Β· December 6, 2023 Β· CAP_SYSCTL(3) β that's the source, the version and the date, all wrapped up with a bow π bye bestie, love u, drink water π
π¦ where this page comes from
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- Copyright (c) 2018 Mariusz Zaborski <oshogbo@FreeBSD.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms