]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/subr_capability.c
Fix missing pfctl(8) tunable.
[FreeBSD/FreeBSD.git] / sys / kern / subr_capability.c
1 /*-
2  * Copyright (c) 2013 FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
6  * the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 /*
34  * Note that this file is compiled into the kernel and into libc.
35  */
36
37 #include <sys/types.h>
38 #include <sys/capsicum.h>
39
40 #ifdef _KERNEL
41 #include <sys/systm.h>
42
43 #include <machine/stdarg.h>
44 #else   /* !_KERNEL */
45 #include <assert.h>
46 #include <stdarg.h>
47 #include <stdbool.h>
48 #include <stdint.h>
49 #include <string.h>
50 #endif
51
52 #ifdef _KERNEL
53 #define assert(exp)     KASSERT((exp), ("%s:%u", __func__, __LINE__))
54 #endif
55
56 #define CAPARSIZE_MIN   (CAP_RIGHTS_VERSION_00 + 2)
57 #define CAPARSIZE_MAX   (CAP_RIGHTS_VERSION + 2)
58
59 static __inline int
60 right_to_index(uint64_t right)
61 {
62         static const int bit2idx[] = {
63                 -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
64                 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
65         };
66         int idx;
67
68         idx = CAPIDXBIT(right);
69         assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0]));
70         return (bit2idx[idx]);
71 }
72
73 static void
74 cap_rights_vset(cap_rights_t *rights, va_list ap)
75 {
76         uint64_t right;
77         int i, n;
78
79         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
80
81         n = CAPARSIZE(rights);
82         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
83
84         for (;;) {
85                 right = (uint64_t)va_arg(ap, unsigned long long);
86                 if (right == 0)
87                         break;
88                 assert(CAPRVER(right) == 0);
89                 i = right_to_index(right);
90                 assert(i >= 0);
91                 assert(i < n);
92                 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
93                 rights->cr_rights[i] |= right;
94                 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
95         }
96 }
97
98 static void
99 cap_rights_vclear(cap_rights_t *rights, va_list ap)
100 {
101         uint64_t right;
102         int i, n;
103
104         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
105
106         n = CAPARSIZE(rights);
107         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
108
109         for (;;) {
110                 right = (uint64_t)va_arg(ap, unsigned long long);
111                 if (right == 0)
112                         break;
113                 assert(CAPRVER(right) == 0);
114                 i = right_to_index(right);
115                 assert(i >= 0);
116                 assert(i < n);
117                 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
118                 rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL);
119                 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
120         }
121 }
122
123 static bool
124 cap_rights_is_vset(const cap_rights_t *rights, va_list ap)
125 {
126         uint64_t right;
127         int i, n;
128
129         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
130
131         n = CAPARSIZE(rights);
132         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
133
134         for (;;) {
135                 right = (uint64_t)va_arg(ap, unsigned long long);
136                 if (right == 0)
137                         break;
138                 assert(CAPRVER(right) == 0);
139                 i = right_to_index(right);
140                 assert(i >= 0);
141                 assert(i < n);
142                 assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
143                 if ((rights->cr_rights[i] & right) != right)
144                         return (false);
145         }
146
147         return (true);
148 }
149
150 cap_rights_t *
151 __cap_rights_init(int version, cap_rights_t *rights, ...)
152 {
153         unsigned int n;
154         va_list ap;
155
156         assert(version == CAP_RIGHTS_VERSION_00);
157
158         n = version + 2;
159         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
160         CAP_NONE(rights);
161         va_start(ap, rights);
162         cap_rights_vset(rights, ap);
163         va_end(ap);
164
165         return (rights);
166 }
167
168 cap_rights_t *
169 __cap_rights_set(cap_rights_t *rights, ...)
170 {
171         va_list ap;
172
173         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
174
175         va_start(ap, rights);
176         cap_rights_vset(rights, ap);
177         va_end(ap);
178
179         return (rights);
180 }
181
182 cap_rights_t *
183 __cap_rights_clear(cap_rights_t *rights, ...)
184 {
185         va_list ap;
186
187         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
188
189         va_start(ap, rights);
190         cap_rights_vclear(rights, ap);
191         va_end(ap);
192
193         return (rights);
194 }
195
196 bool
197 __cap_rights_is_set(const cap_rights_t *rights, ...)
198 {
199         va_list ap;
200         bool ret;
201
202         assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
203
204         va_start(ap, rights);
205         ret = cap_rights_is_vset(rights, ap);
206         va_end(ap);
207
208         return (ret);
209 }
210
211 bool
212 cap_rights_is_valid(const cap_rights_t *rights)
213 {
214         cap_rights_t allrights;
215         int i, j;
216
217         if (CAPVER(rights) != CAP_RIGHTS_VERSION_00)
218                 return (false);
219         if (CAPARSIZE(rights) < CAPARSIZE_MIN ||
220             CAPARSIZE(rights) > CAPARSIZE_MAX) {
221                 return (false);
222         }
223         CAP_ALL(&allrights);
224         if (!cap_rights_contains(&allrights, rights))
225                 return (false);
226         for (i = 0; i < CAPARSIZE(rights); i++) {
227                 j = right_to_index(rights->cr_rights[i]);
228                 if (i != j)
229                         return (false);
230                 if (i > 0) {
231                         if (CAPRVER(rights->cr_rights[i]) != 0)
232                                 return (false);
233                 }
234         }
235
236         return (true);
237 }
238
239 cap_rights_t *
240 cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src)
241 {
242         unsigned int i, n;
243
244         assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
245         assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
246         assert(CAPVER(dst) == CAPVER(src));
247         assert(cap_rights_is_valid(src));
248         assert(cap_rights_is_valid(dst));
249
250         n = CAPARSIZE(dst);
251         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
252
253         for (i = 0; i < n; i++)
254                 dst->cr_rights[i] |= src->cr_rights[i];
255
256         assert(cap_rights_is_valid(src));
257         assert(cap_rights_is_valid(dst));
258
259         return (dst);
260 }
261
262 cap_rights_t *
263 cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src)
264 {
265         unsigned int i, n;
266
267         assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
268         assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
269         assert(CAPVER(dst) == CAPVER(src));
270         assert(cap_rights_is_valid(src));
271         assert(cap_rights_is_valid(dst));
272
273         n = CAPARSIZE(dst);
274         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
275
276         for (i = 0; i < n; i++) {
277                 dst->cr_rights[i] &=
278                     ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL);
279         }
280
281         assert(cap_rights_is_valid(src));
282         assert(cap_rights_is_valid(dst));
283
284         return (dst);
285 }
286
287 bool
288 cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
289 {
290         unsigned int i, n;
291
292         assert(CAPVER(big) == CAP_RIGHTS_VERSION_00);
293         assert(CAPVER(little) == CAP_RIGHTS_VERSION_00);
294         assert(CAPVER(big) == CAPVER(little));
295
296         n = CAPARSIZE(big);
297         assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
298
299         for (i = 0; i < n; i++) {
300                 if ((big->cr_rights[i] & little->cr_rights[i]) !=
301                     little->cr_rights[i]) {
302                         return (false);
303                 }
304         }
305
306         return (true);
307 }