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 (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 763 static int v1_check(unsigned int capability, __u32 data) 764 { 765 return MASK(capability) & data ? 1 : 0; 766 } 767 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 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 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 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 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