• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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