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