Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <errno.h>
4 : : #include <grp.h>
5 : : #include <stdio.h>
6 : : #include <stdlib.h>
7 : : #include <sys/capability.h>
8 : : #include <sys/prctl.h>
9 : : #include <unistd.h>
10 : :
11 : : #include "alloc-util.h"
12 : : #include "capability-util.h"
13 : : #include "cap-list.h"
14 : : #include "fileio.h"
15 : : #include "log.h"
16 : : #include "macro.h"
17 : : #include "missing_prctl.h"
18 : : #include "parse-util.h"
19 : : #include "user-util.h"
20 : : #include "util.h"
21 : :
22 : 4 : int have_effective_cap(int value) {
23 : 4 : _cleanup_cap_free_ cap_t cap;
24 : : cap_flag_value_t fv;
25 : :
26 : 4 : cap = cap_get_proc();
27 [ - + ]: 4 : if (!cap)
28 : 0 : return -errno;
29 : :
30 [ - + ]: 4 : if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0)
31 : 0 : return -errno;
32 : :
33 : 4 : return fv == CAP_SET;
34 : : }
35 : :
36 : 2228 : unsigned long cap_last_cap(void) {
37 : : static thread_local unsigned long saved;
38 : : static thread_local bool valid = false;
39 : 2228 : _cleanup_free_ char *content = NULL;
40 : 2228 : unsigned long p = 0;
41 : : int r;
42 : :
43 [ + + ]: 2228 : if (valid)
44 : 2212 : return saved;
45 : :
46 : : /* available since linux-3.2 */
47 : 16 : r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
48 [ + - ]: 16 : if (r >= 0) {
49 : 16 : r = safe_atolu(content, &p);
50 [ + - ]: 16 : if (r >= 0) {
51 : :
52 [ - + ]: 16 : if (p > 63) /* Safety for the future: if one day the kernel learns more than 64 caps,
53 : : * then we are in trouble (since we, as much userspace and kernel space
54 : : * store capability masks in uint64_t types). Let's hence protect
55 : : * ourselves against that and always cap at 63 for now. */
56 : 0 : p = 63;
57 : :
58 : 16 : saved = p;
59 : 16 : valid = true;
60 : 16 : return p;
61 : : }
62 : : }
63 : :
64 : : /* fall back to syscall-probing for pre linux-3.2 */
65 : 0 : p = MIN((unsigned long) CAP_LAST_CAP, 63U);
66 : :
67 [ # # ]: 0 : if (prctl(PR_CAPBSET_READ, p) < 0) {
68 : :
69 : : /* Hmm, look downwards, until we find one that works */
70 [ # # ]: 0 : for (p--; p > 0; p --)
71 [ # # ]: 0 : if (prctl(PR_CAPBSET_READ, p) >= 0)
72 : 0 : break;
73 : :
74 : : } else {
75 : :
76 : : /* Hmm, look upwards, until we find one that doesn't work */
77 [ # # ]: 0 : for (; p < 63; p++)
78 [ # # ]: 0 : if (prctl(PR_CAPBSET_READ, p+1) < 0)
79 : 0 : break;
80 : : }
81 : :
82 : 0 : saved = p;
83 : 0 : valid = true;
84 : :
85 : 0 : return p;
86 : : }
87 : :
88 : 0 : int capability_update_inherited_set(cap_t caps, uint64_t set) {
89 : : unsigned long i;
90 : :
91 : : /* Add capabilities in the set to the inherited caps. Do not apply
92 : : * them yet. */
93 : :
94 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
95 : :
96 [ # # ]: 0 : if (set & (UINT64_C(1) << i)) {
97 : : cap_value_t v;
98 : :
99 : 0 : v = (cap_value_t) i;
100 : :
101 : : /* Make the capability inheritable. */
102 [ # # ]: 0 : if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, CAP_SET) < 0)
103 : 0 : return -errno;
104 : : }
105 : : }
106 : :
107 : 0 : return 0;
108 : : }
109 : :
110 : 0 : int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
111 : 0 : _cleanup_cap_free_ cap_t caps = NULL;
112 : : unsigned long i;
113 : : int r;
114 : :
115 : : /* Add the capabilities to the ambient set. */
116 : :
117 [ # # ]: 0 : if (also_inherit) {
118 : 0 : caps = cap_get_proc();
119 [ # # ]: 0 : if (!caps)
120 : 0 : return -errno;
121 : :
122 : 0 : r = capability_update_inherited_set(caps, set);
123 [ # # ]: 0 : if (r < 0)
124 : 0 : return -errno;
125 : :
126 [ # # ]: 0 : if (cap_set_proc(caps) < 0)
127 : 0 : return -errno;
128 : : }
129 : :
130 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
131 : :
132 [ # # ]: 0 : if (set & (UINT64_C(1) << i)) {
133 : :
134 : : /* Add the capability to the ambient set. */
135 [ # # ]: 0 : if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0)
136 : 0 : return -errno;
137 : : }
138 : : }
139 : :
140 : 0 : return 0;
141 : : }
142 : :
143 : 0 : int capability_bounding_set_drop(uint64_t keep, bool right_now) {
144 : 0 : _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL;
145 : : cap_flag_value_t fv;
146 : : unsigned long i;
147 : : int r;
148 : :
149 : : /* If we are run as PID 1 we will lack CAP_SETPCAP by default
150 : : * in the effective set (yes, the kernel drops that when
151 : : * executing init!), so get it back temporarily so that we can
152 : : * call PR_CAPBSET_DROP. */
153 : :
154 : 0 : before_cap = cap_get_proc();
155 [ # # ]: 0 : if (!before_cap)
156 : 0 : return -errno;
157 : :
158 [ # # ]: 0 : if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0)
159 : 0 : return -errno;
160 : :
161 [ # # ]: 0 : if (fv != CAP_SET) {
162 [ # # ]: 0 : _cleanup_cap_free_ cap_t temp_cap = NULL;
163 : : static const cap_value_t v = CAP_SETPCAP;
164 : :
165 : 0 : temp_cap = cap_dup(before_cap);
166 [ # # ]: 0 : if (!temp_cap)
167 : 0 : return -errno;
168 : :
169 [ # # ]: 0 : if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0)
170 : 0 : return -errno;
171 : :
172 [ # # ]: 0 : if (cap_set_proc(temp_cap) < 0)
173 [ # # ]: 0 : log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m");
174 : :
175 : : /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means
176 : : * we'll fail later, when we actually intend to drop some capabilities. */
177 : : }
178 : :
179 : 0 : after_cap = cap_dup(before_cap);
180 [ # # ]: 0 : if (!after_cap)
181 : 0 : return -errno;
182 : :
183 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
184 : : cap_value_t v;
185 : :
186 [ # # ]: 0 : if ((keep & (UINT64_C(1) << i)))
187 : 0 : continue;
188 : :
189 : : /* Drop it from the bounding set */
190 [ # # ]: 0 : if (prctl(PR_CAPBSET_DROP, i) < 0) {
191 : 0 : r = -errno;
192 : :
193 : : /* If dropping the capability failed, let's see if we didn't have it in the first place. If so,
194 : : * continue anyway, as dropping a capability we didn't have in the first place doesn't really
195 : : * matter anyway. */
196 [ # # ]: 0 : if (prctl(PR_CAPBSET_READ, i) != 0)
197 : 0 : goto finish;
198 : : }
199 : 0 : v = (cap_value_t) i;
200 : :
201 : : /* Also drop it from the inheritable set, so
202 : : * that anything we exec() loses the
203 : : * capability for good. */
204 [ # # ]: 0 : if (cap_set_flag(after_cap, CAP_INHERITABLE, 1, &v, CAP_CLEAR) < 0) {
205 : 0 : r = -errno;
206 : 0 : goto finish;
207 : : }
208 : :
209 : : /* If we shall apply this right now drop it
210 : : * also from our own capability sets. */
211 [ # # ]: 0 : if (right_now) {
212 [ # # # # ]: 0 : if (cap_set_flag(after_cap, CAP_PERMITTED, 1, &v, CAP_CLEAR) < 0 ||
213 : 0 : cap_set_flag(after_cap, CAP_EFFECTIVE, 1, &v, CAP_CLEAR) < 0) {
214 : 0 : r = -errno;
215 : 0 : goto finish;
216 : : }
217 : : }
218 : : }
219 : :
220 : 0 : r = 0;
221 : :
222 : 0 : finish:
223 [ # # ]: 0 : if (cap_set_proc(after_cap) < 0) {
224 : : /* If there are no actual changes anyway then let's ignore this error. */
225 [ # # ]: 0 : if (cap_compare(before_cap, after_cap) != 0)
226 : 0 : r = -errno;
227 : : }
228 : :
229 : 0 : return r;
230 : : }
231 : :
232 : 0 : static int drop_from_file(const char *fn, uint64_t keep) {
233 : 0 : _cleanup_free_ char *p = NULL;
234 : : uint64_t current, after;
235 : : uint32_t hi, lo;
236 : : int r, k;
237 : :
238 : 0 : r = read_one_line_file(fn, &p);
239 [ # # ]: 0 : if (r < 0)
240 : 0 : return r;
241 : :
242 : 0 : k = sscanf(p, "%" PRIu32 " %" PRIu32, &lo, &hi);
243 [ # # ]: 0 : if (k != 2)
244 : 0 : return -EIO;
245 : :
246 : 0 : current = (uint64_t) lo | ((uint64_t) hi << 32);
247 : 0 : after = current & keep;
248 : :
249 [ # # ]: 0 : if (current == after)
250 : 0 : return 0;
251 : :
252 : 0 : lo = after & UINT32_C(0xFFFFFFFF);
253 : 0 : hi = (after >> 32) & UINT32_C(0xFFFFFFFF);
254 : :
255 : 0 : return write_string_filef(fn, 0, "%" PRIu32 " %" PRIu32, lo, hi);
256 : : }
257 : :
258 : 0 : int capability_bounding_set_drop_usermode(uint64_t keep) {
259 : : int r;
260 : :
261 : 0 : r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep);
262 [ # # ]: 0 : if (r < 0)
263 : 0 : return r;
264 : :
265 : 0 : r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep);
266 [ # # ]: 0 : if (r < 0)
267 : 0 : return r;
268 : :
269 : 0 : return r;
270 : : }
271 : :
272 : 0 : int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
273 : : int r;
274 : :
275 : : /* Unfortunately we cannot leave privilege dropping to PID 1 here, since we want to run as user but
276 : : * want to keep some capabilities. Since file capabilities have been introduced this cannot be done
277 : : * across exec() anymore, unless our binary has the capability configured in the file system, which
278 : : * we want to avoid. */
279 : :
280 [ # # ]: 0 : if (setresgid(gid, gid, gid) < 0)
281 [ # # ]: 0 : return log_error_errno(errno, "Failed to change group ID: %m");
282 : :
283 : 0 : r = maybe_setgroups(0, NULL);
284 [ # # ]: 0 : if (r < 0)
285 [ # # ]: 0 : return log_error_errno(r, "Failed to drop auxiliary groups list: %m");
286 : :
287 : : /* Ensure we keep the permitted caps across the setresuid(). Note that we do this even if we actually
288 : : * don't want to keep any capabilities, since we want to be able to drop them from the bounding set
289 : : * too, and we can only do that if we have capabilities. */
290 [ # # ]: 0 : if (prctl(PR_SET_KEEPCAPS, 1) < 0)
291 [ # # ]: 0 : return log_error_errno(errno, "Failed to enable keep capabilities flag: %m");
292 : :
293 [ # # ]: 0 : if (setresuid(uid, uid, uid) < 0)
294 [ # # ]: 0 : return log_error_errno(errno, "Failed to change user ID: %m");
295 : :
296 [ # # ]: 0 : if (prctl(PR_SET_KEEPCAPS, 0) < 0)
297 [ # # ]: 0 : return log_error_errno(errno, "Failed to disable keep capabilities flag: %m");
298 : :
299 : : /* Drop all caps from the bounding set (as well as the inheritable/permitted/effective sets), except
300 : : * the ones we want to keep */
301 : 0 : r = capability_bounding_set_drop(keep_capabilities, true);
302 [ # # ]: 0 : if (r < 0)
303 [ # # ]: 0 : return log_error_errno(r, "Failed to drop capabilities: %m");
304 : :
305 : : /* Now upgrade the permitted caps we still kept to effective caps */
306 [ # # ]: 0 : if (keep_capabilities != 0) {
307 : 0 : cap_value_t bits[u64log2(keep_capabilities) + 1];
308 [ # # ]: 0 : _cleanup_cap_free_ cap_t d = NULL;
309 : 0 : unsigned i, j = 0;
310 : :
311 : 0 : d = cap_init();
312 [ # # ]: 0 : if (!d)
313 : 0 : return log_oom();
314 : :
315 [ # # ]: 0 : for (i = 0; i < ELEMENTSOF(bits); i++)
316 [ # # ]: 0 : if (keep_capabilities & (1ULL << i))
317 : 0 : bits[j++] = i;
318 : :
319 : : /* use enough bits */
320 [ # # # # ]: 0 : assert(i == 64 || (keep_capabilities >> i) == 0);
321 : : /* don't use too many bits */
322 [ # # ]: 0 : assert(keep_capabilities & (UINT64_C(1) << (i - 1)));
323 : :
324 [ # # # # ]: 0 : if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 ||
325 : 0 : cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0)
326 [ # # ]: 0 : return log_error_errno(errno, "Failed to enable capabilities bits: %m");
327 : :
328 [ # # ]: 0 : if (cap_set_proc(d) < 0)
329 [ # # ]: 0 : return log_error_errno(errno, "Failed to increase capabilities: %m");
330 : : }
331 : :
332 : 0 : return 0;
333 : : }
334 : :
335 : 4 : int drop_capability(cap_value_t cv) {
336 : 4 : _cleanup_cap_free_ cap_t tmp_cap = NULL;
337 : :
338 : 4 : tmp_cap = cap_get_proc();
339 [ - + ]: 4 : if (!tmp_cap)
340 : 0 : return -errno;
341 : :
342 [ + - + - ]: 8 : if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) ||
343 [ - + ]: 8 : (cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) ||
344 : 4 : (cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0))
345 : 0 : return -errno;
346 : :
347 [ - + ]: 4 : if (cap_set_proc(tmp_cap) < 0)
348 : 0 : return -errno;
349 : :
350 : 4 : return 0;
351 : : }
352 : :
353 : 4 : bool ambient_capabilities_supported(void) {
354 : : static int cache = -1;
355 : :
356 [ - + ]: 4 : if (cache >= 0)
357 : 0 : return cache;
358 : :
359 : : /* If PR_CAP_AMBIENT returns something valid, or an unexpected error code we assume that ambient caps are
360 : : * available. */
361 : :
362 [ - + ]: 4 : cache = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_KILL, 0, 0) >= 0 ||
363 [ # # # # ]: 0 : !IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS);
364 : :
365 : 4 : return cache;
366 : : }
367 : :
368 : 0 : bool capability_quintet_mangle(CapabilityQuintet *q) {
369 : : unsigned long i;
370 : 0 : uint64_t combined, drop = 0;
371 : : bool ambient_supported;
372 : :
373 [ # # ]: 0 : assert(q);
374 : :
375 : 0 : combined = q->effective | q->bounding | q->inheritable | q->permitted;
376 : :
377 : 0 : ambient_supported = q->ambient != (uint64_t) -1;
378 [ # # ]: 0 : if (ambient_supported)
379 : 0 : combined |= q->ambient;
380 : :
381 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
382 : 0 : unsigned long bit = UINT64_C(1) << i;
383 [ # # ]: 0 : if (!FLAGS_SET(combined, bit))
384 : 0 : continue;
385 : :
386 [ # # ]: 0 : if (prctl(PR_CAPBSET_READ, i) > 0)
387 : 0 : continue;
388 : :
389 : 0 : drop |= bit;
390 : :
391 [ # # ]: 0 : log_debug("Not in the current bounding set: %s", capability_to_name(i));
392 : : }
393 : :
394 : 0 : q->effective &= ~drop;
395 : 0 : q->bounding &= ~drop;
396 : 0 : q->inheritable &= ~drop;
397 : 0 : q->permitted &= ~drop;
398 : :
399 [ # # ]: 0 : if (ambient_supported)
400 : 0 : q->ambient &= ~drop;
401 : :
402 : 0 : return drop != 0; /* Let the caller know we changed something */
403 : : }
404 : :
405 : 0 : int capability_quintet_enforce(const CapabilityQuintet *q) {
406 : 0 : _cleanup_cap_free_ cap_t c = NULL, modified = NULL;
407 : : int r;
408 : :
409 [ # # ]: 0 : if (q->ambient != (uint64_t) -1) {
410 : : unsigned long i;
411 : 0 : bool changed = false;
412 : :
413 : 0 : c = cap_get_proc();
414 [ # # ]: 0 : if (!c)
415 : 0 : return -errno;
416 : :
417 : : /* In order to raise the ambient caps set we first need to raise the matching inheritable + permitted
418 : : * cap */
419 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
420 : 0 : uint64_t m = UINT64_C(1) << i;
421 : 0 : cap_value_t cv = (cap_value_t) i;
422 : : cap_flag_value_t old_value_inheritable, old_value_permitted;
423 : :
424 [ # # ]: 0 : if ((q->ambient & m) == 0)
425 : 0 : continue;
426 : :
427 [ # # ]: 0 : if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value_inheritable) < 0)
428 : 0 : return -errno;
429 [ # # ]: 0 : if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value_permitted) < 0)
430 : 0 : return -errno;
431 : :
432 [ # # # # ]: 0 : if (old_value_inheritable == CAP_SET && old_value_permitted == CAP_SET)
433 : 0 : continue;
434 : :
435 [ # # ]: 0 : if (cap_set_flag(c, CAP_INHERITABLE, 1, &cv, CAP_SET) < 0)
436 : 0 : return -errno;
437 [ # # ]: 0 : if (cap_set_flag(c, CAP_PERMITTED, 1, &cv, CAP_SET) < 0)
438 : 0 : return -errno;
439 : :
440 : 0 : changed = true;
441 : : }
442 : :
443 [ # # ]: 0 : if (changed)
444 [ # # ]: 0 : if (cap_set_proc(c) < 0)
445 : 0 : return -errno;
446 : :
447 : 0 : r = capability_ambient_set_apply(q->ambient, false);
448 [ # # ]: 0 : if (r < 0)
449 : 0 : return r;
450 : : }
451 : :
452 [ # # # # : 0 : if (q->inheritable != (uint64_t) -1 || q->permitted != (uint64_t) -1 || q->effective != (uint64_t) -1) {
# # ]
453 : 0 : bool changed = false;
454 : : unsigned long i;
455 : :
456 [ # # ]: 0 : if (!c) {
457 : 0 : c = cap_get_proc();
458 [ # # ]: 0 : if (!c)
459 : 0 : return -errno;
460 : : }
461 : :
462 [ # # ]: 0 : for (i = 0; i <= cap_last_cap(); i++) {
463 : 0 : uint64_t m = UINT64_C(1) << i;
464 : 0 : cap_value_t cv = (cap_value_t) i;
465 : :
466 [ # # ]: 0 : if (q->inheritable != (uint64_t) -1) {
467 : : cap_flag_value_t old_value, new_value;
468 : :
469 [ # # ]: 0 : if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value) < 0) {
470 [ # # ]: 0 : if (errno == EINVAL) /* If the kernel knows more caps than this
471 : : * version of libcap, then this will return
472 : : * EINVAL. In that case, simply ignore it,
473 : : * pretend it doesn't exist. */
474 : 0 : continue;
475 : :
476 : 0 : return -errno;
477 : : }
478 : :
479 : 0 : new_value = (q->inheritable & m) ? CAP_SET : CAP_CLEAR;
480 : :
481 [ # # ]: 0 : if (old_value != new_value) {
482 : 0 : changed = true;
483 : :
484 [ # # ]: 0 : if (cap_set_flag(c, CAP_INHERITABLE, 1, &cv, new_value) < 0)
485 : 0 : return -errno;
486 : : }
487 : : }
488 : :
489 [ # # ]: 0 : if (q->permitted != (uint64_t) -1) {
490 : : cap_flag_value_t old_value, new_value;
491 : :
492 [ # # ]: 0 : if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value) < 0) {
493 [ # # ]: 0 : if (errno == EINVAL)
494 : 0 : continue;
495 : :
496 : 0 : return -errno;
497 : : }
498 : :
499 : 0 : new_value = (q->permitted & m) ? CAP_SET : CAP_CLEAR;
500 : :
501 [ # # ]: 0 : if (old_value != new_value) {
502 : 0 : changed = true;
503 : :
504 [ # # ]: 0 : if (cap_set_flag(c, CAP_PERMITTED, 1, &cv, new_value) < 0)
505 : 0 : return -errno;
506 : : }
507 : : }
508 : :
509 [ # # ]: 0 : if (q->effective != (uint64_t) -1) {
510 : : cap_flag_value_t old_value, new_value;
511 : :
512 [ # # ]: 0 : if (cap_get_flag(c, cv, CAP_EFFECTIVE, &old_value) < 0) {
513 [ # # ]: 0 : if (errno == EINVAL)
514 : 0 : continue;
515 : :
516 : 0 : return -errno;
517 : : }
518 : :
519 : 0 : new_value = (q->effective & m) ? CAP_SET : CAP_CLEAR;
520 : :
521 [ # # ]: 0 : if (old_value != new_value) {
522 : 0 : changed = true;
523 : :
524 [ # # ]: 0 : if (cap_set_flag(c, CAP_EFFECTIVE, 1, &cv, new_value) < 0)
525 : 0 : return -errno;
526 : : }
527 : : }
528 : : }
529 : :
530 [ # # ]: 0 : if (changed) {
531 : : /* In order to change the bounding caps, we need to keep CAP_SETPCAP for a bit
532 : : * longer. Let's add it to our list hence for now. */
533 [ # # ]: 0 : if (q->bounding != (uint64_t) -1) {
534 : 0 : cap_value_t cv = CAP_SETPCAP;
535 : :
536 : 0 : modified = cap_dup(c);
537 [ # # ]: 0 : if (!modified)
538 : 0 : return -ENOMEM;
539 : :
540 [ # # ]: 0 : if (cap_set_flag(modified, CAP_PERMITTED, 1, &cv, CAP_SET) < 0)
541 : 0 : return -errno;
542 [ # # ]: 0 : if (cap_set_flag(modified, CAP_EFFECTIVE, 1, &cv, CAP_SET) < 0)
543 : 0 : return -errno;
544 : :
545 [ # # ]: 0 : if (cap_compare(modified, c) == 0) {
546 : : /* No change? then drop this nonsense again */
547 : 0 : cap_free(modified);
548 : 0 : modified = NULL;
549 : : }
550 : : }
551 : :
552 : : /* Now, let's enforce the caps for the first time. Note that this is where we acquire
553 : : * caps in any of the sets we currently don't have. We have to do this before
554 : : * dropping the bounding caps below, since at that point we can never acquire new
555 : : * caps in inherited/permitted/effective anymore, but only lose them. */
556 [ # # # # ]: 0 : if (cap_set_proc(modified ?: c) < 0)
557 : 0 : return -errno;
558 : : }
559 : : }
560 : :
561 [ # # ]: 0 : if (q->bounding != (uint64_t) -1) {
562 : 0 : r = capability_bounding_set_drop(q->bounding, false);
563 [ # # ]: 0 : if (r < 0)
564 : 0 : return r;
565 : : }
566 : :
567 : : /* If needed, let's now set the caps again, this time in the final version, which differs from what
568 : : * we have already set only in the CAP_SETPCAP bit, which we needed for dropping the bounding
569 : : * bits. This call only undoes bits and doesn't acquire any which means the bounding caps don't
570 : : * matter. */
571 [ # # ]: 0 : if (modified)
572 [ # # ]: 0 : if (cap_set_proc(c) < 0)
573 : 0 : return -errno;
574 : :
575 : 0 : return 0;
576 : : }
|