Coverage Report

Created: 2019-06-19 13:33

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