1 /* libcap-ng.c --
2 * Copyright 2009-10 Red Hat Inc., Durham, North Carolina.
3 * All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Authors:
20 * Steve Grubb <sgrubb@redhat.com>
21 */
22
23 #include "config.h"
24 #include "cap-ng.h"
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdio_ext.h>
29 #include <stdlib.h>
30 #include <sys/prctl.h>
31 #include <grp.h>
32 #include <sys/stat.h>
33 #include <stdarg.h>
34 #include <errno.h>
35 #include <byteswap.h>
36 #ifdef HAVE_SYSCALL_H
37 #include <sys/syscall.h>
38 #endif
39 #ifdef HAVE_LINUX_SECUREBITS_H
40 #include <linux/securebits.h>
41 #endif
42
43 /*
44 * Some milestones of when things became available:
45 * 2.6.24 kernel XATTR_NAME_CAPS
46 * 2.6.25 kernel PR_CAPBSET_DROP, CAPABILITY_VERSION_2
47 * 2.6.26 kernel PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3
48 */
49
50 /* External syscall prototypes */
51 extern int capset(cap_user_header_t header, cap_user_data_t data);
52 extern int capget(cap_user_header_t header, const cap_user_data_t data);
53
54 // Local defines
55 #define MASK(x) (1U << (x))
56 #ifdef PR_CAPBSET_DROP
57 #define UPPER_MASK ~(unsigned)((~0U)<<(CAP_LAST_CAP-31))
58 #else
59 // For v1 systems UPPER_MASK will never be used
60 #define UPPER_MASK (unsigned)(~0U)
61 #endif
62
63 // Re-define cap_valid so its uniform between V1 and V3
64 #undef cap_valid
65 #define cap_valid(x) ((x) <= CAP_LAST_CAP)
66
67 // If we don't have the xattr library, then we can't
68 // compile-in file system capabilities
69 #ifndef HAVE_ATTR_XATTR_H
70 #undef VFS_CAP_U32
71 #endif
72
73 #ifdef VFS_CAP_U32
74 #include <attr/xattr.h>
75 #if __BYTE_ORDER == __BIG_ENDIAN
76 #define FIXUP(x) bswap_32(x)
77 #else
78 #define FIXUP(x) (x)
79 #endif
80 #endif
81
82 #ifndef _LINUX_CAPABILITY_VERSION_1
83 #define _LINUX_CAPABILITY_VERSION_1 0x19980330
84 #endif
85 #ifndef _LINUX_CAPABILITY_VERSION_2
86 #define _LINUX_CAPABILITY_VERSION_2 0x20071026
87 #endif
88 #ifndef _LINUX_CAPABILITY_VERSION_3
89 #define _LINUX_CAPABILITY_VERSION_3 0x20080522
90 #endif
91
92 // This public API went private in the 2.6.36 kernel - hope it never changes
93 #ifndef XATTR_CAPS_SUFFIX
94 #define XATTR_CAPS_SUFFIX "capability"
95 #endif
96 #ifndef XATTR_SECURITY_PREFIX
97 #define XATTR_SECURITY_PREFIX "security."
98 #endif
99 #ifndef XATTR_NAME_CAPS
100 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
101 #endif
102
103
104 /* Child processes can't get caps back */
105 #ifndef SECURE_NOROOT
106 #define SECURE_NOROOT 0
107 #endif
108 #ifndef SECURE_NOROOT_LOCKED
109 #define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
110 #endif
111 /* Setuid apps run by uid 0 don't get caps back */
112 #ifndef SECURE_NO_SETUID_FIXUP
113 #define SECURE_NO_SETUID_FIXUP 2
114 #endif
115 #ifndef SECURE_NO_SETUID_FIXUP_LOCKED
116 #define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
117 #endif
118
119 // States: new, allocated, initted, updated, applied
120 typedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT,
121 CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t;
122
123 // Create an easy data struct out of the kernel definitions
124 typedef union {
125 struct __user_cap_data_struct v1;
126 struct __user_cap_data_struct v3[2];
127 } cap_data_t;
128
129 // This struct keeps all state info
130 struct cap_ng
131 {
132 int cap_ver;
133 struct __user_cap_header_struct hdr;
134 cap_data_t data;
135 capng_states_t state;
136 __u32 bounds[2];
137 };
138
139 // Global variables with per thread uniqueness
140 static __thread struct cap_ng m = { 1,
141 {0, 0},
142 { {0, 0, 0} },
143 CAPNG_NEW,
144 {0, 0} };
145
146
init(void)147 static void init(void)
148 {
149 if (m.state != CAPNG_NEW)
150 return;
151
152 memset(&m.hdr, 0, sizeof(m.hdr));
153 (void)capget(&m.hdr, NULL); // Returns -EINVAL
154 if (m.hdr.version == _LINUX_CAPABILITY_VERSION_3 ||
155 m.hdr.version == _LINUX_CAPABILITY_VERSION_2) {
156 m.cap_ver = 3;
157 } else if (m.hdr.version == _LINUX_CAPABILITY_VERSION_1) {
158 m.cap_ver = 1;
159 } else {
160 m.state = CAPNG_ERROR;
161 return;
162 }
163
164 memset(&m.data, 0, sizeof(cap_data_t));
165 #ifdef HAVE_SYSCALL_H
166 m.hdr.pid = (unsigned)syscall(__NR_gettid);
167 #else
168 m.hdr.pid = (unsigned)getpid();
169 #endif
170 m.state = CAPNG_ALLOCATED;
171 }
172
capng_clear(capng_select_t set)173 void capng_clear(capng_select_t set)
174 {
175 if (m.state == CAPNG_NEW)
176 init();
177 if (m.state == CAPNG_ERROR)
178 return;
179
180 if (set & CAPNG_SELECT_CAPS)
181 memset(&m.data, 0, sizeof(cap_data_t));
182 #ifdef PR_CAPBSET_DROP
183 if (set & CAPNG_SELECT_BOUNDS)
184 memset(m.bounds, 0, sizeof(m.bounds));
185 #endif
186 m.state = CAPNG_INIT;
187 }
188
capng_fill(capng_select_t set)189 void capng_fill(capng_select_t set)
190 {
191 if (m.state == CAPNG_NEW)
192 init();
193 if (m.state == CAPNG_ERROR)
194 return;
195
196 if (set & CAPNG_SELECT_CAPS) {
197 if (m.cap_ver == 1) {
198 m.data.v1.effective = 0x7FFFFFFFU;
199 m.data.v1.permitted = 0x7FFFFFFFU;
200 m.data.v1.inheritable = 0;
201 } else {
202 m.data.v3[0].effective = 0xFFFFFFFFU;
203 m.data.v3[0].permitted = 0xFFFFFFFFU;
204 m.data.v3[0].inheritable = 0;
205 m.data.v3[1].effective = 0xFFFFFFFFU;
206 m.data.v3[1].permitted = 0xFFFFFFFFU;
207 m.data.v3[1].inheritable = 0;
208 }
209 }
210 #ifdef PR_CAPBSET_DROP
211 if (set & CAPNG_SELECT_BOUNDS) {
212 unsigned i;
213 for (i=0; i<sizeof(m.bounds)/sizeof(__u32); i++)
214 m.bounds[i] = 0xFFFFFFFFU;
215 }
216 #endif
217 m.state = CAPNG_INIT;
218 }
219
capng_setpid(int pid)220 void capng_setpid(int pid)
221 {
222 if (m.state == CAPNG_NEW)
223 init();
224 if (m.state == CAPNG_ERROR)
225 return;
226
227 m.hdr.pid = pid;
228 }
229
230 #ifdef PR_CAPBSET_DROP
get_bounding_set(void)231 static int get_bounding_set(void)
232 {
233 char buf[64];
234 FILE *f;
235
236 snprintf(buf, sizeof(buf), "/proc/%u/status", m.hdr.pid ? m.hdr.pid :
237 #ifdef HAVE_SYSCALL_H
238 (unsigned)syscall(__NR_gettid));
239 #else
240 (unsigned)getpid();
241 #endif
242 f = fopen(buf, "re");
243 if (f == NULL)
244 return -1;
245 __fsetlocking(f, FSETLOCKING_BYCALLER);
246 while (fgets(buf, sizeof(buf), f)) {
247 if (strncmp(buf, "CapB", 4))
248 continue;
249 sscanf(buf, "CapBnd: %08x%08x", &m.bounds[1], &m.bounds[0]);
250 fclose(f);
251 return 0;
252 }
253 fclose(f);
254 return -1;
255 }
256 #endif
257
capng_get_caps_process(void)258 int capng_get_caps_process(void)
259 {
260 int rc;
261
262 if (m.state == CAPNG_NEW)
263 init();
264 if (m.state == CAPNG_ERROR)
265 return -1;
266
267 rc = capget((cap_user_header_t)&m.hdr, (cap_user_data_t)&m.data);
268 if (rc == 0) {
269 m.state = CAPNG_INIT;
270 #ifdef PR_CAPBSET_DROP
271 rc = get_bounding_set();
272 if (rc < 0)
273 m.state = CAPNG_ERROR;
274 #endif
275 }
276
277 return rc;
278 }
279
280 #ifdef VFS_CAP_U32
load_data(const struct vfs_cap_data * filedata,int size)281 static int load_data(const struct vfs_cap_data *filedata, int size)
282 {
283 unsigned int magic;
284
285 if (m.cap_ver == 1)
286 return -1; // Should never get here but just in case
287
288 magic = FIXUP(filedata->magic_etc);
289 switch (magic & VFS_CAP_REVISION_MASK)
290 {
291 case VFS_CAP_REVISION_1:
292 m.cap_ver = 1;
293 if (size != XATTR_CAPS_SZ_1)
294 return -1;
295 break;
296 case VFS_CAP_REVISION_2:
297 m.cap_ver = 2;
298 if (size != XATTR_CAPS_SZ_2)
299 return -1;
300 break;
301 default:
302 return -1;
303 }
304
305 // Now stuff the data structures
306 m.data.v3[0].permitted = FIXUP(filedata->data[0].permitted);
307 m.data.v3[1].permitted = FIXUP(filedata->data[1].permitted);
308 m.data.v3[0].inheritable = FIXUP(filedata->data[0].inheritable);
309 m.data.v3[1].inheritable = FIXUP(filedata->data[1].inheritable);
310 if (magic & VFS_CAP_FLAGS_EFFECTIVE) {
311 m.data.v3[0].effective =
312 m.data.v3[0].permitted | m.data.v3[0].inheritable;
313 m.data.v3[1].effective =
314 m.data.v3[1].permitted | m.data.v3[1].inheritable;
315 } else {
316 m.data.v3[0].effective = 0;
317 m.data.v3[1].effective = 0;
318 }
319 return 0;
320 }
321 #endif
322
capng_get_caps_fd(int fd)323 int capng_get_caps_fd(int fd)
324 {
325 #ifndef VFS_CAP_U32
326 return -1;
327 #else
328 int rc;
329 struct vfs_cap_data filedata;
330
331 if (m.state == CAPNG_NEW)
332 init();
333 if (m.state == CAPNG_ERROR)
334 return -1;
335
336 rc = fgetxattr(fd, XATTR_NAME_CAPS, &filedata, sizeof(filedata));
337 if (rc <= 0)
338 return -1;
339
340 rc = load_data(&filedata, rc);
341 if (rc == 0)
342 m.state = CAPNG_INIT;
343
344 return rc;
345 #endif
346 }
347
v1_update(capng_act_t action,unsigned int capability,__u32 * data)348 static void v1_update(capng_act_t action, unsigned int capability, __u32 *data)
349 {
350 if (action == CAPNG_ADD)
351 *data |= MASK(capability);
352 else
353 *data &= ~(MASK(capability));
354 }
355
update_effective(capng_act_t action,unsigned int capability,unsigned int idx)356 static void update_effective(capng_act_t action, unsigned int capability,
357 unsigned int idx)
358 {
359 if (action == CAPNG_ADD)
360 m.data.v3[idx].effective |= MASK(capability);
361 else
362 m.data.v3[idx].effective &= ~(MASK(capability));
363 }
364
update_permitted(capng_act_t action,unsigned int capability,unsigned int idx)365 static void update_permitted(capng_act_t action, unsigned int capability,
366 unsigned int idx)
367 {
368 if (action == CAPNG_ADD)
369 m.data.v3[idx].permitted |= MASK(capability);
370 else
371 m.data.v3[idx].permitted &= ~(MASK(capability));
372 }
373
update_inheritable(capng_act_t action,unsigned int capability,unsigned int idx)374 static void update_inheritable(capng_act_t action, unsigned int capability,
375 unsigned int idx)
376 {
377 if (action == CAPNG_ADD)
378 m.data.v3[idx].inheritable |= MASK(capability);
379 else
380 m.data.v3[idx].inheritable &= ~(MASK(capability));
381 }
382
update_bounding_set(capng_act_t action,unsigned int capability,unsigned int idx)383 static void update_bounding_set(capng_act_t action, unsigned int capability,
384 unsigned int idx)
385 {
386 #ifdef PR_CAPBSET_DROP
387 if (action == CAPNG_ADD)
388 m.bounds[idx] |= MASK(capability);
389 else
390 m.bounds[idx] &= ~(MASK(capability));
391 #endif
392 }
393
capng_update(capng_act_t action,capng_type_t type,unsigned int capability)394 int capng_update(capng_act_t action, capng_type_t type, unsigned int capability)
395 {
396 // Before updating, we expect that the data is initialized to something
397 if (m.state < CAPNG_INIT)
398 return -1;
399 if (!cap_valid(capability)) {
400 errno = EINVAL;
401 return -1;
402 }
403
404 if (m.cap_ver == 1) {
405 if (CAPNG_EFFECTIVE & type)
406 v1_update(action, capability, &m.data.v1.effective);
407 if (CAPNG_PERMITTED & type)
408 v1_update(action, capability, &m.data.v1.permitted);
409 if (CAPNG_INHERITABLE & type)
410 v1_update(action, capability, &m.data.v1.inheritable);
411 } else {
412 int idx;
413
414 if (capability > 31) {
415 idx = capability>>5;
416 capability %= 32;
417 } else
418 idx = 0;
419
420 if (CAPNG_EFFECTIVE & type)
421 update_effective(action, capability, idx);
422 if (CAPNG_PERMITTED & type)
423 update_permitted(action, capability, idx);
424 if (CAPNG_INHERITABLE & type)
425 update_inheritable(action, capability, idx);
426 if (CAPNG_BOUNDING_SET & type)
427 update_bounding_set(action, capability, idx);
428 }
429
430 m.state = CAPNG_UPDATED;
431 return 0;
432 }
433
capng_updatev(capng_act_t action,capng_type_t type,unsigned int capability,...)434 int capng_updatev(capng_act_t action, capng_type_t type,
435 unsigned int capability, ...)
436 {
437 int rc;
438 unsigned int cap;
439 va_list ap;
440
441 rc = capng_update(action, type, capability);
442 if (rc)
443 return rc;
444 va_start(ap, capability);
445 cap = va_arg(ap, unsigned int);
446 while (cap_valid(cap)) {
447 rc = capng_update(action, type, cap);
448 if (rc)
449 break;
450 cap = va_arg(ap, unsigned int);
451 }
452 va_end(ap);
453
454 // See if planned exit or invalid
455 if (cap == (unsigned)-1)
456 rc = 0;
457 else {
458 rc = -1;
459 errno = EINVAL;
460 }
461
462 return rc;
463 }
464
capng_apply(capng_select_t set)465 int capng_apply(capng_select_t set)
466 {
467 int rc = -1;
468
469 // Before updating, we expect that the data is initialized to something
470 if (m.state < CAPNG_INIT)
471 return -1;
472
473 if (set & CAPNG_SELECT_BOUNDS) {
474 #ifdef PR_CAPBSET_DROP
475 void *s = capng_save_state();
476 capng_get_caps_process();
477 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
478 int i;
479 capng_restore_state(&s);
480 rc = 0;
481 for (i=0; i <= CAP_LAST_CAP && rc == 0; i++)
482 if (capng_have_capability(CAPNG_BOUNDING_SET,
483 i) == 0)
484 rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
485 if (rc == 0)
486 m.state = CAPNG_APPLIED;
487 } else
488 capng_restore_state(&s);
489 #else
490 rc = 0;
491 #endif
492 }
493 if (set & CAPNG_SELECT_CAPS) {
494 rc = capset((cap_user_header_t)&m.hdr,
495 (cap_user_data_t)&m.data);
496 if (rc == 0)
497 m.state = CAPNG_APPLIED;
498 }
499 return rc;
500 }
501
502 #ifdef VFS_CAP_U32
save_data(struct vfs_cap_data * filedata,int * size)503 static int save_data(struct vfs_cap_data *filedata, int *size)
504 {
505 // Now stuff the data structures
506 if (m.cap_ver == 1) {
507 filedata->data[0].permitted = FIXUP(m.data.v1.permitted);
508 filedata->data[0].inheritable = FIXUP(m.data.v1.inheritable);
509 filedata->magic_etc = FIXUP(VFS_CAP_REVISION_1);
510 *size = XATTR_CAPS_SZ_1;
511 } else {
512 int eff;
513
514 if (m.data.v3[0].effective || m.data.v3[1].effective)
515 eff = VFS_CAP_FLAGS_EFFECTIVE;
516 else
517 eff = 0;
518 filedata->data[0].permitted = FIXUP(m.data.v3[0].permitted);
519 filedata->data[0].inheritable = FIXUP(m.data.v3[0].inheritable);
520 filedata->data[1].permitted = FIXUP(m.data.v3[1].permitted);
521 filedata->data[1].inheritable = FIXUP(m.data.v3[1].inheritable);
522 filedata->magic_etc = FIXUP(VFS_CAP_REVISION_2 | eff);
523 *size = XATTR_CAPS_SZ_2;
524 }
525
526 return 0;
527 }
528 #endif
529
capng_apply_caps_fd(int fd)530 int capng_apply_caps_fd(int fd)
531 {
532 #ifndef VFS_CAP_U32
533 return -1;
534 #else
535 int rc, size;
536 struct vfs_cap_data filedata;
537 struct stat buf;
538
539 // Before updating, we expect that the data is initialized to something
540 if (m.state < CAPNG_INIT)
541 return -1;
542
543 if (fstat(fd, &buf) != 0)
544 return -1;
545 if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
546 errno = EINVAL;
547 return -1;
548 }
549 if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE)
550 rc = fremovexattr(fd, XATTR_NAME_CAPS);
551 else {
552 save_data(&filedata, &size);
553 rc = fsetxattr(fd, XATTR_NAME_CAPS, &filedata, size, 0);
554 }
555
556 if (rc == 0)
557 m.state = CAPNG_APPLIED;
558
559 return rc;
560 #endif
561 }
562
563 // Change uids keeping/removing only certain capabilities
564 // flag to drop supp groups
capng_change_id(int uid,int gid,capng_flags_t flag)565 int capng_change_id(int uid, int gid, capng_flags_t flag)
566 {
567 int rc, need_setgid, need_setuid;
568
569 // Before updating, we expect that the data is initialized to something
570 if (m.state < CAPNG_INIT)
571 return -1;
572
573 // Check the current capabilities
574 #ifdef PR_CAPBSET_DROP
575 // If newer kernel, we need setpcap to change the bounding set
576 if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP) == 0 &&
577 flag & CAPNG_CLEAR_BOUNDING)
578 capng_update(CAPNG_ADD,
579 CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
580 #endif
581 if (gid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETGID))
582 need_setgid = 0;
583 else {
584 need_setgid = 1;
585 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
586 CAP_SETGID);
587 }
588 if (uid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETUID))
589 need_setuid = 0;
590 else {
591 need_setuid = 1;
592 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
593 CAP_SETUID);
594 }
595
596 // Tell system we want to keep caps across uid change
597 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0))
598 return -2;
599
600 // Change to the temp capabilities
601 rc = capng_apply(CAPNG_SELECT_CAPS);
602 if (rc < 0)
603 return -3;
604
605 // Clear bounding set if needed while we have CAP_SETPCAP
606 if (flag & CAPNG_CLEAR_BOUNDING) {
607 capng_clear(CAPNG_BOUNDING_SET);
608 rc = capng_apply(CAPNG_SELECT_BOUNDS);
609 if (rc)
610 return -8;
611 }
612
613 // Change gid
614 if (gid != -1) {
615 rc = setresgid(gid, gid, gid);
616 if (rc)
617 return -4;
618 }
619
620 // See if we need to unload supplemental groups
621 if ((flag & CAPNG_DROP_SUPP_GRP) && gid != -1) {
622 if (setgroups(0, NULL))
623 return -5;
624 }
625
626 // Change uid
627 if (uid != -1) {
628 rc = setresuid(uid, uid, uid);
629 if (rc)
630 return -6;
631 }
632
633 // Tell it we are done keeping capabilities
634 rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
635 if (rc)
636 return -7;
637
638 // Now throw away CAP_SETPCAP so no more changes
639 if (need_setgid)
640 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
641 CAP_SETGID);
642 if (need_setuid)
643 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
644 CAP_SETUID);
645
646 // Now drop setpcap & apply
647 capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
648 CAP_SETPCAP);
649 rc = capng_apply(CAPNG_SELECT_CAPS);
650 if (rc < 0)
651 return -9;
652
653 // Done
654 m.state = CAPNG_UPDATED;
655 return 0;
656 }
657
capng_lock(void)658 int capng_lock(void)
659 {
660 #ifdef PR_SET_SECUREBITS
661 int rc = prctl(PR_SET_SECUREBITS,
662 1 << SECURE_NOROOT |
663 1 << SECURE_NOROOT_LOCKED |
664 1 << SECURE_NO_SETUID_FIXUP |
665 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0);
666 if (rc)
667 return -1;
668 #endif
669
670 return 0;
671 }
672
673 // -1 - error, 0 - no caps, 1 partial caps, 2 full caps
capng_have_capabilities(capng_select_t set)674 capng_results_t capng_have_capabilities(capng_select_t set)
675 {
676 int empty = 0, full = 0;
677
678 // First, try to init with current set
679 if (m.state < CAPNG_INIT)
680 capng_get_caps_process();
681
682 // If we still don't have anything, error out
683 if (m.state < CAPNG_INIT)
684 return CAPNG_FAIL;
685
686 if (set & CAPNG_SELECT_CAPS) {
687 if (m.cap_ver == 1) {
688 if (m.data.v1.effective == 0)
689 empty = 1;
690 // after fill, 30 bits starts from upper to lower
691 else if (m.data.v1.effective == 0x7FFFFFFFU)
692 full = 1;
693 // actual capabilities read from system
694 else if (m.data.v1.effective == 0xFFFFFEFFU)
695 full = 1;
696 else
697 return CAPNG_PARTIAL;
698 } else {
699 if (m.data.v3[0].effective == 0)
700 empty = 1;
701 else if (m.data.v3[0].effective == 0xFFFFFFFFU)
702 full = 1;
703 else
704 return CAPNG_PARTIAL;
705 if ((m.data.v3[1].effective & UPPER_MASK) == 0)
706 empty = 1;
707 else if ((m.data.v3[1].effective & UPPER_MASK) ==
708 UPPER_MASK)
709 full = 1;
710 else
711 return CAPNG_PARTIAL;
712 }
713 }
714 #ifdef PR_CAPBSET_DROP
715 if (set & CAPNG_SELECT_BOUNDS) {
716 if (m.bounds[0] == 0)
717 empty = 1;
718 else if (m.bounds[0] == 0xFFFFFFFFU)
719 full = 1;
720 else
721 return CAPNG_PARTIAL;
722 if ((m.bounds[1] & UPPER_MASK) == 0)
723 empty = 1;
724 else if ((m.bounds[1] & UPPER_MASK) == UPPER_MASK)
725 full = 1;
726 else
727 return CAPNG_PARTIAL;
728 }
729 #endif
730
731 if (empty == 1 && full == 0)
732 return CAPNG_NONE;
733 else if (empty == 0 && full == 1)
734 return CAPNG_FULL;
735
736 return CAPNG_PARTIAL;
737 }
738
check_effective(unsigned int capability,unsigned int idx)739 static int check_effective(unsigned int capability, unsigned int idx)
740 {
741 return MASK(capability) & m.data.v3[idx].effective ? 1 : 0;
742 }
743
check_permitted(unsigned int capability,unsigned int idx)744 static int check_permitted(unsigned int capability, unsigned int idx)
745 {
746 return MASK(capability) & m.data.v3[idx].permitted ? 1 : 0;
747 }
748
check_inheritable(unsigned int capability,unsigned int idx)749 static int check_inheritable(unsigned int capability, unsigned int idx)
750 {
751 return MASK(capability) & m.data.v3[idx].inheritable ? 1 : 0;
752 }
753
bounds_bit_check(unsigned int capability,unsigned int idx)754 static int bounds_bit_check(unsigned int capability, unsigned int idx)
755 {
756 #ifdef PR_CAPBSET_DROP
757 return MASK(capability) & m.bounds[idx] ? 1 : 0;
758 #else
759 return 0;
760 #endif
761 }
762
v1_check(unsigned int capability,__u32 data)763 static int v1_check(unsigned int capability, __u32 data)
764 {
765 return MASK(capability) & data ? 1 : 0;
766 }
767
capng_have_capability(capng_type_t which,unsigned int capability)768 int capng_have_capability(capng_type_t which, unsigned int capability)
769 {
770 // First, try to init with current set
771 if (m.state < CAPNG_INIT)
772 capng_get_caps_process();
773
774 // If we still don't have anything, error out
775 if (m.state < CAPNG_INIT)
776 return CAPNG_FAIL;
777 if (m.cap_ver == 1 && capability > 31)
778 return 0;
779 if (!cap_valid(capability))
780 return 0;
781
782 if (m.cap_ver == 1) {
783 if (which == CAPNG_EFFECTIVE)
784 return v1_check(capability, m.data.v1.effective);
785 else if (which == CAPNG_PERMITTED)
786 return v1_check(capability, m.data.v1.permitted);
787 else if (which == CAPNG_INHERITABLE)
788 return v1_check(capability, m.data.v1.inheritable);
789 } else {
790 unsigned int idx;
791
792 if (capability > 31) {
793 idx = capability>>5;
794 capability %= 32;
795 } else
796 idx = 0;
797
798 if (which == CAPNG_EFFECTIVE)
799 return check_effective(capability, idx);
800 else if (which == CAPNG_PERMITTED)
801 return check_permitted(capability, idx);
802 else if (which == CAPNG_INHERITABLE)
803 return check_inheritable(capability, idx);
804 else if (which == CAPNG_BOUNDING_SET)
805 return bounds_bit_check(capability, idx);
806 }
807 return 0;
808 }
809
capng_print_caps_numeric(capng_print_t where,capng_select_t set)810 char *capng_print_caps_numeric(capng_print_t where, capng_select_t set)
811 {
812 char *ptr = NULL;
813
814 if (m.state < CAPNG_INIT)
815 return ptr;
816
817 if (where == CAPNG_PRINT_STDOUT) {
818 if (set & CAPNG_SELECT_CAPS) {
819 if (m.cap_ver == 1) {
820 printf( "Effective: %08X\n"
821 "Permitted: %08X\n"
822 "Inheritable: %08X\n",
823 m.data.v1.effective,
824 m.data.v1.permitted,
825 m.data.v1.inheritable);
826 } else {
827 printf( "Effective: %08X, %08X\n"
828 "Permitted: %08X, %08X\n"
829 "Inheritable: %08X, %08X\n",
830 m.data.v3[1].effective & UPPER_MASK,
831 m.data.v3[0].effective,
832 m.data.v3[1].permitted & UPPER_MASK,
833 m.data.v3[0].permitted,
834 m.data.v3[1].inheritable & UPPER_MASK,
835 m.data.v3[0].inheritable);
836
837 }
838 }
839 #ifdef PR_CAPBSET_DROP
840 if (set & CAPNG_SELECT_BOUNDS)
841 printf("Bounding Set: %08X, %08X\n",
842 m.bounds[1] & UPPER_MASK, m.bounds[0]);
843 #endif
844 } else if (where == CAPNG_PRINT_BUFFER) {
845 if (set & CAPNG_SELECT_CAPS) {
846 // Make it big enough for bounding set, too
847 ptr = malloc(160);
848 if (m.cap_ver == 1) {
849 snprintf(ptr, 160,
850 "Effective: %08X\n"
851 "Permitted: %08X\n"
852 "Inheritable: %08X\n",
853 m.data.v1.effective,
854 m.data.v1.permitted,
855 m.data.v1.inheritable);
856 } else {
857 snprintf(ptr, 160,
858 "Effective: %08X, %08X\n"
859 "Permitted: %08X, %08X\n"
860 "Inheritable: %08X, %08X\n",
861 m.data.v3[1].effective & UPPER_MASK,
862 m.data.v3[0].effective,
863 m.data.v3[1].permitted & UPPER_MASK,
864 m.data.v3[0].permitted,
865 m.data.v3[1].inheritable & UPPER_MASK,
866 m.data.v3[0].inheritable);
867 }
868 }
869 if (set & CAPNG_SELECT_BOUNDS) {
870 #ifdef PR_CAPBSET_DROP
871 char *s;
872 if (ptr == NULL ){
873 ptr = malloc(40);
874 if (ptr == NULL)
875 return ptr;
876 *ptr = 0;
877 s = ptr;
878 } else
879 s = ptr + strlen(ptr);
880 snprintf(s, 40, "Bounding Set: %08X, %08X\n",
881 m.bounds[1] & UPPER_MASK, m.bounds[0]);
882 #endif
883 }
884 }
885
886 return ptr;
887 }
888
capng_print_caps_text(capng_print_t where,capng_type_t which)889 char *capng_print_caps_text(capng_print_t where, capng_type_t which)
890 {
891 unsigned int i;
892 int once = 0, cnt = 0;
893 char *ptr = NULL;
894
895 if (m.state < CAPNG_INIT)
896 return ptr;
897
898 for (i=0; i<=CAP_LAST_CAP; i++) {
899 if (capng_have_capability(which, i)) {
900 const char *n = capng_capability_to_name(i);
901 if (n == NULL)
902 n = "unknown";
903 if (where == CAPNG_PRINT_STDOUT) {
904 if (once == 0) {
905 printf("%s", n);
906 once++;
907 } else
908 printf(", %s", n);
909 } else if (where == CAPNG_PRINT_BUFFER) {
910 int len;
911 if (once == 0) {
912 ptr = malloc(CAP_LAST_CAP*18);
913 if (ptr == NULL)
914 return ptr;
915 len = sprintf(ptr+cnt, "%s", n);
916 once++;
917 } else
918 len = sprintf(ptr+cnt, ", %s", n);
919 if (len > 0)
920 cnt+=len;
921 }
922 }
923 }
924 if (once == 0) {
925 if (where == CAPNG_PRINT_STDOUT)
926 printf("none");
927 else
928 ptr = strdup("none");
929 }
930 return ptr;
931 }
932
capng_save_state(void)933 void *capng_save_state(void)
934 {
935 void *ptr = malloc(sizeof(m));
936 if (ptr)
937 memcpy(ptr, &m, sizeof(m));
938 return ptr;
939 }
940
capng_restore_state(void ** state)941 void capng_restore_state(void **state)
942 {
943 if (state) {
944 void *ptr = *state;
945 if (ptr)
946 memcpy(&m, ptr, sizeof(m));
947 free(ptr);
948 *state = NULL;
949 }
950 }
951
952