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