• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 29295695877

13 Jul 2026 11:19PM UTC coverage: 72.94% (-0.05%) from 72.994%
29295695877

push

github

web-flow
userdb: suppress userdb queries for backends indicating uid/gid/name range info via xattrs on entrypoint sockets (#42961)

Let's optimize userdb queries a bit: by encoding the covered UID/GID
ranges and user/group name patterns on the varlink entrypoint sockets
for userdb backends we can make them wake up less and reduce the work
triggered by queries.

81 of 92 new or added lines in 5 files covered. (88.04%)

5898 existing lines in 76 files now uncovered.

345436 of 473591 relevant lines covered (72.94%)

1320061.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.07
/src/basic/capability-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdatomic.h>
4
#include <stdio.h>
5
#include <sys/prctl.h> /* IWYU pragma: keep */
6
#include <sys/syscall.h>
7
#include <unistd.h>
8

9
#include "alloc-util.h"
10
#include "bitfield.h"
11
#include "capability-list.h"
12
#include "capability-util.h"
13
#include "errno-util.h"
14
#include "fd-util.h"
15
#include "fileio.h"
16
#include "log.h"
17
#include "parse-util.h"
18
#include "pidref.h"
19
#include "process-util.h"
20
#include "stat-util.h"
21
#include "user-util.h"
22

23
int capability_get(CapabilityQuintet *ret) {
199,111✔
24
        assert(ret);
199,111✔
25

26
        struct __user_cap_header_struct hdr = {
398,222✔
27
                .version = _LINUX_CAPABILITY_VERSION_3,
28
                .pid = getpid_cached(),
199,111✔
29
        };
30

31
        assert_cc(_LINUX_CAPABILITY_U32S_3 == 2);
199,111✔
32
        struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3];
199,111✔
33
        if (syscall(SYS_capget, &hdr, data) < 0)
199,111✔
34
                return -errno;
×
35

36
        *ret = (CapabilityQuintet) {
199,111✔
37
                .effective = (uint64_t) data[0].effective | ((uint64_t) data[1].effective << 32),
199,111✔
38
                .bounding = UINT64_MAX,
39
                .inheritable = (uint64_t) data[0].inheritable | ((uint64_t) data[1].inheritable << 32),
199,111✔
40
                .permitted = (uint64_t) data[0].permitted | ((uint64_t) data[1].permitted << 32),
199,111✔
41
                .ambient = UINT64_MAX,
42
        };
43
        return 0;
199,111✔
44
}
45

46
static int capability_apply(const CapabilityQuintet *q) {
7,827✔
47
        assert(q);
7,827✔
48

49
        struct __user_cap_header_struct hdr = {
15,654✔
50
                .version = _LINUX_CAPABILITY_VERSION_3,
51
                .pid = getpid_cached(),
7,827✔
52
        };
53

54
        struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3] = {
7,827✔
55
                {
56
                        .effective = (uint32_t) (q->effective & UINT32_MAX),
7,827✔
57
                        .inheritable = (uint32_t) (q->inheritable & UINT32_MAX),
7,827✔
58
                        .permitted = (uint32_t) (q->permitted & UINT32_MAX),
7,827✔
59
                },
60
                {
61
                        .effective = (uint32_t) (q->effective >> 32),
7,827✔
62
                        .inheritable = (uint32_t) (q->inheritable >> 32),
7,827✔
63
                        .permitted = (uint32_t) (q->permitted >> 32),
7,827✔
64
                },
65
        };
66
        return RET_NERRNO(syscall(SYS_capset, &hdr, data));
7,827✔
67
}
68

69
unsigned cap_last_cap(void) {
2,469,325✔
70
        static atomic_int saved = INT_MAX;
2,469,325✔
71
        int r, c;
2,469,325✔
72

73
        c = saved;
2,469,325✔
74
        if (c != INT_MAX)
2,469,325✔
75
                return c;
2,469,325✔
76

77
        /* Available since linux-3.2 */
78
        _cleanup_free_ char *content = NULL;
13,453✔
79
        r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content);
13,453✔
80
        if (r < 0)
13,453✔
81
                log_debug_errno(r, "Failed to read /proc/sys/kernel/cap_last_cap, ignoring: %m");
×
82
        else {
83
                r = safe_atoi(content, &c);
13,453✔
84
                if (r < 0)
13,453✔
85
                        log_debug_errno(r, "Failed to parse /proc/sys/kernel/cap_last_cap, ignoring: %m");
×
86
                else {
87
                        if (c > CAP_LIMIT) /* Safety for the future: if one day the kernel learns more than
13,453✔
88
                                            * 64 caps, then we are in trouble (since we, as much userspace
89
                                            * and kernel space store capability masks in uint64_t types). We
90
                                            * also want to use UINT64_MAX as marker for "unset". Hence let's
91
                                            * hence protect ourselves against that and always cap at 62 for
92
                                            * now. */
93
                                c = CAP_LIMIT;
×
94

95
                        saved = c;
13,453✔
96
                        return c;
13,453✔
97
                }
98
        }
99

100
        /* Fall back to syscall-probing for pre linux-3.2, or where /proc/ is not mounted */
101
        unsigned long p = (unsigned long) MIN(CAP_LAST_CAP, CAP_LIMIT);
×
102

103
        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) < 0) {
×
104

105
                /* Hmm, look downwards, until we find one that works */
106
                for (p--; p > 0; p--)
×
107
                        if (prctl_safe(PR_CAPBSET_READ, p, 0, 0, 0) >= 0)
×
108
                                break;
109

110
        } else {
111

112
                /* Hmm, look upwards, until we find one that doesn't work */
113
                for (; p < CAP_LIMIT; p++)
×
114
                        if (prctl_safe(PR_CAPBSET_READ, p+1, 0, 0, 0) < 0)
×
115
                                break;
116
        }
117

118
        c = (int) p;
×
119
        saved = c;
×
120
        return c;
×
121
}
122

123
int have_effective_cap(unsigned cap) {
187,641✔
124
        CapabilityQuintet q;
187,641✔
125
        int r;
187,641✔
126

127
        assert(cap <= CAP_LIMIT);
187,641✔
128

129
        r = capability_get(&q);
187,641✔
130
        if (r < 0)
187,641✔
131
                return r;
187,641✔
132

133
        return BIT_SET(q.effective, cap);
187,641✔
134
}
135

136
int have_inheritable_cap(unsigned cap) {
2✔
137
        CapabilityQuintet q;
2✔
138
        int r;
2✔
139

140
        assert(cap <= CAP_LIMIT);
2✔
141

142
        r = capability_get(&q);
2✔
143
        if (r < 0)
2✔
144
                return r;
2✔
145

146
        return BIT_SET(q.inheritable, cap);
2✔
147
}
148

149
int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
24,837✔
150
        int r;
24,837✔
151

152
        /* Remove capabilities requested in ambient set, but not in the bounding set */
153
        for (unsigned i = 0; i <= cap_last_cap(); i++) {
1,043,154✔
154
                if (!BIT_SET(set, i))
1,018,317✔
155
                        continue;
1,010,810✔
156

157
                r = prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0);
7,507✔
158
                if (r < 0)
7,507✔
159
                        return r;
160
                if (r != 1) {
7,507✔
161
                        log_debug("Ambient capability %s requested but missing from bounding set, suppressing automatically.",
53✔
162
                                  capability_to_name(i));
163
                        CLEAR_BIT(set, i);
53✔
164
                }
165
        }
166

167
        /* Add the capabilities to the ambient set (an possibly also the inheritable set) */
168

169
        if (also_inherit) {
24,837✔
170
                CapabilityQuintet q;
767✔
171

172
                r = capability_get(&q);
767✔
173
                if (r < 0)
767✔
UNCOV
174
                        return r;
×
175

176
                q.inheritable = set;
767✔
177

178
                r = capability_apply(&q);
767✔
179
                if (r < 0)
767✔
180
                        return r;
181
        }
182

183
        for (unsigned i = 0; i <= cap_last_cap(); i++)
1,043,154✔
184
                if (BIT_SET(set, i)) {
1,018,317✔
185
                        /* Add the capability to the ambient set. */
186
                        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0);
7,454✔
187
                        if (r < 0)
7,454✔
188
                                return r;
189
                } else {
190
                        /* Drop the capability so we don't inherit capabilities we didn't ask for. */
191
                        r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
1,010,863✔
192
                        if (r < 0)
1,010,863✔
193
                                return r;
194
                        if (r > 0) {
1,010,863✔
195
                                r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, i, 0, 0);
625✔
196
                                if (r < 0)
625✔
197
                                        return r;
198
                        }
199
                }
200

201
        return 0;
202
}
203

204
int capability_gain_cap_setpcap(void) {
3,742✔
205
        CapabilityQuintet q;
3,742✔
206
        int r;
3,742✔
207

208
        r = capability_get(&q);
3,742✔
209
        if (r < 0)
3,742✔
210
                return r;
3,742✔
211

212
        if (BIT_SET(q.effective, CAP_SETPCAP))
3,742✔
213
                return 1; /* We already have capability. */
214

215
        SET_BIT(q.effective, CAP_SETPCAP);
105✔
216

217
        r = capability_apply(&q);
105✔
218
        if (r < 0) {
105✔
219
                /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this
220
                 * just means we'll fail later, when we actually intend to drop some capabilities or try to
221
                 * set securebits. */
UNCOV
222
                log_debug_errno(r, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m");
×
223
                return 0;
224
        }
225

226
        return 1; /* acquired */
227
}
228

229
int capability_bounding_set_drop(uint64_t keep, bool right_now) {
2,916✔
230
        int k, r;
2,916✔
231

232
        /* If we are run as PID 1 we will lack CAP_SETPCAP by default in the effective set (yes, the kernel
233
         * drops that when executing init!), so get it back temporarily so that we can call PR_CAPBSET_DROP. */
234

235
        CapabilityQuintet q;
2,916✔
236
        r = capability_get(&q);
2,916✔
237
        if (r < 0)
2,916✔
238
                return r;
2,916✔
239
        CapabilityQuintet saved = q;
2,916✔
240

241
        r = capability_gain_cap_setpcap();
2,916✔
242
        if (r < 0)
2,916✔
243
                return r;
244

245
        for (unsigned i = 0; i <= cap_last_cap(); i++) {
122,472✔
246
                if (BIT_SET(keep, i))
119,556✔
247
                        continue;
31,541✔
248

249
                /* Drop it from the bounding set */
250
                r = prctl_safe(PR_CAPBSET_DROP, i, 0, 0, 0);
88,015✔
251
                if (r < 0) {
88,015✔
252
                        /* If dropping the capability failed, let's see if we didn't have it in the first
253
                         * place. If so, continue anyway, as dropping a capability we didn't have in the
254
                         * first place doesn't really matter anyway. */
UNCOV
255
                        if (prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0) != 0)
×
UNCOV
256
                                goto finish;
×
257
                }
258

259
                /* Also drop it from the inheritable set, so that anything we exec() loses the capability for
260
                 * good. */
261
                CLEAR_BIT(q.inheritable, i);
88,015✔
262

263
                /* If we shall apply this right now drop it also from our own capability sets. */
264
                if (right_now) {
88,015✔
265
                        CLEAR_BIT(q.effective, i);
3,676✔
266
                        CLEAR_BIT(q.permitted, i);
3,676✔
267
                }
268
        }
269

270
        r = 0;
271

272
finish:
2,916✔
273
        k = capability_apply(&q);
2,916✔
274
        if (k < 0)
2,916✔
275
                /* If there are no actual changes anyway then let's ignore this error. */
UNCOV
276
                if (!capability_quintet_equal(&q, &saved))
×
277
                        return k;
×
278

279
        return r;
280
}
281

UNCOV
282
static int drop_from_file(const char *fn, uint64_t keep) {
×
283
        _cleanup_free_ char *p = NULL;
×
284
        uint64_t current, after;
×
UNCOV
285
        uint32_t hi, lo;
×
UNCOV
286
        int r, k;
×
287

288
        r = read_one_line_file(fn, &p);
×
UNCOV
289
        if (r < 0)
×
290
                return r;
291

292
        k = sscanf(p, "%" PRIu32 " %" PRIu32, &lo, &hi);
×
UNCOV
293
        if (k != 2)
×
294
                return -EIO;
295

UNCOV
296
        current = (uint64_t) lo | ((uint64_t) hi << 32);
×
297
        after = current & keep;
×
298

UNCOV
299
        if (current == after)
×
300
                return 0;
301

UNCOV
302
        lo = after & UINT32_MAX;
×
303
        hi = (after >> 32) & UINT32_MAX;
×
304

UNCOV
305
        return write_string_filef(fn, 0, "%" PRIu32 " %" PRIu32, lo, hi);
×
306
}
307

UNCOV
308
int capability_bounding_set_drop_usermode(uint64_t keep) {
×
UNCOV
309
        int r;
×
310

311
        r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep);
×
312
        if (r < 0)
×
313
                return r;
314

UNCOV
315
        r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep);
×
UNCOV
316
        if (r < 0)
×
UNCOV
317
                return r;
×
318

319
        return r;
320
}
321

322
int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) {
28✔
323
        int r;
28✔
324

325
        /* Unfortunately we cannot leave privilege dropping to PID 1 here, since we want to run as user but
326
         * want to keep some capabilities. Since file capabilities have been introduced this cannot be done
327
         * across exec() anymore, unless our binary has the capability configured in the file system, which
328
         * we want to avoid. */
329

330
        if (setresgid(gid, gid, gid) < 0)
28✔
331
                return log_error_errno(errno, "Failed to change group ID: %m");
1✔
332

333
        r = maybe_setgroups(/* size= */ 0, /* list= */ NULL);
27✔
334
        if (r < 0)
27✔
335
                return log_error_errno(r, "Failed to drop auxiliary groups list: %m");
1✔
336

337
        /* Ensure we keep the permitted caps across the setresuid(). Note that we do this even if we actually
338
         * don't want to keep any capabilities, since we want to be able to drop them from the bounding set
339
         * too, and we can only do that if we have capabilities. */
340
        r = prctl_safe(PR_SET_KEEPCAPS, 1, 0, 0, 0);
26✔
341
        if (r < 0)
26✔
342
                return log_error_errno(r, "Failed to enable keep capabilities flag: %m");
×
343

344
        if (setresuid(uid, uid, uid) < 0)
26✔
UNCOV
345
                return log_error_errno(errno, "Failed to change user ID: %m");
×
346

347
        r = prctl_safe(PR_SET_KEEPCAPS, 0, 0, 0, 0);
26✔
348
        if (r < 0)
26✔
UNCOV
349
                return log_error_errno(r, "Failed to disable keep capabilities flag: %m");
×
350

351
        /* Drop all caps from the bounding set (as well as the inheritable/permitted/effective sets), except
352
         * the ones we want to keep */
353
        r = capability_bounding_set_drop(keep_capabilities, /* right_now= */ true);
26✔
354
        if (r < 0)
26✔
UNCOV
355
                return log_error_errno(r, "Failed to drop capabilities: %m");
×
356

357
        /* Now upgrade the permitted caps we still kept to effective caps */
358
        if (keep_capabilities != 0) {
26✔
359
                CapabilityQuintet q = {
4✔
360
                        .effective = keep_capabilities,
361
                        .permitted = keep_capabilities,
362
                };
363

364
                r = capability_apply(&q);
4✔
365
                if (r < 0)
4✔
UNCOV
366
                        return log_error_errno(r, "Failed to increase capabilities: %m");
×
367
        }
368

369
        return 0;
370
}
371

372
static int change_capability(unsigned cap, bool b) {
3,915✔
373
        CapabilityQuintet q;
3,915✔
374
        int r;
3,915✔
375

376
        assert(cap <= CAP_LIMIT);
3,915✔
377

378
        r = capability_get(&q);
3,915✔
379
        if (r < 0)
3,915✔
380
                return r;
3,915✔
381

382
        if (b) {
3,915✔
383
                SET_BIT(q.effective, cap);
1,506✔
384
                SET_BIT(q.permitted, cap);
1,506✔
385
                SET_BIT(q.inheritable, cap);
1,506✔
386
        } else {
387
                CLEAR_BIT(q.effective, cap);
2,409✔
388
                CLEAR_BIT(q.permitted, cap);
2,409✔
389
                CLEAR_BIT(q.inheritable, cap);
2,409✔
390
        }
391

392
        return capability_apply(&q);
3,915✔
393
}
394

395
int drop_capability(unsigned cap) {
2,409✔
396
        return change_capability(cap, false);
2,409✔
397
}
398

399
int keep_capability(unsigned cap) {
1,506✔
400
        return change_capability(cap, true);
1,506✔
401
}
402

403
bool capability_quintet_mangle(CapabilityQuintet *q) {
125✔
404
        uint64_t combined, drop = 0;
125✔
405

406
        assert(q);
125✔
407

408
        combined = q->effective | q->bounding | q->inheritable | q->permitted | q->ambient;
125✔
409

410
        for (unsigned i = 0; i <= cap_last_cap(); i++) {
5,250✔
411
                if (!BIT_SET(combined, i))
5,125✔
412
                        continue;
1,847✔
413

414
                if (prctl_safe(PR_CAPBSET_READ, i, 0, 0, 0) > 0)
3,278✔
415
                        continue;
3,278✔
416

UNCOV
417
                SET_BIT(drop, i);
×
418

UNCOV
419
                log_debug("Dropping capability not in the current bounding set: %s", capability_to_name(i));
×
420
        }
421

422
        q->effective &= ~drop;
125✔
423
        q->bounding &= ~drop;
125✔
424
        q->inheritable &= ~drop;
125✔
425
        q->permitted &= ~drop;
125✔
426
        q->ambient &= ~drop;
125✔
427

428
        return drop != 0; /* Let the caller know we changed something */
125✔
429
}
430

431
int capability_quintet_enforce(const CapabilityQuintet *q) {
125✔
432
        CapabilityQuintet c;
125✔
433
        bool modified = false;
125✔
434
        int r;
125✔
435

436
        assert(q);
125✔
437

438
        if (q->ambient != CAP_MASK_UNSET ||
125✔
UNCOV
439
            q->inheritable != CAP_MASK_UNSET ||
×
UNCOV
440
            q->permitted != CAP_MASK_UNSET ||
×
UNCOV
441
            q->effective != CAP_MASK_UNSET) {
×
442
                r = capability_get(&c);
125✔
443
                if (r < 0)
125✔
444
                        return r;
125✔
445
        }
446

447
        if (q->ambient != CAP_MASK_UNSET) {
125✔
448
                /* In order to raise the ambient caps set we first need to raise the matching
449
                 * inheritable + permitted cap */
450
                if (!FLAGS_SET(c.permitted, q->ambient) ||
125✔
451
                    !FLAGS_SET(c.inheritable, q->ambient)) {
125✔
452

453
                        c.permitted |= q->ambient;
1✔
454
                        c.inheritable |= q->ambient;
1✔
455

456
                        r = capability_apply(&c);
1✔
457
                        if (r < 0)
1✔
458
                                return r;
459
                }
460

461
                r = capability_ambient_set_apply(q->ambient, /* also_inherit= */ false);
125✔
462
                if (r < 0)
125✔
463
                        return r;
464
        }
465

466
        if (q->inheritable != CAP_MASK_UNSET || q->permitted != CAP_MASK_UNSET || q->effective != CAP_MASK_UNSET) {
125✔
467
                if (!FLAGS_SET(c.effective, q->effective) ||
124✔
468
                    !FLAGS_SET(c.permitted, q->permitted) ||
124✔
469
                    !FLAGS_SET(c.inheritable, q->inheritable)) {
124✔
470

471
                        c.effective |= q->effective;
119✔
472
                        c.permitted |= q->permitted;
119✔
473
                        c.inheritable |= q->inheritable;
119✔
474

475
                        /* Now, let's enforce the caps for the first time. Note that this is where we acquire
476
                         * caps in any of the sets we currently don't have. We have to do this before
477
                         * dropping the bounding caps below, since at that point we can never acquire new
478
                         * caps in inherited/permitted/effective anymore, but only lose them.
479
                         *
480
                         * In order to change the bounding caps, we need to keep CAP_SETPCAP for a bit
481
                         * longer. Let's add it to our list hence for now. */
482
                        if (q->bounding != CAP_MASK_UNSET &&
119✔
483
                            (!BIT_SET(c.effective, CAP_SETPCAP) || !BIT_SET(c.permitted, CAP_SETPCAP))) {
119✔
484
                                CapabilityQuintet tmp = c;
×
485

UNCOV
486
                                SET_BIT(c.effective, CAP_SETPCAP);
×
UNCOV
487
                                SET_BIT(c.permitted, CAP_SETPCAP);
×
488

UNCOV
489
                                modified = true;
×
490

UNCOV
491
                                r = capability_apply(&tmp);
×
492
                        } else
493
                                r = capability_apply(&c);
119✔
494
                        if (r < 0)
119✔
495
                                return r;
496
                }
497
        }
498

499
        if (q->bounding != CAP_MASK_UNSET) {
125✔
500
                r = capability_bounding_set_drop(q->bounding, /* right_now= */ false);
124✔
501
                if (r < 0)
124✔
502
                        return r;
503
        }
504

505
        /* If needed, let's now set the caps again, this time in the final version, which differs from what
506
         * we have already set only in the CAP_SETPCAP bit, which we needed for dropping the bounding
507
         * bits. This call only undoes bits and doesn't acquire any which means the bounding caps don't
508
         * matter. */
509
        if (modified) {
125✔
UNCOV
510
                r = capability_apply(&c);
×
UNCOV
511
                if (r < 0)
×
UNCOV
512
                        return r;
×
513
        }
514

515
        return 0;
516
}
517

518
int capability_get_ambient(uint64_t *ret) {
901✔
519
        uint64_t a = 0;
901✔
520
        int r;
901✔
521

522
        assert(ret);
901✔
523

524
        for (unsigned i = 0; i <= cap_last_cap(); i++) {
37,842✔
525
                r = prctl_safe(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
36,941✔
526
                if (r < 0)
36,941✔
527
                        return r;
528
                if (r > 0)
36,941✔
529
                        SET_BIT(a, i);
139✔
530
        }
531

532
        *ret = a;
901✔
533
        return 1;
901✔
534
}
535

536
int pidref_get_capability(const PidRef *pidref, CapabilityQuintet *ret) {
17,954✔
537
        int r;
17,954✔
538

539
        if (!pidref_is_set(pidref))
17,954✔
540
                return -ESRCH;
17,954✔
541
        if (pidref_is_remote(pidref))
17,954✔
542
                return -EREMOTE;
543

544
        const char *path = procfs_file_alloca(pidref->pid, "status");
17,954✔
545
        _cleanup_fclose_ FILE *f = fopen(path, "re");
35,908✔
546
        if (!f) {
17,954✔
547
                if (errno == ENOENT && proc_mounted() == 0)
3,704✔
548
                        return -ENOSYS;
549

550
                return -errno;
3,704✔
551
        }
552

553
        CapabilityQuintet q = CAPABILITY_QUINTET_NULL;
14,250✔
554
        for (;;) {
1,738,972✔
555
                _cleanup_free_ char *line = NULL;
862,361✔
556

557
                r = read_line(f, LONG_LINE_MAX, &line);
876,611✔
558
                if (r < 0)
876,611✔
559
                        return r;
560
                if (r == 0)
876,611✔
561
                        break;
562

563
                static const struct {
564
                        const char *field;
565
                        size_t offset;
566
                } fields[] = {
567
                        { "CapBnd:", offsetof(CapabilityQuintet, bounding)    },
568
                        { "CapInh:", offsetof(CapabilityQuintet, inheritable) },
569
                        { "CapPrm:", offsetof(CapabilityQuintet, permitted)   },
570
                        { "CapEff:", offsetof(CapabilityQuintet, effective)   },
571
                        { "CapAmb:", offsetof(CapabilityQuintet, ambient)     },
572
                };
573

574
                FOREACH_ELEMENT(i, fields) {
5,174,166✔
575

576
                        const char *p = first_word(line, i->field);
4,311,805✔
577
                        if (!p)
4,311,805✔
578
                                continue;
4,240,555✔
579

580
                        uint64_t *v = (uint64_t*) ((uint8_t*) &q + i->offset);
71,250✔
581

582
                        if (*v != CAP_MASK_UNSET)
71,250✔
583
                                return -EBADMSG;
584

585
                        r = safe_atoux64(p, v);
71,250✔
586
                        if (r < 0)
71,250✔
587
                                return r;
588

589
                        if (*v == CAP_MASK_UNSET)
71,250✔
590
                                return -EBADMSG;
591
                }
592
        }
593

594
        if (!capability_quintet_is_fully_set(&q))
14,250✔
595
                return -EBADMSG;
596

597
        r = pidref_verify(pidref);
14,250✔
598
        if (r < 0)
14,250✔
599
                return r;
600

601
        if (ret)
14,250✔
602
                *ret = q;
14,250✔
603

604
        return 0;
605
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc