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 #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 */
53 extern int capset(cap_user_header_t header, cap_user_data_t data);
54 extern 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
122 typedef 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
126 typedef 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
132 struct 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
142 static __thread struct cap_ng m = { 1,
143 {0, 0},
144 { {0, 0, 0} },
145 CAPNG_NEW,
146 {0, 0} };
147
148
init(void)149 static 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
capng_clear(capng_select_t set)175 void 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
capng_fill(capng_select_t set)191 void 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
capng_setpid(int pid)222 void 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
get_bounding_set(void)233 static 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
capng_get_caps_process(void)262 int 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
load_data(const struct vfs_cap_data * filedata,int size)285 static 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
capng_get_caps_fd(int fd)327 int 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
v1_update(capng_act_t action,unsigned int capability,__u32 * data)352 static 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
update_effective(capng_act_t action,unsigned int capability,unsigned int idx)360 static 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
update_permitted(capng_act_t action,unsigned int capability,unsigned int idx)369 static 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
update_inheritable(capng_act_t action,unsigned int capability,unsigned int idx)378 static 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
update_bounding_set(capng_act_t action,unsigned int capability,unsigned int idx)387 static 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
capng_update(capng_act_t action,capng_type_t type,unsigned int capability)398 int 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
capng_updatev(capng_act_t action,capng_type_t type,unsigned int capability,...)438 int 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
capng_apply(capng_select_t set)469 int 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
save_data(struct vfs_cap_data * filedata,int * size)507 static 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
capng_apply_caps_fd(int fd)534 int 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
capng_change_id(int uid,int gid,capng_flags_t flag)569 int 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
capng_lock(void)662 int 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
capng_have_capabilities(capng_select_t set)678 capng_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
check_effective(unsigned int capability,unsigned int idx)743 static int check_effective(unsigned int capability, unsigned int idx)
744 {
745 return MASK(capability) & m.data.v3[idx].effective ? 1 : 0;
746 }
747
check_permitted(unsigned int capability,unsigned int idx)748 static int check_permitted(unsigned int capability, unsigned int idx)
749 {
750 return MASK(capability) & m.data.v3[idx].permitted ? 1 : 0;
751 }
752
check_inheritable(unsigned int capability,unsigned int idx)753 static int check_inheritable(unsigned int capability, unsigned int idx)
754 {
755 return MASK(capability) & m.data.v3[idx].inheritable ? 1 : 0;
756 }
757
bounds_bit_check(unsigned int capability,unsigned int idx)758 static 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
v1_check(unsigned int capability,__u32 data)767 static int v1_check(unsigned int capability, __u32 data)
768 {
769 return MASK(capability) & data ? 1 : 0;
770 }
771
capng_have_capability(capng_type_t which,unsigned int capability)772 int 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
capng_print_caps_numeric(capng_print_t where,capng_select_t set)814 char *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
capng_print_caps_text(capng_print_t where,capng_type_t which)893 char *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
capng_save_state(void)937 void *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
capng_restore_state(void ** state)945 void 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
956