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