1.\" Copyright (c) 2018 Mariusz Zaborski <oshogbo@FreeBSD.org>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.\"
25.Dd December 6, 2023
26.Dt CAP_SYSCTL 3
27.Os
28.Sh NAME
29.Nm cap_sysctl
30.Nd "library for getting or setting system information in capability mode"
31.Sh LIBRARY
32.Lb libcap_sysctl
33.Sh SYNOPSIS
34.In libcasper.h
35.In casper/cap_sysctl.h
36.Ft int
37.Fn cap_sysctl "cap_channel_t *chan" "const int *name" "u_int namelen" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
38.Ft int
39.Fn cap_sysctlbyname "cap_channel_t *chan" "const char *name" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
40.Ft int
41.Fn cap_sysctlnametomib "cap_channel_t *chan" "const char *name" "int *mibp" "size_t *sizep"
42.Ft cap_sysctl_limit_t *
43.Fn cap_sysctl_limit_init "cap_channel_t *chan"
44.Ft cap_sysctl_limit_t *
45.Fn cap_sysctl_limit_name "cap_sysctl_limit_t *limit" "const char *name" "int flags"
46.Ft cap_sysctl_limit_t *
47.Fn cap_sysctl_limit_mib "cap_sysctl_limit_t *limit" "const int *mibp" "u_int miblen" "int flags"
48.Ft int
49.Fn cap_sysctl_limit "cap_sysctl_limit_t *limit"
50.Sh DESCRIPTION
51The
52.Fn cap_sysctl ,
53.Fn cap_sysctlbyname
54and
55.Fn cap_sysctlnametomib
56functions are equivalent to
57.Xr sysctl 3 ,
58.Xr sysctlbyname 3
59and
60.Xr sysctlnametomib 3 ,
61except that they are implemented by the
62.Ql system.sysctl
63.Xr libcasper 3
64service and require a corresponding
65.Xr libcasper 3
66capability.
67.Pp
68All of these functions, with the exceptions of
69.Fn cap_sysctl_limit_init
70and
71.Fn cap_sysctl_limit_mib ,
72are reentrant but not thread-safe.
73That is, they may be called from separate threads only with different
74.Vt cap_channel_t
75arguments or with synchronization.
76.Sh LIMITS
77By default, the
78.Nm
79capability provides unrestricted access to the sysctl namespace.
80Applications typically only require access to a small number of sysctl
81variables; the
82.Fn cap_sysctl_limit
83interface can be used to restrict the sysctls that can be accessed using
84the
85.Nm
86capability.
87.Fn cap_sysctl_limit_init
88returns an opaque limit handle used to store a list of permitted sysctls
89and access rights.
90Rights are encoded using the following flags:
91.Pp
92.Bd -literal -offset indent -compact
93CAP_SYSCTL_READ		allow reads of the sysctl variable
94CAP_SYSCTL_WRITE        allow writes of the sysctl variable
95CAP_SYSCTL_RDWR         allow reads and writes of the sysctl variable
96CAP_RECURSIVE           permit access to any child of the sysctl variable
97.Ed
98.Pp
99The
100.Fn cap_sysctl_limit_name
101function adds the sysctl identified by
102.Ar name
103to the limit list, and
104.Fn cap_sysctl_limit_mib
105function adds the sysctl identified by
106.Ar mibp
107to the limit list.
108The access rights for the sysctl are specified in the
109.Ar flags
110parameter; at least one of
111.Dv CAP_SYSCTL_READ ,
112.Dv CAP_SYSCTL_WRITE
113and
114.Dv CAP_SYSCTL_RDWR
115must be specified.
116.Fn cap_sysctl_limit
117applies a set of sysctl limits to the capability, denying access to sysctl
118variables not belonging to the set.
119It consumes the limit handle.
120After either success or failure, the user must not access the handle again.
121.Pp
122Once a set of limits is applied, subsequent calls to
123.Fn cap_sysctl_limit
124will fail unless the new set is a subset of the current set.
125.Pp
126.Fn cap_sysctlnametomib
127will succeed so long as the named sysctl variable is present in the limit set,
128regardless of its access rights.
129When a sysctl variable name is added to a limit set, its MIB identifier is
130automatically added to the set.
131.Sh EXAMPLES
132The following example first opens a capability to casper, uses this
133capability to create the
134.Nm system.sysctl
135casper service, and then uses the
136.Nm
137capability to get the value of
138.Dv kern.trap_enotcap .
139.Bd -literal
140cap_channel_t *capcas, *capsysctl;
141const char *name = "kern.trap_enotcap";
142void *limit;
143size_t size;
144bool value;
145
146/* Open capability to Casper. */
147capcas = cap_init();
148if (capcas == NULL)
149	err(1, "Unable to contact Casper");
150
151/* Enter capability mode sandbox. */
152if (cap_enter() < 0 && errno != ENOSYS)
153	err(1, "Unable to enter capability mode");
154
155/* Use Casper capability to create capability to the system.sysctl service. */
156capsysctl = cap_service_open(capcas, "system.sysctl");
157if (capsysctl == NULL)
158	err(1, "Unable to open system.sysctl service");
159
160/* Close Casper capability, we don't need it anymore. */
161cap_close(capcas);
162
163/* Create limit for one MIB with read access only. */
164limit = cap_sysctl_limit_init(capsysctl);
165(void)cap_sysctl_limit_name(limit, name, CAP_SYSCTL_READ);
166
167/* Limit system.sysctl. */
168if (cap_sysctl_limit(limit) < 0)
169	err(1, "Unable to set limits");
170
171/* Fetch value. */
172size = sizeof(value);
173if (cap_sysctlbyname(capsysctl, name, &value, &size, NULL, 0) < 0)
174	err(1, "Unable to get value of sysctl");
175
176printf("The value of %s is %d.\\n", name, value);
177
178cap_close(capsysctl);
179.Ed
180.Sh RETURN VALUES
181.Fn cap_sysctl_limit_init
182will return a new limit handle on success or
183.Dv NULL
184on failure, and set
185.Va errno .
186.Fn cap_sysctl_limit_mib
187and
188.Fn cap_sysctl_limit_name
189will return the modified limit handle on success or
190.Dv NULL
191on failure and set
192.Va errno .
193After failure, the caller must not access the limit handle again.
194.Fn cap_sysctl_limit
195will return
196.Dv -1
197on failure and set
198.Va errno .
199.Fn cap_sysctl ,
200.Fn cap_sysctlbyname ,
201and
202.Fn cap_sysctlnametomib
203have the same return values as their non-capability-mode equivalents as
204documented in
205.Xr sysctl 3 .
206.Sh SEE ALSO
207.Xr cap_enter 2 ,
208.Xr err 3 ,
209.Xr sysctl 3 ,
210.Xr sysctlbyname 3 ,
211.Xr sysctlnametomib 3 ,
212.Xr capsicum 4 ,
213.Xr nv 9
214.Sh HISTORY
215The
216.Nm cap_sysctl
217service first appeared in
218.Fx 10.3 .
219.Sh AUTHORS
220The
221.Nm cap_sysctl
222service was implemented by
223.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
224under sponsorship from the FreeBSD Foundation.
225.Pp
226This manual page was written by
227.An Mariusz Zaborski Aq Mt oshogbo@FreeBSD.org .
228