Home | History | Annotate | Download | only in src
      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