xref: /aosp_15_r20/external/libcap-ng/src/cap-ng.c (revision 8dd5e09d5faf27a871e8654ddaa2d2af7c696578)
1*8dd5e09dSSadaf Ebrahimi /* libcap-ng.c --
2*8dd5e09dSSadaf Ebrahimi  * Copyright 2009-10, 2013, 2017, 2020-21 Red Hat Inc.
3*8dd5e09dSSadaf Ebrahimi  * All Rights Reserved.
4*8dd5e09dSSadaf Ebrahimi  *
5*8dd5e09dSSadaf Ebrahimi  * This library is free software; you can redistribute it and/or
6*8dd5e09dSSadaf Ebrahimi  * modify it under the terms of the GNU Lesser General Public
7*8dd5e09dSSadaf Ebrahimi  * License as published by the Free Software Foundation; either
8*8dd5e09dSSadaf Ebrahimi  * version 2.1 of the License, or (at your option) any later version.
9*8dd5e09dSSadaf Ebrahimi  *
10*8dd5e09dSSadaf Ebrahimi  * This library is distributed in the hope that it will be useful,
11*8dd5e09dSSadaf Ebrahimi  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*8dd5e09dSSadaf Ebrahimi  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*8dd5e09dSSadaf Ebrahimi  * Lesser General Public License for more details.
14*8dd5e09dSSadaf Ebrahimi  *
15*8dd5e09dSSadaf Ebrahimi  * You should have received a copy of the GNU Lesser General Public License
16*8dd5e09dSSadaf Ebrahimi  * along with this program; see the file COPYING.LIB. If not, write to the
17*8dd5e09dSSadaf Ebrahimi  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
18*8dd5e09dSSadaf Ebrahimi  * Boston, MA 02110-1335, USA.
19*8dd5e09dSSadaf Ebrahimi  *
20*8dd5e09dSSadaf Ebrahimi  * Authors:
21*8dd5e09dSSadaf Ebrahimi  *      Steve Grubb <[email protected]>
22*8dd5e09dSSadaf Ebrahimi  */
23*8dd5e09dSSadaf Ebrahimi 
24*8dd5e09dSSadaf Ebrahimi #include "config.h"
25*8dd5e09dSSadaf Ebrahimi #include "cap-ng.h"
26*8dd5e09dSSadaf Ebrahimi #include <string.h>
27*8dd5e09dSSadaf Ebrahimi #include <stdarg.h>
28*8dd5e09dSSadaf Ebrahimi #include <stdio.h>
29*8dd5e09dSSadaf Ebrahimi #include <stdio_ext.h>
30*8dd5e09dSSadaf Ebrahimi #include <stdlib.h>
31*8dd5e09dSSadaf Ebrahimi #include <sys/prctl.h>
32*8dd5e09dSSadaf Ebrahimi #include <pwd.h>
33*8dd5e09dSSadaf Ebrahimi #include <grp.h>
34*8dd5e09dSSadaf Ebrahimi #include <sys/stat.h>
35*8dd5e09dSSadaf Ebrahimi #include <errno.h>
36*8dd5e09dSSadaf Ebrahimi #include <fcntl.h>
37*8dd5e09dSSadaf Ebrahimi #include <endian.h>
38*8dd5e09dSSadaf Ebrahimi #include <byteswap.h>
39*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_PTHREAD_H
40*8dd5e09dSSadaf Ebrahimi #include <pthread.h>	// For pthread_atfork
41*8dd5e09dSSadaf Ebrahimi #endif
42*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_SYSCALL_H
43*8dd5e09dSSadaf Ebrahimi #include <sys/syscall.h>
44*8dd5e09dSSadaf Ebrahimi #endif
45*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_LINUX_SECUREBITS_H
46*8dd5e09dSSadaf Ebrahimi #include <linux/securebits.h>
47*8dd5e09dSSadaf Ebrahimi #endif
48*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_LINUX_MAGIC_H
49*8dd5e09dSSadaf Ebrahimi #include <sys/vfs.h>
50*8dd5e09dSSadaf Ebrahimi #include <linux/magic.h>
51*8dd5e09dSSadaf Ebrahimi #endif
52*8dd5e09dSSadaf Ebrahimi 
53*8dd5e09dSSadaf Ebrahimi # define hidden __attribute__ ((visibility ("hidden")))
54*8dd5e09dSSadaf Ebrahimi unsigned int last_cap hidden = 0;
55*8dd5e09dSSadaf Ebrahimi /*
56*8dd5e09dSSadaf Ebrahimi  * Some milestones of when things became available:
57*8dd5e09dSSadaf Ebrahimi  * 2.6.24 kernel	XATTR_NAME_CAPS
58*8dd5e09dSSadaf Ebrahimi  * 2.6.25 kernel	PR_CAPBSET_DROP, CAPABILITY_VERSION_2
59*8dd5e09dSSadaf Ebrahimi  * 2.6.26 kernel	PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3
60*8dd5e09dSSadaf Ebrahimi  * 3.5    kernel	PR_SET_NO_NEW_PRIVS
61*8dd5e09dSSadaf Ebrahimi  * 4.3    kernel	PR_CAP_AMBIENT
62*8dd5e09dSSadaf Ebrahimi  * 4.14   kernel	VFS_CAP_REVISION_3
63*8dd5e09dSSadaf Ebrahimi  */
64*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
65*8dd5e09dSSadaf Ebrahimi static int HAVE_PR_CAPBSET_DROP = 0;
66*8dd5e09dSSadaf Ebrahimi #endif
67*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_SECUREBITS
68*8dd5e09dSSadaf Ebrahimi static int HAVE_PR_SET_SECUREBITS = 0;
69*8dd5e09dSSadaf Ebrahimi #endif
70*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_NO_NEW_PRIVS
71*8dd5e09dSSadaf Ebrahimi static int HAVE_PR_SET_NO_NEW_PRIVS = 0;
72*8dd5e09dSSadaf Ebrahimi #endif
73*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
74*8dd5e09dSSadaf Ebrahimi static int HAVE_PR_CAP_AMBIENT = 0;
75*8dd5e09dSSadaf Ebrahimi #endif
76*8dd5e09dSSadaf Ebrahimi 
77*8dd5e09dSSadaf Ebrahimi /* External syscall prototypes */
78*8dd5e09dSSadaf Ebrahimi extern int capset(cap_user_header_t header, cap_user_data_t data);
79*8dd5e09dSSadaf Ebrahimi extern int capget(cap_user_header_t header, const cap_user_data_t data);
80*8dd5e09dSSadaf Ebrahimi 
81*8dd5e09dSSadaf Ebrahimi // Local functions
82*8dd5e09dSSadaf Ebrahimi static void update_bounding_set(capng_act_t action, unsigned int capability,
83*8dd5e09dSSadaf Ebrahimi 	unsigned int idx);
84*8dd5e09dSSadaf Ebrahimi static void update_ambient_set(capng_act_t action, unsigned int capability,
85*8dd5e09dSSadaf Ebrahimi 	unsigned int idx);
86*8dd5e09dSSadaf Ebrahimi 
87*8dd5e09dSSadaf Ebrahimi // Local defines
88*8dd5e09dSSadaf Ebrahimi #define MASK(x) (1U << (x))
89*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
90*8dd5e09dSSadaf Ebrahimi #define UPPER_MASK ~((~0U)<<(last_cap-31))
91*8dd5e09dSSadaf Ebrahimi #else
92*8dd5e09dSSadaf Ebrahimi // For v1 systems UPPER_MASK will never be used
93*8dd5e09dSSadaf Ebrahimi #define UPPER_MASK (unsigned)(~0U)
94*8dd5e09dSSadaf Ebrahimi #endif
95*8dd5e09dSSadaf Ebrahimi 
96*8dd5e09dSSadaf Ebrahimi // Re-define cap_valid so its uniform between V1 and V3
97*8dd5e09dSSadaf Ebrahimi #undef cap_valid
98*8dd5e09dSSadaf Ebrahimi #define cap_valid(x) ((x) <= last_cap)
99*8dd5e09dSSadaf Ebrahimi 
100*8dd5e09dSSadaf Ebrahimi // If we don't have the xattr library, then we can't
101*8dd5e09dSSadaf Ebrahimi // compile-in file system capabilities
102*8dd5e09dSSadaf Ebrahimi #if !defined(HAVE_ATTR_XATTR_H) && !defined (HAVE_SYS_XATTR_H)
103*8dd5e09dSSadaf Ebrahimi #undef VFS_CAP_U32
104*8dd5e09dSSadaf Ebrahimi #endif
105*8dd5e09dSSadaf Ebrahimi 
106*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_U32
107*8dd5e09dSSadaf Ebrahimi  #ifdef HAVE_SYS_XATTR_H
108*8dd5e09dSSadaf Ebrahimi    #include <sys/xattr.h>
109*8dd5e09dSSadaf Ebrahimi  #else
110*8dd5e09dSSadaf Ebrahimi   #ifdef HAVE_ATTR_XATTR_H
111*8dd5e09dSSadaf Ebrahimi    #include <attr/xattr.h>
112*8dd5e09dSSadaf Ebrahimi   #endif
113*8dd5e09dSSadaf Ebrahimi  #endif
114*8dd5e09dSSadaf Ebrahimi  #if __BYTE_ORDER == __BIG_ENDIAN
115*8dd5e09dSSadaf Ebrahimi   #define FIXUP(x) bswap_32(x)
116*8dd5e09dSSadaf Ebrahimi  #else
117*8dd5e09dSSadaf Ebrahimi   #define FIXUP(x) (x)
118*8dd5e09dSSadaf Ebrahimi  #endif
119*8dd5e09dSSadaf Ebrahimi #endif
120*8dd5e09dSSadaf Ebrahimi 
121*8dd5e09dSSadaf Ebrahimi #ifndef _LINUX_CAPABILITY_VERSION_1
122*8dd5e09dSSadaf Ebrahimi #define _LINUX_CAPABILITY_VERSION_1 0x19980330
123*8dd5e09dSSadaf Ebrahimi #endif
124*8dd5e09dSSadaf Ebrahimi #ifndef _LINUX_CAPABILITY_VERSION_2
125*8dd5e09dSSadaf Ebrahimi #define _LINUX_CAPABILITY_VERSION_2 0x20071026
126*8dd5e09dSSadaf Ebrahimi #endif
127*8dd5e09dSSadaf Ebrahimi #ifndef _LINUX_CAPABILITY_VERSION_3
128*8dd5e09dSSadaf Ebrahimi #define _LINUX_CAPABILITY_VERSION_3 0x20080522
129*8dd5e09dSSadaf Ebrahimi #endif
130*8dd5e09dSSadaf Ebrahimi 
131*8dd5e09dSSadaf Ebrahimi // This public API went private in the 2.6.36 kernel - hope it never changes
132*8dd5e09dSSadaf Ebrahimi #ifndef XATTR_CAPS_SUFFIX
133*8dd5e09dSSadaf Ebrahimi #define XATTR_CAPS_SUFFIX "capability"
134*8dd5e09dSSadaf Ebrahimi #endif
135*8dd5e09dSSadaf Ebrahimi #ifndef XATTR_SECURITY_PREFIX
136*8dd5e09dSSadaf Ebrahimi #define XATTR_SECURITY_PREFIX "security."
137*8dd5e09dSSadaf Ebrahimi #endif
138*8dd5e09dSSadaf Ebrahimi #ifndef XATTR_NAME_CAPS
139*8dd5e09dSSadaf Ebrahimi #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
140*8dd5e09dSSadaf Ebrahimi #endif
141*8dd5e09dSSadaf Ebrahimi 
142*8dd5e09dSSadaf Ebrahimi 
143*8dd5e09dSSadaf Ebrahimi /* Child processes can't get caps back */
144*8dd5e09dSSadaf Ebrahimi #ifndef SECURE_NOROOT
145*8dd5e09dSSadaf Ebrahimi #define SECURE_NOROOT                   0
146*8dd5e09dSSadaf Ebrahimi #endif
147*8dd5e09dSSadaf Ebrahimi #ifndef SECURE_NOROOT_LOCKED
148*8dd5e09dSSadaf Ebrahimi #define SECURE_NOROOT_LOCKED            1  /* make bit-0 immutable */
149*8dd5e09dSSadaf Ebrahimi #endif
150*8dd5e09dSSadaf Ebrahimi /* Setuid apps run by uid 0 don't get caps back */
151*8dd5e09dSSadaf Ebrahimi #ifndef SECURE_NO_SETUID_FIXUP
152*8dd5e09dSSadaf Ebrahimi #define SECURE_NO_SETUID_FIXUP          2
153*8dd5e09dSSadaf Ebrahimi #endif
154*8dd5e09dSSadaf Ebrahimi #ifndef SECURE_NO_SETUID_FIXUP_LOCKED
155*8dd5e09dSSadaf Ebrahimi #define SECURE_NO_SETUID_FIXUP_LOCKED   3  /* make bit-2 immutable */
156*8dd5e09dSSadaf Ebrahimi #endif
157*8dd5e09dSSadaf Ebrahimi 
158*8dd5e09dSSadaf Ebrahimi #ifndef VFS_CAP_U32
159*8dd5e09dSSadaf Ebrahimi #define VFS_CAP_U32 2
160*8dd5e09dSSadaf Ebrahimi #endif
161*8dd5e09dSSadaf Ebrahimi 
162*8dd5e09dSSadaf Ebrahimi #if (VFS_CAP_U32 != 2)
163*8dd5e09dSSadaf Ebrahimi #error VFS_CAP_U32 does not match the library, you need a new version
164*8dd5e09dSSadaf Ebrahimi #endif
165*8dd5e09dSSadaf Ebrahimi 
166*8dd5e09dSSadaf Ebrahimi 
167*8dd5e09dSSadaf Ebrahimi // States: new, allocated, initted, updated, applied
168*8dd5e09dSSadaf Ebrahimi typedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT,
169*8dd5e09dSSadaf Ebrahimi 	CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t;
170*8dd5e09dSSadaf Ebrahimi 
171*8dd5e09dSSadaf Ebrahimi // Create an easy data struct out of the kernel definitions
172*8dd5e09dSSadaf Ebrahimi typedef union {
173*8dd5e09dSSadaf Ebrahimi 	struct __user_cap_data_struct v1;
174*8dd5e09dSSadaf Ebrahimi 	struct __user_cap_data_struct v3[VFS_CAP_U32];
175*8dd5e09dSSadaf Ebrahimi } cap_data_t;
176*8dd5e09dSSadaf Ebrahimi 
177*8dd5e09dSSadaf Ebrahimi // This struct keeps all state info
178*8dd5e09dSSadaf Ebrahimi struct cap_ng
179*8dd5e09dSSadaf Ebrahimi {
180*8dd5e09dSSadaf Ebrahimi 	int cap_ver;
181*8dd5e09dSSadaf Ebrahimi 	int vfs_cap_ver;
182*8dd5e09dSSadaf Ebrahimi 	struct __user_cap_header_struct hdr;
183*8dd5e09dSSadaf Ebrahimi 	cap_data_t data;
184*8dd5e09dSSadaf Ebrahimi 	capng_states_t state;
185*8dd5e09dSSadaf Ebrahimi 	__le32 rootid;
186*8dd5e09dSSadaf Ebrahimi 	__u32 bounds[VFS_CAP_U32];
187*8dd5e09dSSadaf Ebrahimi 	__u32 ambient[VFS_CAP_U32];
188*8dd5e09dSSadaf Ebrahimi };
189*8dd5e09dSSadaf Ebrahimi 
190*8dd5e09dSSadaf Ebrahimi // Global variables with per thread uniqueness
191*8dd5e09dSSadaf Ebrahimi static __thread struct cap_ng m =	{ 1, 1,
192*8dd5e09dSSadaf Ebrahimi 					{0, 0},
193*8dd5e09dSSadaf Ebrahimi 					{ {0, 0, 0} },
194*8dd5e09dSSadaf Ebrahimi 					CAPNG_NEW, CAPNG_UNSET_ROOTID,
195*8dd5e09dSSadaf Ebrahimi 					{0, 0},
196*8dd5e09dSSadaf Ebrahimi 					{0, 0} };
197*8dd5e09dSSadaf Ebrahimi 
198*8dd5e09dSSadaf Ebrahimi /*
199*8dd5e09dSSadaf Ebrahimi  * Reset the state so that init gets called to erase everything
200*8dd5e09dSSadaf Ebrahimi  */
deinit(void)201*8dd5e09dSSadaf Ebrahimi static void deinit(void)
202*8dd5e09dSSadaf Ebrahimi {
203*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_NEW;
204*8dd5e09dSSadaf Ebrahimi }
205*8dd5e09dSSadaf Ebrahimi 
test_cap(unsigned int cap)206*8dd5e09dSSadaf Ebrahimi static inline int test_cap(unsigned int cap)
207*8dd5e09dSSadaf Ebrahimi {
208*8dd5e09dSSadaf Ebrahimi 	// prctl returns 0 or 1 for valid caps, -1 otherwise
209*8dd5e09dSSadaf Ebrahimi 	return prctl(PR_CAPBSET_READ, cap) >= 0;
210*8dd5e09dSSadaf Ebrahimi }
211*8dd5e09dSSadaf Ebrahimi 
212*8dd5e09dSSadaf Ebrahimi // The maximum cap value is determined by VFS_CAP_U32
213*8dd5e09dSSadaf Ebrahimi #define MAX_CAP_VALUE (VFS_CAP_U32 * sizeof(__le32) * 8)
214*8dd5e09dSSadaf Ebrahimi 
215*8dd5e09dSSadaf Ebrahimi static void init_lib(void) __attribute__ ((constructor));
init_lib(void)216*8dd5e09dSSadaf Ebrahimi static void init_lib(void)
217*8dd5e09dSSadaf Ebrahimi {
218*8dd5e09dSSadaf Ebrahimi        // This is so dynamic libraries don't re-init
219*8dd5e09dSSadaf Ebrahimi        static unsigned int run_once = 0;
220*8dd5e09dSSadaf Ebrahimi        if (run_once)
221*8dd5e09dSSadaf Ebrahimi                return;
222*8dd5e09dSSadaf Ebrahimi        run_once = 1;
223*8dd5e09dSSadaf Ebrahimi 
224*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_PTHREAD_H
225*8dd5e09dSSadaf Ebrahimi 	pthread_atfork(NULL, NULL, deinit);
226*8dd5e09dSSadaf Ebrahimi #endif
227*8dd5e09dSSadaf Ebrahimi 	// Detect last cap
228*8dd5e09dSSadaf Ebrahimi 	if (last_cap == 0) {
229*8dd5e09dSSadaf Ebrahimi 		int fd;
230*8dd5e09dSSadaf Ebrahimi 
231*8dd5e09dSSadaf Ebrahimi 		// Try to read last cap from procfs
232*8dd5e09dSSadaf Ebrahimi 		fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
233*8dd5e09dSSadaf Ebrahimi 		if (fd >= 0) {
234*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_LINUX_MAGIC_H
235*8dd5e09dSSadaf Ebrahimi 			struct statfs st;
236*8dd5e09dSSadaf Ebrahimi 			// Bail out if procfs is invalid or fstatfs fails
237*8dd5e09dSSadaf Ebrahimi 			if (fstatfs(fd, &st) || st.f_type != PROC_SUPER_MAGIC)
238*8dd5e09dSSadaf Ebrahimi 				goto fail;
239*8dd5e09dSSadaf Ebrahimi #endif
240*8dd5e09dSSadaf Ebrahimi 			char buf[8];
241*8dd5e09dSSadaf Ebrahimi 			int num = read(fd, buf, sizeof(buf) - 1);
242*8dd5e09dSSadaf Ebrahimi 			if (num > 0) {
243*8dd5e09dSSadaf Ebrahimi 				buf[num] = 0;
244*8dd5e09dSSadaf Ebrahimi 				errno = 0;
245*8dd5e09dSSadaf Ebrahimi 				unsigned int val = strtoul(buf, NULL, 10);
246*8dd5e09dSSadaf Ebrahimi 				if (errno == 0)
247*8dd5e09dSSadaf Ebrahimi 					last_cap = val;
248*8dd5e09dSSadaf Ebrahimi 			}
249*8dd5e09dSSadaf Ebrahimi fail:
250*8dd5e09dSSadaf Ebrahimi 			close(fd);
251*8dd5e09dSSadaf Ebrahimi 		}
252*8dd5e09dSSadaf Ebrahimi 		// Run a binary search over capabilities
253*8dd5e09dSSadaf Ebrahimi 		if (last_cap == 0) {
254*8dd5e09dSSadaf Ebrahimi 			// starting with last_cap=MAX_CAP_VALUE means we always know
255*8dd5e09dSSadaf Ebrahimi 			// that cap1 is invalid after the first iteration
256*8dd5e09dSSadaf Ebrahimi 			last_cap = MAX_CAP_VALUE;
257*8dd5e09dSSadaf Ebrahimi 			unsigned int cap0 = 0, cap1 = MAX_CAP_VALUE;
258*8dd5e09dSSadaf Ebrahimi 
259*8dd5e09dSSadaf Ebrahimi 			while (cap0 < last_cap) {
260*8dd5e09dSSadaf Ebrahimi 				if (test_cap(last_cap))
261*8dd5e09dSSadaf Ebrahimi 					cap0 = last_cap;
262*8dd5e09dSSadaf Ebrahimi 				else
263*8dd5e09dSSadaf Ebrahimi 					cap1 = last_cap;
264*8dd5e09dSSadaf Ebrahimi 
265*8dd5e09dSSadaf Ebrahimi 				last_cap = (cap0 + cap1) / 2U;
266*8dd5e09dSSadaf Ebrahimi 			}
267*8dd5e09dSSadaf Ebrahimi 		}
268*8dd5e09dSSadaf Ebrahimi 	}
269*8dd5e09dSSadaf Ebrahimi 	// Detect prctl options at runtime
270*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
271*8dd5e09dSSadaf Ebrahimi 	errno = 0;
272*8dd5e09dSSadaf Ebrahimi 	prctl(PR_CAPBSET_READ, 0, 0, 0, 0);
273*8dd5e09dSSadaf Ebrahimi 	if (!errno)
274*8dd5e09dSSadaf Ebrahimi 		HAVE_PR_CAPBSET_DROP = 1;
275*8dd5e09dSSadaf Ebrahimi #endif
276*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_SECUREBITS
277*8dd5e09dSSadaf Ebrahimi 	errno = 0;
278*8dd5e09dSSadaf Ebrahimi 	prctl(PR_GET_SECUREBITS, 0, 0, 0, 0);
279*8dd5e09dSSadaf Ebrahimi 	if (!errno)
280*8dd5e09dSSadaf Ebrahimi 		HAVE_PR_SET_SECUREBITS = 1;
281*8dd5e09dSSadaf Ebrahimi #endif
282*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_NO_NEW_PRIVS
283*8dd5e09dSSadaf Ebrahimi 	errno = 0;
284*8dd5e09dSSadaf Ebrahimi 	prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
285*8dd5e09dSSadaf Ebrahimi 	if (!errno)
286*8dd5e09dSSadaf Ebrahimi 		HAVE_PR_SET_NO_NEW_PRIVS = 1;
287*8dd5e09dSSadaf Ebrahimi #endif
288*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
289*8dd5e09dSSadaf Ebrahimi 	errno = 0;
290*8dd5e09dSSadaf Ebrahimi 	prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, 0, 0, 0);
291*8dd5e09dSSadaf Ebrahimi 	if (!errno)
292*8dd5e09dSSadaf Ebrahimi 		HAVE_PR_CAP_AMBIENT = 1;
293*8dd5e09dSSadaf Ebrahimi #endif
294*8dd5e09dSSadaf Ebrahimi }
295*8dd5e09dSSadaf Ebrahimi 
init(void)296*8dd5e09dSSadaf Ebrahimi static void init(void)
297*8dd5e09dSSadaf Ebrahimi {
298*8dd5e09dSSadaf Ebrahimi 	// This is so static libs get initialized
299*8dd5e09dSSadaf Ebrahimi 	init_lib();
300*8dd5e09dSSadaf Ebrahimi 
301*8dd5e09dSSadaf Ebrahimi 	if (m.state != CAPNG_NEW)
302*8dd5e09dSSadaf Ebrahimi 		return;
303*8dd5e09dSSadaf Ebrahimi 
304*8dd5e09dSSadaf Ebrahimi 	memset(&m.hdr, 0, sizeof(m.hdr));
305*8dd5e09dSSadaf Ebrahimi 	(void)capget(&m.hdr, NULL); // Returns -EINVAL
306*8dd5e09dSSadaf Ebrahimi 	if (m.hdr.version == _LINUX_CAPABILITY_VERSION_3 ||
307*8dd5e09dSSadaf Ebrahimi 		m.hdr.version == _LINUX_CAPABILITY_VERSION_2) {
308*8dd5e09dSSadaf Ebrahimi 		m.cap_ver = 3;
309*8dd5e09dSSadaf Ebrahimi 	} else if (m.hdr.version == _LINUX_CAPABILITY_VERSION_1) {
310*8dd5e09dSSadaf Ebrahimi 		m.cap_ver = 1;
311*8dd5e09dSSadaf Ebrahimi 	} else {
312*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_ERROR;
313*8dd5e09dSSadaf Ebrahimi 		return;
314*8dd5e09dSSadaf Ebrahimi 	}
315*8dd5e09dSSadaf Ebrahimi 
316*8dd5e09dSSadaf Ebrahimi #if VFS_CAP_REVISION == VFS_CAP_REVISION_1
317*8dd5e09dSSadaf Ebrahimi 	m.vfs_cap_ver = 1;
318*8dd5e09dSSadaf Ebrahimi #else
319*8dd5e09dSSadaf Ebrahimi 	m.vfs_cap_ver = 2; // Intentionally set to 2 for both 2 & 3
320*8dd5e09dSSadaf Ebrahimi #endif
321*8dd5e09dSSadaf Ebrahimi 
322*8dd5e09dSSadaf Ebrahimi 	memset(&m.data, 0, sizeof(cap_data_t));
323*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_SYSCALL_H
324*8dd5e09dSSadaf Ebrahimi 	m.hdr.pid = (unsigned)syscall(__NR_gettid);
325*8dd5e09dSSadaf Ebrahimi #else
326*8dd5e09dSSadaf Ebrahimi 	m.hdr.pid = (unsigned)getpid();
327*8dd5e09dSSadaf Ebrahimi #endif
328*8dd5e09dSSadaf Ebrahimi 	m.rootid = CAPNG_UNSET_ROOTID;
329*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_ALLOCATED;
330*8dd5e09dSSadaf Ebrahimi }
331*8dd5e09dSSadaf Ebrahimi 
capng_clear(capng_select_t set)332*8dd5e09dSSadaf Ebrahimi void capng_clear(capng_select_t set)
333*8dd5e09dSSadaf Ebrahimi {
334*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
335*8dd5e09dSSadaf Ebrahimi 		init();
336*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
337*8dd5e09dSSadaf Ebrahimi 		return;
338*8dd5e09dSSadaf Ebrahimi 
339*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_CAPS)
340*8dd5e09dSSadaf Ebrahimi 		memset(&m.data, 0, sizeof(cap_data_t));
341*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
342*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
343*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_BOUNDS)
344*8dd5e09dSSadaf Ebrahimi 		memset(m.bounds, 0, sizeof(m.bounds));
345*8dd5e09dSSadaf Ebrahimi }
346*8dd5e09dSSadaf Ebrahimi #endif
347*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
348*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
349*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_AMBIENT)
350*8dd5e09dSSadaf Ebrahimi 		memset(m.ambient, 0, sizeof(m.ambient));
351*8dd5e09dSSadaf Ebrahimi }
352*8dd5e09dSSadaf Ebrahimi #endif
353*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_INIT;
354*8dd5e09dSSadaf Ebrahimi }
355*8dd5e09dSSadaf Ebrahimi 
capng_fill(capng_select_t set)356*8dd5e09dSSadaf Ebrahimi void capng_fill(capng_select_t set)
357*8dd5e09dSSadaf Ebrahimi {
358*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
359*8dd5e09dSSadaf Ebrahimi 		init();
360*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
361*8dd5e09dSSadaf Ebrahimi 		return;
362*8dd5e09dSSadaf Ebrahimi 
363*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_CAPS) {
364*8dd5e09dSSadaf Ebrahimi 		if (m.cap_ver == 1) {
365*8dd5e09dSSadaf Ebrahimi 			m.data.v1.effective = 0x7FFFFFFFU;
366*8dd5e09dSSadaf Ebrahimi 			m.data.v1.permitted = 0x7FFFFFFFU;
367*8dd5e09dSSadaf Ebrahimi 			m.data.v1.inheritable = 0;
368*8dd5e09dSSadaf Ebrahimi 		} else {
369*8dd5e09dSSadaf Ebrahimi 			m.data.v3[0].effective = 0xFFFFFFFFU;
370*8dd5e09dSSadaf Ebrahimi 			m.data.v3[0].permitted = 0xFFFFFFFFU;
371*8dd5e09dSSadaf Ebrahimi 			m.data.v3[0].inheritable = 0;
372*8dd5e09dSSadaf Ebrahimi 			m.data.v3[1].effective = 0xFFFFFFFFU;
373*8dd5e09dSSadaf Ebrahimi 			m.data.v3[1].permitted = 0xFFFFFFFFU;
374*8dd5e09dSSadaf Ebrahimi 			m.data.v3[1].inheritable = 0;
375*8dd5e09dSSadaf Ebrahimi 		}
376*8dd5e09dSSadaf Ebrahimi 	}
377*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
378*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
379*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_BOUNDS) {
380*8dd5e09dSSadaf Ebrahimi 		unsigned i;
381*8dd5e09dSSadaf Ebrahimi 		for (i=0; i<sizeof(m.bounds)/sizeof(__u32); i++)
382*8dd5e09dSSadaf Ebrahimi 			m.bounds[i] = 0xFFFFFFFFU;
383*8dd5e09dSSadaf Ebrahimi 	}
384*8dd5e09dSSadaf Ebrahimi }
385*8dd5e09dSSadaf Ebrahimi #endif
386*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
387*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
388*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_AMBIENT) {
389*8dd5e09dSSadaf Ebrahimi 		unsigned i;
390*8dd5e09dSSadaf Ebrahimi 		for (i=0; i<sizeof(m.ambient)/sizeof(__u32); i++)
391*8dd5e09dSSadaf Ebrahimi 			m.ambient[i] = 0xFFFFFFFFU;
392*8dd5e09dSSadaf Ebrahimi 	}
393*8dd5e09dSSadaf Ebrahimi }
394*8dd5e09dSSadaf Ebrahimi #endif
395*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_INIT;
396*8dd5e09dSSadaf Ebrahimi }
397*8dd5e09dSSadaf Ebrahimi 
capng_setpid(int pid)398*8dd5e09dSSadaf Ebrahimi void capng_setpid(int pid)
399*8dd5e09dSSadaf Ebrahimi {
400*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
401*8dd5e09dSSadaf Ebrahimi 		init();
402*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
403*8dd5e09dSSadaf Ebrahimi 		return;
404*8dd5e09dSSadaf Ebrahimi 
405*8dd5e09dSSadaf Ebrahimi 	m.hdr.pid = pid;
406*8dd5e09dSSadaf Ebrahimi }
407*8dd5e09dSSadaf Ebrahimi 
capng_get_rootid(void)408*8dd5e09dSSadaf Ebrahimi int capng_get_rootid(void)
409*8dd5e09dSSadaf Ebrahimi {
410*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
411*8dd5e09dSSadaf Ebrahimi 	return m.rootid;
412*8dd5e09dSSadaf Ebrahimi #else
413*8dd5e09dSSadaf Ebrahimi 	return CAPNG_UNSET_ROOTID;
414*8dd5e09dSSadaf Ebrahimi #endif
415*8dd5e09dSSadaf Ebrahimi }
416*8dd5e09dSSadaf Ebrahimi 
capng_set_rootid(int rootid)417*8dd5e09dSSadaf Ebrahimi int capng_set_rootid(int rootid)
418*8dd5e09dSSadaf Ebrahimi {
419*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
420*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
421*8dd5e09dSSadaf Ebrahimi 		init();
422*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
423*8dd5e09dSSadaf Ebrahimi 		return -1;
424*8dd5e09dSSadaf Ebrahimi 
425*8dd5e09dSSadaf Ebrahimi 	if (rootid < 0)
426*8dd5e09dSSadaf Ebrahimi 		return -1;
427*8dd5e09dSSadaf Ebrahimi 
428*8dd5e09dSSadaf Ebrahimi 	m.rootid = rootid;
429*8dd5e09dSSadaf Ebrahimi 	m.vfs_cap_ver = 3;
430*8dd5e09dSSadaf Ebrahimi 
431*8dd5e09dSSadaf Ebrahimi 	return 0;
432*8dd5e09dSSadaf Ebrahimi #else
433*8dd5e09dSSadaf Ebrahimi 	return -1;
434*8dd5e09dSSadaf Ebrahimi #endif
435*8dd5e09dSSadaf Ebrahimi }
436*8dd5e09dSSadaf Ebrahimi 
437*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
get_bounding_set(void)438*8dd5e09dSSadaf Ebrahimi static int get_bounding_set(void)
439*8dd5e09dSSadaf Ebrahimi {
440*8dd5e09dSSadaf Ebrahimi 	char buf[64];
441*8dd5e09dSSadaf Ebrahimi 	FILE *f;
442*8dd5e09dSSadaf Ebrahimi 	int rc;
443*8dd5e09dSSadaf Ebrahimi 
444*8dd5e09dSSadaf Ebrahimi 	snprintf(buf, sizeof(buf), "/proc/%d/status", m.hdr.pid ? m.hdr.pid :
445*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_SYSCALL_H
446*8dd5e09dSSadaf Ebrahimi 		(int)syscall(__NR_gettid));
447*8dd5e09dSSadaf Ebrahimi #else
448*8dd5e09dSSadaf Ebrahimi 		(int)getpid());
449*8dd5e09dSSadaf Ebrahimi #endif
450*8dd5e09dSSadaf Ebrahimi 	f = fopen(buf, "re");
451*8dd5e09dSSadaf Ebrahimi 	if (f) {
452*8dd5e09dSSadaf Ebrahimi 		__fsetlocking(f, FSETLOCKING_BYCALLER);
453*8dd5e09dSSadaf Ebrahimi 		while (fgets(buf, sizeof(buf), f)) {
454*8dd5e09dSSadaf Ebrahimi 			if (strncmp(buf, "CapB", 4))
455*8dd5e09dSSadaf Ebrahimi 				continue;
456*8dd5e09dSSadaf Ebrahimi 			sscanf(buf, "CapBnd:  %08x%08x",
457*8dd5e09dSSadaf Ebrahimi 			       &m.bounds[1], &m.bounds[0]);
458*8dd5e09dSSadaf Ebrahimi 			fclose(f);
459*8dd5e09dSSadaf Ebrahimi 			return 0;
460*8dd5e09dSSadaf Ebrahimi 		}
461*8dd5e09dSSadaf Ebrahimi 		// Didn't find bounding set, fall through and try prctl way
462*8dd5e09dSSadaf Ebrahimi 		fclose(f);
463*8dd5e09dSSadaf Ebrahimi 	}
464*8dd5e09dSSadaf Ebrahimi 	// Might be in a container with no procfs - do it the hard way
465*8dd5e09dSSadaf Ebrahimi 	memset(m.bounds, 0, sizeof(m.bounds));
466*8dd5e09dSSadaf Ebrahimi 	unsigned int i = 0;
467*8dd5e09dSSadaf Ebrahimi 	do {
468*8dd5e09dSSadaf Ebrahimi 		rc = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
469*8dd5e09dSSadaf Ebrahimi 		if (rc < 0)
470*8dd5e09dSSadaf Ebrahimi 			return -1;
471*8dd5e09dSSadaf Ebrahimi 
472*8dd5e09dSSadaf Ebrahimi 		// Just add set bits
473*8dd5e09dSSadaf Ebrahimi 		if (rc)
474*8dd5e09dSSadaf Ebrahimi 			update_bounding_set(CAPNG_ADD, i%32, i>>5);
475*8dd5e09dSSadaf Ebrahimi 		i++;
476*8dd5e09dSSadaf Ebrahimi 	} while (cap_valid(i));
477*8dd5e09dSSadaf Ebrahimi 
478*8dd5e09dSSadaf Ebrahimi 	return 0;
479*8dd5e09dSSadaf Ebrahimi }
480*8dd5e09dSSadaf Ebrahimi #endif
481*8dd5e09dSSadaf Ebrahimi 
482*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
get_ambient_set(void)483*8dd5e09dSSadaf Ebrahimi static int get_ambient_set(void)
484*8dd5e09dSSadaf Ebrahimi {
485*8dd5e09dSSadaf Ebrahimi 	char buf[64];
486*8dd5e09dSSadaf Ebrahimi 	FILE *f;
487*8dd5e09dSSadaf Ebrahimi 	int rc;
488*8dd5e09dSSadaf Ebrahimi 
489*8dd5e09dSSadaf Ebrahimi 	snprintf(buf, sizeof(buf), "/proc/%d/status", m.hdr.pid ? m.hdr.pid :
490*8dd5e09dSSadaf Ebrahimi #ifdef HAVE_SYSCALL_H
491*8dd5e09dSSadaf Ebrahimi 		(int)syscall(__NR_gettid));
492*8dd5e09dSSadaf Ebrahimi #else
493*8dd5e09dSSadaf Ebrahimi 		(int)getpid());
494*8dd5e09dSSadaf Ebrahimi #endif
495*8dd5e09dSSadaf Ebrahimi 	f = fopen(buf, "re");
496*8dd5e09dSSadaf Ebrahimi 	if (f) {
497*8dd5e09dSSadaf Ebrahimi 		__fsetlocking(f, FSETLOCKING_BYCALLER);
498*8dd5e09dSSadaf Ebrahimi 		while (fgets(buf, sizeof(buf), f)) {
499*8dd5e09dSSadaf Ebrahimi 			if (strncmp(buf, "CapA", 4))
500*8dd5e09dSSadaf Ebrahimi 				continue;
501*8dd5e09dSSadaf Ebrahimi 			sscanf(buf, "CapAmb:  %08x%08x",
502*8dd5e09dSSadaf Ebrahimi 			       &m.ambient[1], &m.ambient[0]);
503*8dd5e09dSSadaf Ebrahimi 			fclose(f);
504*8dd5e09dSSadaf Ebrahimi 			return 0;
505*8dd5e09dSSadaf Ebrahimi 		}
506*8dd5e09dSSadaf Ebrahimi 		fclose(f);
507*8dd5e09dSSadaf Ebrahimi 		// Didn't find ambient set, fall through and try prctl way
508*8dd5e09dSSadaf Ebrahimi 	}
509*8dd5e09dSSadaf Ebrahimi 	// Might be in a container with no procfs - do it the hard way
510*8dd5e09dSSadaf Ebrahimi 	memset(m.ambient, 0, sizeof(m.ambient));
511*8dd5e09dSSadaf Ebrahimi 	unsigned int i = 0;
512*8dd5e09dSSadaf Ebrahimi 	do {
513*8dd5e09dSSadaf Ebrahimi 		rc = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, i, 0, 0);
514*8dd5e09dSSadaf Ebrahimi 		if (rc < 0)
515*8dd5e09dSSadaf Ebrahimi 			return -1;
516*8dd5e09dSSadaf Ebrahimi 
517*8dd5e09dSSadaf Ebrahimi 		// Just add set bits
518*8dd5e09dSSadaf Ebrahimi 		if (rc)
519*8dd5e09dSSadaf Ebrahimi 			update_ambient_set(CAPNG_ADD, i%32, i>>5);
520*8dd5e09dSSadaf Ebrahimi 		i++;
521*8dd5e09dSSadaf Ebrahimi 	} while (cap_valid(i));
522*8dd5e09dSSadaf Ebrahimi 
523*8dd5e09dSSadaf Ebrahimi 	return 0;
524*8dd5e09dSSadaf Ebrahimi }
525*8dd5e09dSSadaf Ebrahimi #endif
526*8dd5e09dSSadaf Ebrahimi 
527*8dd5e09dSSadaf Ebrahimi /*
528*8dd5e09dSSadaf Ebrahimi  * Returns 0 on success and -1 on failure
529*8dd5e09dSSadaf Ebrahimi  */
capng_get_caps_process(void)530*8dd5e09dSSadaf Ebrahimi int capng_get_caps_process(void)
531*8dd5e09dSSadaf Ebrahimi {
532*8dd5e09dSSadaf Ebrahimi 	int rc;
533*8dd5e09dSSadaf Ebrahimi 
534*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
535*8dd5e09dSSadaf Ebrahimi 		init();
536*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
537*8dd5e09dSSadaf Ebrahimi 		return -1;
538*8dd5e09dSSadaf Ebrahimi 
539*8dd5e09dSSadaf Ebrahimi 	rc = capget((cap_user_header_t)&m.hdr, (cap_user_data_t)&m.data);
540*8dd5e09dSSadaf Ebrahimi 	if (rc == 0) {
541*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_INIT;
542*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
543*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
544*8dd5e09dSSadaf Ebrahimi 		rc = get_bounding_set();
545*8dd5e09dSSadaf Ebrahimi 		if (rc < 0)
546*8dd5e09dSSadaf Ebrahimi 			m.state = CAPNG_ERROR;
547*8dd5e09dSSadaf Ebrahimi }
548*8dd5e09dSSadaf Ebrahimi #endif
549*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
550*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
551*8dd5e09dSSadaf Ebrahimi 		rc = get_ambient_set();
552*8dd5e09dSSadaf Ebrahimi 		if (rc < 0)
553*8dd5e09dSSadaf Ebrahimi 			m.state = CAPNG_ERROR;
554*8dd5e09dSSadaf Ebrahimi }
555*8dd5e09dSSadaf Ebrahimi #endif
556*8dd5e09dSSadaf Ebrahimi 	}
557*8dd5e09dSSadaf Ebrahimi 
558*8dd5e09dSSadaf Ebrahimi 	return rc;
559*8dd5e09dSSadaf Ebrahimi }
560*8dd5e09dSSadaf Ebrahimi 
561*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_U32
562*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
load_data(const struct vfs_ns_cap_data * filedata,int size)563*8dd5e09dSSadaf Ebrahimi static int load_data(const struct vfs_ns_cap_data *filedata, int size)
564*8dd5e09dSSadaf Ebrahimi #else
565*8dd5e09dSSadaf Ebrahimi static int load_data(const struct vfs_cap_data *filedata, int size)
566*8dd5e09dSSadaf Ebrahimi #endif
567*8dd5e09dSSadaf Ebrahimi {
568*8dd5e09dSSadaf Ebrahimi 	unsigned int magic;
569*8dd5e09dSSadaf Ebrahimi 
570*8dd5e09dSSadaf Ebrahimi 	if (m.cap_ver == 1)
571*8dd5e09dSSadaf Ebrahimi 		return -1;	// Should never get here but just in case
572*8dd5e09dSSadaf Ebrahimi 
573*8dd5e09dSSadaf Ebrahimi 	magic = FIXUP(filedata->magic_etc);
574*8dd5e09dSSadaf Ebrahimi 	switch (magic & VFS_CAP_REVISION_MASK)
575*8dd5e09dSSadaf Ebrahimi 	{
576*8dd5e09dSSadaf Ebrahimi 		case VFS_CAP_REVISION_1:
577*8dd5e09dSSadaf Ebrahimi 			m.vfs_cap_ver = 1;
578*8dd5e09dSSadaf Ebrahimi 			if (size != XATTR_CAPS_SZ_1)
579*8dd5e09dSSadaf Ebrahimi 				return -1;
580*8dd5e09dSSadaf Ebrahimi 			break;
581*8dd5e09dSSadaf Ebrahimi 		case VFS_CAP_REVISION_2:
582*8dd5e09dSSadaf Ebrahimi 			m.vfs_cap_ver = 2;
583*8dd5e09dSSadaf Ebrahimi 			if (size != XATTR_CAPS_SZ_2)
584*8dd5e09dSSadaf Ebrahimi 				return -1;
585*8dd5e09dSSadaf Ebrahimi 			break;
586*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
587*8dd5e09dSSadaf Ebrahimi 		case VFS_CAP_REVISION_3:
588*8dd5e09dSSadaf Ebrahimi 			m.vfs_cap_ver = 3;
589*8dd5e09dSSadaf Ebrahimi 			if (size != XATTR_CAPS_SZ_3)
590*8dd5e09dSSadaf Ebrahimi 				return -1;
591*8dd5e09dSSadaf Ebrahimi 			break;
592*8dd5e09dSSadaf Ebrahimi #endif
593*8dd5e09dSSadaf Ebrahimi 		default:
594*8dd5e09dSSadaf Ebrahimi 			return -1;
595*8dd5e09dSSadaf Ebrahimi 	}
596*8dd5e09dSSadaf Ebrahimi 
597*8dd5e09dSSadaf Ebrahimi 	// Now stuff the data structures
598*8dd5e09dSSadaf Ebrahimi 	m.data.v3[0].permitted = FIXUP(filedata->data[0].permitted);
599*8dd5e09dSSadaf Ebrahimi 	m.data.v3[1].permitted = FIXUP(filedata->data[1].permitted);
600*8dd5e09dSSadaf Ebrahimi 	m.data.v3[0].inheritable = FIXUP(filedata->data[0].inheritable);
601*8dd5e09dSSadaf Ebrahimi 	m.data.v3[1].inheritable = FIXUP(filedata->data[1].inheritable);
602*8dd5e09dSSadaf Ebrahimi 	if (magic & VFS_CAP_FLAGS_EFFECTIVE) {
603*8dd5e09dSSadaf Ebrahimi 		m.data.v3[0].effective =
604*8dd5e09dSSadaf Ebrahimi 			m.data.v3[0].permitted | m.data.v3[0].inheritable;
605*8dd5e09dSSadaf Ebrahimi 		m.data.v3[1].effective =
606*8dd5e09dSSadaf Ebrahimi 			m.data.v3[1].permitted | m.data.v3[1].inheritable;
607*8dd5e09dSSadaf Ebrahimi 	} else {
608*8dd5e09dSSadaf Ebrahimi 		m.data.v3[0].effective = 0;
609*8dd5e09dSSadaf Ebrahimi 		m.data.v3[1].effective = 0;
610*8dd5e09dSSadaf Ebrahimi 	}
611*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
612*8dd5e09dSSadaf Ebrahimi 	if (size == XATTR_CAPS_SZ_3) {
613*8dd5e09dSSadaf Ebrahimi 	    struct vfs_ns_cap_data *d = (struct vfs_ns_cap_data *)filedata;
614*8dd5e09dSSadaf Ebrahimi 	    m.rootid = FIXUP(d->rootid);
615*8dd5e09dSSadaf Ebrahimi 	}
616*8dd5e09dSSadaf Ebrahimi #endif
617*8dd5e09dSSadaf Ebrahimi 	return 0;
618*8dd5e09dSSadaf Ebrahimi }
619*8dd5e09dSSadaf Ebrahimi #endif
620*8dd5e09dSSadaf Ebrahimi 
capng_get_caps_fd(int fd)621*8dd5e09dSSadaf Ebrahimi int capng_get_caps_fd(int fd)
622*8dd5e09dSSadaf Ebrahimi {
623*8dd5e09dSSadaf Ebrahimi #ifndef VFS_CAP_U32
624*8dd5e09dSSadaf Ebrahimi 	return -1;
625*8dd5e09dSSadaf Ebrahimi #else
626*8dd5e09dSSadaf Ebrahimi 	int rc;
627*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
628*8dd5e09dSSadaf Ebrahimi 	struct vfs_ns_cap_data filedata;
629*8dd5e09dSSadaf Ebrahimi #else
630*8dd5e09dSSadaf Ebrahimi 	struct vfs_cap_data filedata;
631*8dd5e09dSSadaf Ebrahimi #endif
632*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_NEW)
633*8dd5e09dSSadaf Ebrahimi 		init();
634*8dd5e09dSSadaf Ebrahimi 	if (m.state == CAPNG_ERROR)
635*8dd5e09dSSadaf Ebrahimi 		return -1;
636*8dd5e09dSSadaf Ebrahimi 
637*8dd5e09dSSadaf Ebrahimi 	rc = fgetxattr(fd, XATTR_NAME_CAPS, &filedata, sizeof(filedata));
638*8dd5e09dSSadaf Ebrahimi 	if (rc <= 0)
639*8dd5e09dSSadaf Ebrahimi 		return -1;
640*8dd5e09dSSadaf Ebrahimi 
641*8dd5e09dSSadaf Ebrahimi 	rc = load_data(&filedata, rc);
642*8dd5e09dSSadaf Ebrahimi 	if (rc == 0)
643*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_INIT;
644*8dd5e09dSSadaf Ebrahimi 	else
645*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_ERROR; // If load data failed, malformed data
646*8dd5e09dSSadaf Ebrahimi 
647*8dd5e09dSSadaf Ebrahimi 	return rc;
648*8dd5e09dSSadaf Ebrahimi #endif
649*8dd5e09dSSadaf Ebrahimi }
650*8dd5e09dSSadaf Ebrahimi 
v1_update(capng_act_t action,unsigned int capability,__u32 * data)651*8dd5e09dSSadaf Ebrahimi static void v1_update(capng_act_t action, unsigned int capability, __u32 *data)
652*8dd5e09dSSadaf Ebrahimi {
653*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
654*8dd5e09dSSadaf Ebrahimi 		*data |= MASK(capability);
655*8dd5e09dSSadaf Ebrahimi 	else
656*8dd5e09dSSadaf Ebrahimi 		*data &= ~(MASK(capability));
657*8dd5e09dSSadaf Ebrahimi }
658*8dd5e09dSSadaf Ebrahimi 
update_effective(capng_act_t action,unsigned int capability,unsigned int idx)659*8dd5e09dSSadaf Ebrahimi static void update_effective(capng_act_t action, unsigned int capability,
660*8dd5e09dSSadaf Ebrahimi 	unsigned int idx)
661*8dd5e09dSSadaf Ebrahimi {
662*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
663*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].effective |= MASK(capability);
664*8dd5e09dSSadaf Ebrahimi 	else
665*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].effective &= ~(MASK(capability));
666*8dd5e09dSSadaf Ebrahimi }
667*8dd5e09dSSadaf Ebrahimi 
update_permitted(capng_act_t action,unsigned int capability,unsigned int idx)668*8dd5e09dSSadaf Ebrahimi static void update_permitted(capng_act_t action, unsigned int capability,
669*8dd5e09dSSadaf Ebrahimi 	unsigned int idx)
670*8dd5e09dSSadaf Ebrahimi {
671*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
672*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].permitted |= MASK(capability);
673*8dd5e09dSSadaf Ebrahimi 	else
674*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].permitted &= ~(MASK(capability));
675*8dd5e09dSSadaf Ebrahimi }
676*8dd5e09dSSadaf Ebrahimi 
update_inheritable(capng_act_t action,unsigned int capability,unsigned int idx)677*8dd5e09dSSadaf Ebrahimi static void update_inheritable(capng_act_t action, unsigned int capability,
678*8dd5e09dSSadaf Ebrahimi 	unsigned int idx)
679*8dd5e09dSSadaf Ebrahimi {
680*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
681*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].inheritable |= MASK(capability);
682*8dd5e09dSSadaf Ebrahimi 	else
683*8dd5e09dSSadaf Ebrahimi 		m.data.v3[idx].inheritable &= ~(MASK(capability));
684*8dd5e09dSSadaf Ebrahimi }
685*8dd5e09dSSadaf Ebrahimi 
update_bounding_set(capng_act_t action,unsigned int capability,unsigned int idx)686*8dd5e09dSSadaf Ebrahimi static void update_bounding_set(capng_act_t action, unsigned int capability,
687*8dd5e09dSSadaf Ebrahimi 	unsigned int idx)
688*8dd5e09dSSadaf Ebrahimi {
689*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
690*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
691*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
692*8dd5e09dSSadaf Ebrahimi 		m.bounds[idx] |= MASK(capability);
693*8dd5e09dSSadaf Ebrahimi 	else
694*8dd5e09dSSadaf Ebrahimi 		m.bounds[idx] &= ~(MASK(capability));
695*8dd5e09dSSadaf Ebrahimi }
696*8dd5e09dSSadaf Ebrahimi #endif
697*8dd5e09dSSadaf Ebrahimi }
698*8dd5e09dSSadaf Ebrahimi 
update_ambient_set(capng_act_t action,unsigned int capability,unsigned int idx)699*8dd5e09dSSadaf Ebrahimi static void update_ambient_set(capng_act_t action, unsigned int capability,
700*8dd5e09dSSadaf Ebrahimi 	unsigned int idx)
701*8dd5e09dSSadaf Ebrahimi {
702*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
703*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
704*8dd5e09dSSadaf Ebrahimi 	if (action == CAPNG_ADD)
705*8dd5e09dSSadaf Ebrahimi 		m.ambient[idx] |= MASK(capability);
706*8dd5e09dSSadaf Ebrahimi 	else
707*8dd5e09dSSadaf Ebrahimi 		m.ambient[idx] &= ~(MASK(capability));
708*8dd5e09dSSadaf Ebrahimi }
709*8dd5e09dSSadaf Ebrahimi #endif
710*8dd5e09dSSadaf Ebrahimi }
711*8dd5e09dSSadaf Ebrahimi 
capng_update(capng_act_t action,capng_type_t type,unsigned int capability)712*8dd5e09dSSadaf Ebrahimi int capng_update(capng_act_t action, capng_type_t type, unsigned int capability)
713*8dd5e09dSSadaf Ebrahimi {
714*8dd5e09dSSadaf Ebrahimi 	// Before updating, we expect that the data is initialized to something
715*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
716*8dd5e09dSSadaf Ebrahimi 		return -1;
717*8dd5e09dSSadaf Ebrahimi 	if (!cap_valid(capability)) {
718*8dd5e09dSSadaf Ebrahimi 		errno = EINVAL;
719*8dd5e09dSSadaf Ebrahimi 		return -1;
720*8dd5e09dSSadaf Ebrahimi 	}
721*8dd5e09dSSadaf Ebrahimi 
722*8dd5e09dSSadaf Ebrahimi 	if (m.cap_ver == 1) {
723*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_EFFECTIVE & type)
724*8dd5e09dSSadaf Ebrahimi 			v1_update(action, capability, &m.data.v1.effective);
725*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_PERMITTED & type)
726*8dd5e09dSSadaf Ebrahimi 			v1_update(action, capability, &m.data.v1.permitted);
727*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_INHERITABLE & type)
728*8dd5e09dSSadaf Ebrahimi 			v1_update(action, capability, &m.data.v1.inheritable);
729*8dd5e09dSSadaf Ebrahimi 	} else {
730*8dd5e09dSSadaf Ebrahimi 		unsigned int idx;
731*8dd5e09dSSadaf Ebrahimi 
732*8dd5e09dSSadaf Ebrahimi 		if (capability > 31) {
733*8dd5e09dSSadaf Ebrahimi 			idx = capability>>5;
734*8dd5e09dSSadaf Ebrahimi 			capability %= 32;
735*8dd5e09dSSadaf Ebrahimi 		} else
736*8dd5e09dSSadaf Ebrahimi 			idx = 0;
737*8dd5e09dSSadaf Ebrahimi 
738*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_EFFECTIVE & type)
739*8dd5e09dSSadaf Ebrahimi 			update_effective(action, capability, idx);
740*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_PERMITTED & type)
741*8dd5e09dSSadaf Ebrahimi 			update_permitted(action, capability, idx);
742*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_INHERITABLE & type)
743*8dd5e09dSSadaf Ebrahimi 			update_inheritable(action, capability, idx);
744*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_BOUNDING_SET & type)
745*8dd5e09dSSadaf Ebrahimi 			update_bounding_set(action, capability, idx);
746*8dd5e09dSSadaf Ebrahimi 		if (CAPNG_AMBIENT & type)
747*8dd5e09dSSadaf Ebrahimi 			update_ambient_set(action, capability, idx);
748*8dd5e09dSSadaf Ebrahimi 	}
749*8dd5e09dSSadaf Ebrahimi 
750*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_UPDATED;
751*8dd5e09dSSadaf Ebrahimi 	return 0;
752*8dd5e09dSSadaf Ebrahimi }
753*8dd5e09dSSadaf Ebrahimi 
capng_updatev(capng_act_t action,capng_type_t type,unsigned int capability,...)754*8dd5e09dSSadaf Ebrahimi int capng_updatev(capng_act_t action, capng_type_t type,
755*8dd5e09dSSadaf Ebrahimi                 unsigned int capability, ...)
756*8dd5e09dSSadaf Ebrahimi {
757*8dd5e09dSSadaf Ebrahimi 	int rc;
758*8dd5e09dSSadaf Ebrahimi 	unsigned int cap;
759*8dd5e09dSSadaf Ebrahimi 	va_list ap;
760*8dd5e09dSSadaf Ebrahimi 
761*8dd5e09dSSadaf Ebrahimi 	rc = capng_update(action, type, capability);
762*8dd5e09dSSadaf Ebrahimi 	if (rc)
763*8dd5e09dSSadaf Ebrahimi 		return rc;
764*8dd5e09dSSadaf Ebrahimi 	va_start(ap, capability);
765*8dd5e09dSSadaf Ebrahimi 	cap = va_arg(ap, unsigned int);
766*8dd5e09dSSadaf Ebrahimi 	while (cap_valid(cap)) {
767*8dd5e09dSSadaf Ebrahimi 		rc = capng_update(action, type, cap);
768*8dd5e09dSSadaf Ebrahimi 		if (rc)
769*8dd5e09dSSadaf Ebrahimi 			break;
770*8dd5e09dSSadaf Ebrahimi 		cap = va_arg(ap, unsigned int);
771*8dd5e09dSSadaf Ebrahimi 	}
772*8dd5e09dSSadaf Ebrahimi 	va_end(ap);
773*8dd5e09dSSadaf Ebrahimi 
774*8dd5e09dSSadaf Ebrahimi 	// See if planned exit or invalid
775*8dd5e09dSSadaf Ebrahimi 	if (cap == (unsigned)-1)
776*8dd5e09dSSadaf Ebrahimi 		rc = 0;
777*8dd5e09dSSadaf Ebrahimi 	else {
778*8dd5e09dSSadaf Ebrahimi 		rc = -1;
779*8dd5e09dSSadaf Ebrahimi 		errno = EINVAL;
780*8dd5e09dSSadaf Ebrahimi 	}
781*8dd5e09dSSadaf Ebrahimi 
782*8dd5e09dSSadaf Ebrahimi 	return rc;
783*8dd5e09dSSadaf Ebrahimi }
784*8dd5e09dSSadaf Ebrahimi 
capng_apply(capng_select_t set)785*8dd5e09dSSadaf Ebrahimi int capng_apply(capng_select_t set)
786*8dd5e09dSSadaf Ebrahimi {
787*8dd5e09dSSadaf Ebrahimi 	int rc = 0;
788*8dd5e09dSSadaf Ebrahimi 
789*8dd5e09dSSadaf Ebrahimi 	// Before updating, we expect that the data is initialized to something
790*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
791*8dd5e09dSSadaf Ebrahimi 		return -1;
792*8dd5e09dSSadaf Ebrahimi 
793*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_BOUNDS) {
794*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
795*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
796*8dd5e09dSSadaf Ebrahimi 		struct cap_ng state;
797*8dd5e09dSSadaf Ebrahimi 		memcpy(&state, &m, sizeof(state)); /* save state */
798*8dd5e09dSSadaf Ebrahimi 		if (capng_get_caps_process())
799*8dd5e09dSSadaf Ebrahimi 			return -9;
800*8dd5e09dSSadaf Ebrahimi 		if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
801*8dd5e09dSSadaf Ebrahimi 			unsigned int i;
802*8dd5e09dSSadaf Ebrahimi 			memcpy(&m, &state, sizeof(m)); /* restore state */
803*8dd5e09dSSadaf Ebrahimi 			for (i=0; i <= last_cap; i++) {
804*8dd5e09dSSadaf Ebrahimi 				if (capng_have_capability(CAPNG_BOUNDING_SET,
805*8dd5e09dSSadaf Ebrahimi 								 i) == 0) {
806*8dd5e09dSSadaf Ebrahimi 				    if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0) <0) {
807*8dd5e09dSSadaf Ebrahimi 					rc = -2;
808*8dd5e09dSSadaf Ebrahimi 					goto try_caps;
809*8dd5e09dSSadaf Ebrahimi 				    }
810*8dd5e09dSSadaf Ebrahimi 				}
811*8dd5e09dSSadaf Ebrahimi 			}
812*8dd5e09dSSadaf Ebrahimi 			m.state = CAPNG_APPLIED;
813*8dd5e09dSSadaf Ebrahimi 			if (get_bounding_set() < 0) {
814*8dd5e09dSSadaf Ebrahimi 				rc = -3;
815*8dd5e09dSSadaf Ebrahimi 				goto try_caps;
816*8dd5e09dSSadaf Ebrahimi 			}
817*8dd5e09dSSadaf Ebrahimi 		} else {
818*8dd5e09dSSadaf Ebrahimi 			memcpy(&m, &state, sizeof(m)); /* restore state */
819*8dd5e09dSSadaf Ebrahimi 			rc = -4;
820*8dd5e09dSSadaf Ebrahimi 			goto try_caps;
821*8dd5e09dSSadaf Ebrahimi 		}
822*8dd5e09dSSadaf Ebrahimi }
823*8dd5e09dSSadaf Ebrahimi #endif
824*8dd5e09dSSadaf Ebrahimi 	}
825*8dd5e09dSSadaf Ebrahimi 
826*8dd5e09dSSadaf Ebrahimi 	// Try caps is here so that if someone had SELECT_BOTH and we blew up
827*8dd5e09dSSadaf Ebrahimi 	// doing the bounding set, we at least try to set any capabilities
828*8dd5e09dSSadaf Ebrahimi 	// before returning in case the caller also doesn't bother checking
829*8dd5e09dSSadaf Ebrahimi 	// the return code.
830*8dd5e09dSSadaf Ebrahimi try_caps:
831*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_CAPS) {
832*8dd5e09dSSadaf Ebrahimi 		if (capset((cap_user_header_t)&m.hdr,
833*8dd5e09dSSadaf Ebrahimi 				(cap_user_data_t)&m.data) == 0)
834*8dd5e09dSSadaf Ebrahimi 			m.state = CAPNG_APPLIED;
835*8dd5e09dSSadaf Ebrahimi 		else
836*8dd5e09dSSadaf Ebrahimi 			rc = -5;
837*8dd5e09dSSadaf Ebrahimi 	}
838*8dd5e09dSSadaf Ebrahimi 
839*8dd5e09dSSadaf Ebrahimi 	// Most programs do not and should not mess with ambient capabilities.
840*8dd5e09dSSadaf Ebrahimi 	// Instead of returning here if rc is set, we'll let it try to
841*8dd5e09dSSadaf Ebrahimi 	// do something with ambient capabilities in hopes that it's lowering
842*8dd5e09dSSadaf Ebrahimi 	// capabilities. Again, this is for people that don't check their
843*8dd5e09dSSadaf Ebrahimi 	// return codes.
844*8dd5e09dSSadaf Ebrahimi 	//
845*8dd5e09dSSadaf Ebrahimi 	// Do ambient last so that inheritable and permitted are set by the
846*8dd5e09dSSadaf Ebrahimi 	// time we get here.
847*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_AMBIENT) {
848*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
849*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
850*8dd5e09dSSadaf Ebrahimi 		if (capng_have_capabilities(CAPNG_SELECT_AMBIENT) ==
851*8dd5e09dSSadaf Ebrahimi 								CAPNG_NONE) {
852*8dd5e09dSSadaf Ebrahimi 			if (prctl(PR_CAP_AMBIENT,
853*8dd5e09dSSadaf Ebrahimi 				   PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) < 0) {
854*8dd5e09dSSadaf Ebrahimi 				rc = -6;
855*8dd5e09dSSadaf Ebrahimi 				goto out;
856*8dd5e09dSSadaf Ebrahimi 			}
857*8dd5e09dSSadaf Ebrahimi 		} else {
858*8dd5e09dSSadaf Ebrahimi 			unsigned int i;
859*8dd5e09dSSadaf Ebrahimi 
860*8dd5e09dSSadaf Ebrahimi 			// Clear them all
861*8dd5e09dSSadaf Ebrahimi 			if (prctl(PR_CAP_AMBIENT,
862*8dd5e09dSSadaf Ebrahimi 				   PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) < 0) {
863*8dd5e09dSSadaf Ebrahimi 				rc = -7;
864*8dd5e09dSSadaf Ebrahimi 				goto out;
865*8dd5e09dSSadaf Ebrahimi 			}
866*8dd5e09dSSadaf Ebrahimi 			for (i=0; i <= last_cap; i++) {
867*8dd5e09dSSadaf Ebrahimi 				if (capng_have_capability(CAPNG_AMBIENT, i))
868*8dd5e09dSSadaf Ebrahimi 					if (prctl(PR_CAP_AMBIENT,
869*8dd5e09dSSadaf Ebrahimi 					    PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0){
870*8dd5e09dSSadaf Ebrahimi 						rc = -8;
871*8dd5e09dSSadaf Ebrahimi 						goto out;
872*8dd5e09dSSadaf Ebrahimi 					}
873*8dd5e09dSSadaf Ebrahimi 			}
874*8dd5e09dSSadaf Ebrahimi 		}
875*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_APPLIED;
876*8dd5e09dSSadaf Ebrahimi }
877*8dd5e09dSSadaf Ebrahimi #endif
878*8dd5e09dSSadaf Ebrahimi 	}
879*8dd5e09dSSadaf Ebrahimi out:
880*8dd5e09dSSadaf Ebrahimi 	return rc;
881*8dd5e09dSSadaf Ebrahimi }
882*8dd5e09dSSadaf Ebrahimi 
883*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_U32
884*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
save_data(struct vfs_ns_cap_data * filedata,int * size)885*8dd5e09dSSadaf Ebrahimi static int save_data(struct vfs_ns_cap_data *filedata, int *size)
886*8dd5e09dSSadaf Ebrahimi #else
887*8dd5e09dSSadaf Ebrahimi static int save_data(struct vfs_cap_data *filedata, int *size)
888*8dd5e09dSSadaf Ebrahimi #endif
889*8dd5e09dSSadaf Ebrahimi {
890*8dd5e09dSSadaf Ebrahimi 	// Now stuff the data structures
891*8dd5e09dSSadaf Ebrahimi 	if (m.vfs_cap_ver == 1) {
892*8dd5e09dSSadaf Ebrahimi 		filedata->data[0].permitted = FIXUP(m.data.v1.permitted);
893*8dd5e09dSSadaf Ebrahimi 		filedata->data[0].inheritable = FIXUP(m.data.v1.inheritable);
894*8dd5e09dSSadaf Ebrahimi 		filedata->magic_etc = FIXUP(VFS_CAP_REVISION_1);
895*8dd5e09dSSadaf Ebrahimi 		*size = XATTR_CAPS_SZ_1;
896*8dd5e09dSSadaf Ebrahimi 	} else if (m.vfs_cap_ver == 2 || m.vfs_cap_ver == 3) {
897*8dd5e09dSSadaf Ebrahimi 		int eff;
898*8dd5e09dSSadaf Ebrahimi 
899*8dd5e09dSSadaf Ebrahimi 		if (m.data.v3[0].effective || m.data.v3[1].effective)
900*8dd5e09dSSadaf Ebrahimi 			eff = VFS_CAP_FLAGS_EFFECTIVE;
901*8dd5e09dSSadaf Ebrahimi 		else
902*8dd5e09dSSadaf Ebrahimi 			eff = 0;
903*8dd5e09dSSadaf Ebrahimi 		filedata->data[0].permitted = FIXUP(m.data.v3[0].permitted);
904*8dd5e09dSSadaf Ebrahimi 		filedata->data[0].inheritable = FIXUP(m.data.v3[0].inheritable);
905*8dd5e09dSSadaf Ebrahimi 		filedata->data[1].permitted = FIXUP(m.data.v3[1].permitted);
906*8dd5e09dSSadaf Ebrahimi 		filedata->data[1].inheritable = FIXUP(m.data.v3[1].inheritable);
907*8dd5e09dSSadaf Ebrahimi 		filedata->magic_etc = FIXUP(VFS_CAP_REVISION_2 | eff);
908*8dd5e09dSSadaf Ebrahimi 		*size = XATTR_CAPS_SZ_2;
909*8dd5e09dSSadaf Ebrahimi 	}
910*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
911*8dd5e09dSSadaf Ebrahimi 	if (m.vfs_cap_ver == 3) {
912*8dd5e09dSSadaf Ebrahimi 		// Kernel doesn't support namespaces with non-0 rootid
913*8dd5e09dSSadaf Ebrahimi 		if (m.rootid!= 0)
914*8dd5e09dSSadaf Ebrahimi 			return -1;
915*8dd5e09dSSadaf Ebrahimi 		filedata->rootid = FIXUP(m.rootid);
916*8dd5e09dSSadaf Ebrahimi 		*size = XATTR_CAPS_SZ_3;
917*8dd5e09dSSadaf Ebrahimi 	}
918*8dd5e09dSSadaf Ebrahimi #endif
919*8dd5e09dSSadaf Ebrahimi 
920*8dd5e09dSSadaf Ebrahimi 	return 0;
921*8dd5e09dSSadaf Ebrahimi }
922*8dd5e09dSSadaf Ebrahimi #endif
923*8dd5e09dSSadaf Ebrahimi 
capng_apply_caps_fd(int fd)924*8dd5e09dSSadaf Ebrahimi int capng_apply_caps_fd(int fd)
925*8dd5e09dSSadaf Ebrahimi {
926*8dd5e09dSSadaf Ebrahimi #ifndef VFS_CAP_U32
927*8dd5e09dSSadaf Ebrahimi 	return -1;
928*8dd5e09dSSadaf Ebrahimi #else
929*8dd5e09dSSadaf Ebrahimi 	int rc, size = 0;
930*8dd5e09dSSadaf Ebrahimi #ifdef VFS_CAP_REVISION_3
931*8dd5e09dSSadaf Ebrahimi 	struct vfs_ns_cap_data filedata;
932*8dd5e09dSSadaf Ebrahimi #else
933*8dd5e09dSSadaf Ebrahimi 	struct vfs_cap_data filedata;
934*8dd5e09dSSadaf Ebrahimi #endif
935*8dd5e09dSSadaf Ebrahimi 	struct stat buf;
936*8dd5e09dSSadaf Ebrahimi 
937*8dd5e09dSSadaf Ebrahimi 	// Before updating, we expect that the data is initialized to something
938*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
939*8dd5e09dSSadaf Ebrahimi 		return -1;
940*8dd5e09dSSadaf Ebrahimi 
941*8dd5e09dSSadaf Ebrahimi 	if (fstat(fd, &buf) != 0)
942*8dd5e09dSSadaf Ebrahimi 		return -1;
943*8dd5e09dSSadaf Ebrahimi 	if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
944*8dd5e09dSSadaf Ebrahimi 		errno = EINVAL;
945*8dd5e09dSSadaf Ebrahimi 		return -1;
946*8dd5e09dSSadaf Ebrahimi 	}
947*8dd5e09dSSadaf Ebrahimi 	if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE)
948*8dd5e09dSSadaf Ebrahimi 		rc = fremovexattr(fd, XATTR_NAME_CAPS);
949*8dd5e09dSSadaf Ebrahimi 	else {
950*8dd5e09dSSadaf Ebrahimi 		if (save_data(&filedata, &size)) {
951*8dd5e09dSSadaf Ebrahimi 			m.state = CAPNG_ERROR;
952*8dd5e09dSSadaf Ebrahimi 			errno = EINVAL;
953*8dd5e09dSSadaf Ebrahimi 			return -2;
954*8dd5e09dSSadaf Ebrahimi 		}
955*8dd5e09dSSadaf Ebrahimi 		rc = fsetxattr(fd, XATTR_NAME_CAPS, &filedata, size, 0);
956*8dd5e09dSSadaf Ebrahimi 	}
957*8dd5e09dSSadaf Ebrahimi 
958*8dd5e09dSSadaf Ebrahimi 	if (rc == 0)
959*8dd5e09dSSadaf Ebrahimi 		m.state = CAPNG_APPLIED;
960*8dd5e09dSSadaf Ebrahimi 
961*8dd5e09dSSadaf Ebrahimi 	return rc;
962*8dd5e09dSSadaf Ebrahimi #endif
963*8dd5e09dSSadaf Ebrahimi }
964*8dd5e09dSSadaf Ebrahimi 
965*8dd5e09dSSadaf Ebrahimi // Change uids keeping/removing only certain capabilities
966*8dd5e09dSSadaf Ebrahimi // flag to drop supp groups
capng_change_id(int uid,int gid,capng_flags_t flag)967*8dd5e09dSSadaf Ebrahimi int capng_change_id(int uid, int gid, capng_flags_t flag)
968*8dd5e09dSSadaf Ebrahimi {
969*8dd5e09dSSadaf Ebrahimi 	int rc, ret, need_setgid, need_setuid;
970*8dd5e09dSSadaf Ebrahimi 
971*8dd5e09dSSadaf Ebrahimi 	// Before updating, we expect that the data is initialized to something
972*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
973*8dd5e09dSSadaf Ebrahimi 		return -1;
974*8dd5e09dSSadaf Ebrahimi 
975*8dd5e09dSSadaf Ebrahimi 	// Check the current capabilities
976*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
977*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
978*8dd5e09dSSadaf Ebrahimi 	// If newer kernel, we need setpcap to change the bounding set
979*8dd5e09dSSadaf Ebrahimi 	if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP) == 0 &&
980*8dd5e09dSSadaf Ebrahimi 					flag & CAPNG_CLEAR_BOUNDING)
981*8dd5e09dSSadaf Ebrahimi 		capng_update(CAPNG_ADD,
982*8dd5e09dSSadaf Ebrahimi 				CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
983*8dd5e09dSSadaf Ebrahimi }
984*8dd5e09dSSadaf Ebrahimi #endif
985*8dd5e09dSSadaf Ebrahimi 	if (gid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETGID))
986*8dd5e09dSSadaf Ebrahimi 		need_setgid = 0;
987*8dd5e09dSSadaf Ebrahimi 	else {
988*8dd5e09dSSadaf Ebrahimi 		need_setgid = 1;
989*8dd5e09dSSadaf Ebrahimi 		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
990*8dd5e09dSSadaf Ebrahimi 				CAP_SETGID);
991*8dd5e09dSSadaf Ebrahimi 	}
992*8dd5e09dSSadaf Ebrahimi 	if (uid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETUID))
993*8dd5e09dSSadaf Ebrahimi 		need_setuid = 0;
994*8dd5e09dSSadaf Ebrahimi 	else {
995*8dd5e09dSSadaf Ebrahimi 		need_setuid = 1;
996*8dd5e09dSSadaf Ebrahimi 		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
997*8dd5e09dSSadaf Ebrahimi 				CAP_SETUID);
998*8dd5e09dSSadaf Ebrahimi 	}
999*8dd5e09dSSadaf Ebrahimi 
1000*8dd5e09dSSadaf Ebrahimi 	// Tell system we want to keep caps across uid change
1001*8dd5e09dSSadaf Ebrahimi 	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0))
1002*8dd5e09dSSadaf Ebrahimi 		return -2;
1003*8dd5e09dSSadaf Ebrahimi 
1004*8dd5e09dSSadaf Ebrahimi 	// Change to the temp capabilities
1005*8dd5e09dSSadaf Ebrahimi 	rc = capng_apply(CAPNG_SELECT_CAPS);
1006*8dd5e09dSSadaf Ebrahimi 	if (rc < 0) {
1007*8dd5e09dSSadaf Ebrahimi 		ret = -3;
1008*8dd5e09dSSadaf Ebrahimi 		goto err_out;
1009*8dd5e09dSSadaf Ebrahimi 	}
1010*8dd5e09dSSadaf Ebrahimi 
1011*8dd5e09dSSadaf Ebrahimi 	// If we are clearing ambient, only clear since its applied at the end
1012*8dd5e09dSSadaf Ebrahimi 	if (flag & CAPNG_CLEAR_AMBIENT)
1013*8dd5e09dSSadaf Ebrahimi 		capng_clear(CAPNG_SELECT_AMBIENT);
1014*8dd5e09dSSadaf Ebrahimi 
1015*8dd5e09dSSadaf Ebrahimi 	// Clear bounding set if needed while we have CAP_SETPCAP
1016*8dd5e09dSSadaf Ebrahimi 	if (flag & CAPNG_CLEAR_BOUNDING) {
1017*8dd5e09dSSadaf Ebrahimi 		capng_clear(CAPNG_SELECT_BOUNDS);
1018*8dd5e09dSSadaf Ebrahimi 		rc = capng_apply(CAPNG_SELECT_BOUNDS);
1019*8dd5e09dSSadaf Ebrahimi 		if (rc) {
1020*8dd5e09dSSadaf Ebrahimi 			ret = -8;
1021*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1022*8dd5e09dSSadaf Ebrahimi 		}
1023*8dd5e09dSSadaf Ebrahimi 	}
1024*8dd5e09dSSadaf Ebrahimi 
1025*8dd5e09dSSadaf Ebrahimi 	// Change gid
1026*8dd5e09dSSadaf Ebrahimi 	if (gid != -1) {
1027*8dd5e09dSSadaf Ebrahimi 		rc = setresgid(gid, gid, gid);
1028*8dd5e09dSSadaf Ebrahimi 		if (rc) {
1029*8dd5e09dSSadaf Ebrahimi 			ret = -4;
1030*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1031*8dd5e09dSSadaf Ebrahimi 		}
1032*8dd5e09dSSadaf Ebrahimi 	}
1033*8dd5e09dSSadaf Ebrahimi 
1034*8dd5e09dSSadaf Ebrahimi 	// See if we need to init supplemental groups
1035*8dd5e09dSSadaf Ebrahimi 	if ((flag & CAPNG_INIT_SUPP_GRP) && uid != -1) {
1036*8dd5e09dSSadaf Ebrahimi 		struct passwd *pw = getpwuid(uid);
1037*8dd5e09dSSadaf Ebrahimi 		if (pw == NULL) {
1038*8dd5e09dSSadaf Ebrahimi 			ret = -10;
1039*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1040*8dd5e09dSSadaf Ebrahimi 		}
1041*8dd5e09dSSadaf Ebrahimi 		if (gid != -1) {
1042*8dd5e09dSSadaf Ebrahimi 			if (initgroups(pw->pw_name, gid)) {
1043*8dd5e09dSSadaf Ebrahimi 				ret = -5;
1044*8dd5e09dSSadaf Ebrahimi 				goto err_out;
1045*8dd5e09dSSadaf Ebrahimi 			}
1046*8dd5e09dSSadaf Ebrahimi 		} else if (initgroups(pw->pw_name, pw->pw_gid)) {
1047*8dd5e09dSSadaf Ebrahimi 			ret = -5;
1048*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1049*8dd5e09dSSadaf Ebrahimi 		}
1050*8dd5e09dSSadaf Ebrahimi 	}
1051*8dd5e09dSSadaf Ebrahimi 
1052*8dd5e09dSSadaf Ebrahimi 	// See if we need to unload supplemental groups
1053*8dd5e09dSSadaf Ebrahimi 	if ((flag & CAPNG_DROP_SUPP_GRP) && gid != -1) {
1054*8dd5e09dSSadaf Ebrahimi 		if (setgroups(0, NULL)) {
1055*8dd5e09dSSadaf Ebrahimi 			ret = -5;
1056*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1057*8dd5e09dSSadaf Ebrahimi 		}
1058*8dd5e09dSSadaf Ebrahimi 	}
1059*8dd5e09dSSadaf Ebrahimi 
1060*8dd5e09dSSadaf Ebrahimi 	// Change uid
1061*8dd5e09dSSadaf Ebrahimi 	if (uid != -1) {
1062*8dd5e09dSSadaf Ebrahimi 		rc = setresuid(uid, uid, uid);
1063*8dd5e09dSSadaf Ebrahimi 		if (rc) {
1064*8dd5e09dSSadaf Ebrahimi 			ret = -6;
1065*8dd5e09dSSadaf Ebrahimi 			goto err_out;
1066*8dd5e09dSSadaf Ebrahimi 		}
1067*8dd5e09dSSadaf Ebrahimi 	}
1068*8dd5e09dSSadaf Ebrahimi 
1069*8dd5e09dSSadaf Ebrahimi 	// Tell it we are done keeping capabilities
1070*8dd5e09dSSadaf Ebrahimi 	rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
1071*8dd5e09dSSadaf Ebrahimi 	if (rc)
1072*8dd5e09dSSadaf Ebrahimi 		return -7;
1073*8dd5e09dSSadaf Ebrahimi 
1074*8dd5e09dSSadaf Ebrahimi 	// Now throw away CAP_SETPCAP so no more changes
1075*8dd5e09dSSadaf Ebrahimi 	if (need_setgid)
1076*8dd5e09dSSadaf Ebrahimi 		capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
1077*8dd5e09dSSadaf Ebrahimi 				CAP_SETGID);
1078*8dd5e09dSSadaf Ebrahimi 	if (need_setuid)
1079*8dd5e09dSSadaf Ebrahimi 		capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
1080*8dd5e09dSSadaf Ebrahimi 				CAP_SETUID);
1081*8dd5e09dSSadaf Ebrahimi 
1082*8dd5e09dSSadaf Ebrahimi 	// Now drop setpcap & apply
1083*8dd5e09dSSadaf Ebrahimi 	capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
1084*8dd5e09dSSadaf Ebrahimi 				CAP_SETPCAP);
1085*8dd5e09dSSadaf Ebrahimi 	rc = capng_apply(CAPNG_SELECT_CAPS|CAPNG_SELECT_AMBIENT);
1086*8dd5e09dSSadaf Ebrahimi 	if (rc < 0)
1087*8dd5e09dSSadaf Ebrahimi 		return -9;
1088*8dd5e09dSSadaf Ebrahimi 
1089*8dd5e09dSSadaf Ebrahimi 	// Done
1090*8dd5e09dSSadaf Ebrahimi 	m.state = CAPNG_UPDATED;
1091*8dd5e09dSSadaf Ebrahimi 	return 0;
1092*8dd5e09dSSadaf Ebrahimi 
1093*8dd5e09dSSadaf Ebrahimi err_out:
1094*8dd5e09dSSadaf Ebrahimi 	prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
1095*8dd5e09dSSadaf Ebrahimi 	return ret;
1096*8dd5e09dSSadaf Ebrahimi }
1097*8dd5e09dSSadaf Ebrahimi 
capng_lock(void)1098*8dd5e09dSSadaf Ebrahimi int capng_lock(void)
1099*8dd5e09dSSadaf Ebrahimi {
1100*8dd5e09dSSadaf Ebrahimi 	// If either fail, return -1 since something is not right
1101*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_SECUREBITS
1102*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_SET_SECUREBITS) {
1103*8dd5e09dSSadaf Ebrahimi 	int rc = prctl(PR_SET_SECUREBITS,
1104*8dd5e09dSSadaf Ebrahimi 			1 << SECURE_NOROOT |
1105*8dd5e09dSSadaf Ebrahimi 			1 << SECURE_NOROOT_LOCKED |
1106*8dd5e09dSSadaf Ebrahimi 			1 << SECURE_NO_SETUID_FIXUP |
1107*8dd5e09dSSadaf Ebrahimi 			1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0);
1108*8dd5e09dSSadaf Ebrahimi #ifdef PR_SET_NO_NEW_PRIVS
1109*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_SET_NO_NEW_PRIVS) {
1110*8dd5e09dSSadaf Ebrahimi 	if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
1111*8dd5e09dSSadaf Ebrahimi 		return -1;
1112*8dd5e09dSSadaf Ebrahimi }
1113*8dd5e09dSSadaf Ebrahimi #endif
1114*8dd5e09dSSadaf Ebrahimi 	if (rc)
1115*8dd5e09dSSadaf Ebrahimi 		return -1;
1116*8dd5e09dSSadaf Ebrahimi }
1117*8dd5e09dSSadaf Ebrahimi #endif
1118*8dd5e09dSSadaf Ebrahimi 
1119*8dd5e09dSSadaf Ebrahimi 	return 0;
1120*8dd5e09dSSadaf Ebrahimi }
1121*8dd5e09dSSadaf Ebrahimi 
1122*8dd5e09dSSadaf Ebrahimi // -1 - error, 0 - no caps, 1 partial caps, 2 full caps
capng_have_capabilities(capng_select_t set)1123*8dd5e09dSSadaf Ebrahimi capng_results_t capng_have_capabilities(capng_select_t set)
1124*8dd5e09dSSadaf Ebrahimi {
1125*8dd5e09dSSadaf Ebrahimi 	int empty = 0, full = 0;
1126*8dd5e09dSSadaf Ebrahimi 
1127*8dd5e09dSSadaf Ebrahimi 	// First, try to init with current set
1128*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT) {
1129*8dd5e09dSSadaf Ebrahimi 		if (capng_get_caps_process())
1130*8dd5e09dSSadaf Ebrahimi 			return CAPNG_FAIL;
1131*8dd5e09dSSadaf Ebrahimi 	}
1132*8dd5e09dSSadaf Ebrahimi 
1133*8dd5e09dSSadaf Ebrahimi 	// If we still don't have anything, error out
1134*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
1135*8dd5e09dSSadaf Ebrahimi 		return CAPNG_FAIL;
1136*8dd5e09dSSadaf Ebrahimi 
1137*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_CAPS) {
1138*8dd5e09dSSadaf Ebrahimi 		if (m.cap_ver == 1) {
1139*8dd5e09dSSadaf Ebrahimi 			if (m.data.v1.effective == 0)
1140*8dd5e09dSSadaf Ebrahimi 				empty = 1;
1141*8dd5e09dSSadaf Ebrahimi 			// after fill, 30 bits starts from upper to lower
1142*8dd5e09dSSadaf Ebrahimi 			else if (m.data.v1.effective == 0x7FFFFFFFU)
1143*8dd5e09dSSadaf Ebrahimi 				full = 1;
1144*8dd5e09dSSadaf Ebrahimi 			// actual capabilities read from system
1145*8dd5e09dSSadaf Ebrahimi 			else if (m.data.v1.effective == 0xFFFFFEFFU)
1146*8dd5e09dSSadaf Ebrahimi 				full = 1;
1147*8dd5e09dSSadaf Ebrahimi 			else
1148*8dd5e09dSSadaf Ebrahimi 				return CAPNG_PARTIAL;
1149*8dd5e09dSSadaf Ebrahimi 		} else {
1150*8dd5e09dSSadaf Ebrahimi 			if (m.data.v3[0].effective == 0)
1151*8dd5e09dSSadaf Ebrahimi 				empty = 1;
1152*8dd5e09dSSadaf Ebrahimi 			else if (m.data.v3[0].effective == 0xFFFFFFFFU)
1153*8dd5e09dSSadaf Ebrahimi 				full = 1;
1154*8dd5e09dSSadaf Ebrahimi 			else
1155*8dd5e09dSSadaf Ebrahimi 				return CAPNG_PARTIAL;
1156*8dd5e09dSSadaf Ebrahimi 			if ((m.data.v3[1].effective & UPPER_MASK) == 0 && !full)
1157*8dd5e09dSSadaf Ebrahimi 				empty = 1;
1158*8dd5e09dSSadaf Ebrahimi 			else if ((m.data.v3[1].effective & UPPER_MASK) ==
1159*8dd5e09dSSadaf Ebrahimi 						UPPER_MASK && !empty)
1160*8dd5e09dSSadaf Ebrahimi 				full = 1;
1161*8dd5e09dSSadaf Ebrahimi 			else
1162*8dd5e09dSSadaf Ebrahimi 				return CAPNG_PARTIAL;
1163*8dd5e09dSSadaf Ebrahimi 		}
1164*8dd5e09dSSadaf Ebrahimi 	}
1165*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
1166*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
1167*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_BOUNDS) {
1168*8dd5e09dSSadaf Ebrahimi 		if (m.bounds[0] == 0)
1169*8dd5e09dSSadaf Ebrahimi 			empty = 1;
1170*8dd5e09dSSadaf Ebrahimi 		else if (m.bounds[0] == 0xFFFFFFFFU)
1171*8dd5e09dSSadaf Ebrahimi 			full = 1;
1172*8dd5e09dSSadaf Ebrahimi 		else
1173*8dd5e09dSSadaf Ebrahimi 			return CAPNG_PARTIAL;
1174*8dd5e09dSSadaf Ebrahimi 		if ((m.bounds[1] & UPPER_MASK) == 0)
1175*8dd5e09dSSadaf Ebrahimi 			empty = 1;
1176*8dd5e09dSSadaf Ebrahimi 		else if ((m.bounds[1] & UPPER_MASK) == UPPER_MASK)
1177*8dd5e09dSSadaf Ebrahimi 			full = 1;
1178*8dd5e09dSSadaf Ebrahimi 		else
1179*8dd5e09dSSadaf Ebrahimi 			return CAPNG_PARTIAL;
1180*8dd5e09dSSadaf Ebrahimi 	}
1181*8dd5e09dSSadaf Ebrahimi } else
1182*8dd5e09dSSadaf Ebrahimi 	empty = 1;
1183*8dd5e09dSSadaf Ebrahimi #endif
1184*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
1185*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
1186*8dd5e09dSSadaf Ebrahimi 	if (set & CAPNG_SELECT_AMBIENT) {
1187*8dd5e09dSSadaf Ebrahimi 		if (m.ambient[0] == 0)
1188*8dd5e09dSSadaf Ebrahimi 			empty = 1;
1189*8dd5e09dSSadaf Ebrahimi 		else if (m.ambient[0] == 0xFFFFFFFFU)
1190*8dd5e09dSSadaf Ebrahimi 			full = 1;
1191*8dd5e09dSSadaf Ebrahimi 		else
1192*8dd5e09dSSadaf Ebrahimi 			return CAPNG_PARTIAL;
1193*8dd5e09dSSadaf Ebrahimi 		if ((m.ambient[1] & UPPER_MASK) == 0)
1194*8dd5e09dSSadaf Ebrahimi 			empty = 1;
1195*8dd5e09dSSadaf Ebrahimi 		else if ((m.ambient[1] & UPPER_MASK) == UPPER_MASK)
1196*8dd5e09dSSadaf Ebrahimi 			full = 1;
1197*8dd5e09dSSadaf Ebrahimi 		else
1198*8dd5e09dSSadaf Ebrahimi 			return CAPNG_PARTIAL;
1199*8dd5e09dSSadaf Ebrahimi 	}
1200*8dd5e09dSSadaf Ebrahimi } else
1201*8dd5e09dSSadaf Ebrahimi 	empty = 1;
1202*8dd5e09dSSadaf Ebrahimi #endif
1203*8dd5e09dSSadaf Ebrahimi 	if (empty == 1 && full == 0)
1204*8dd5e09dSSadaf Ebrahimi 		return CAPNG_NONE;
1205*8dd5e09dSSadaf Ebrahimi 	else if (empty == 0 && full == 1)
1206*8dd5e09dSSadaf Ebrahimi 		return CAPNG_FULL;
1207*8dd5e09dSSadaf Ebrahimi 
1208*8dd5e09dSSadaf Ebrahimi 	return CAPNG_PARTIAL;
1209*8dd5e09dSSadaf Ebrahimi }
1210*8dd5e09dSSadaf Ebrahimi 
1211*8dd5e09dSSadaf Ebrahimi // -1 - error, 0 - no caps, 1 partial caps, 2 full caps
capng_have_permitted_capabilities(void)1212*8dd5e09dSSadaf Ebrahimi capng_results_t capng_have_permitted_capabilities(void)
1213*8dd5e09dSSadaf Ebrahimi {
1214*8dd5e09dSSadaf Ebrahimi 	int empty = 0, full = 0;
1215*8dd5e09dSSadaf Ebrahimi 
1216*8dd5e09dSSadaf Ebrahimi 	// First, try to init with current set
1217*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT) {
1218*8dd5e09dSSadaf Ebrahimi 		if (capng_get_caps_process())
1219*8dd5e09dSSadaf Ebrahimi 			return CAPNG_FAIL;
1220*8dd5e09dSSadaf Ebrahimi 	}
1221*8dd5e09dSSadaf Ebrahimi 
1222*8dd5e09dSSadaf Ebrahimi 	// If we still don't have anything, error out
1223*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
1224*8dd5e09dSSadaf Ebrahimi 		return CAPNG_FAIL;
1225*8dd5e09dSSadaf Ebrahimi 
1226*8dd5e09dSSadaf Ebrahimi 	if (m.data.v3[0].permitted == 0)
1227*8dd5e09dSSadaf Ebrahimi 		empty = 1;
1228*8dd5e09dSSadaf Ebrahimi 	else if (m.data.v3[0].permitted == 0xFFFFFFFFU)
1229*8dd5e09dSSadaf Ebrahimi 		full = 1;
1230*8dd5e09dSSadaf Ebrahimi 	else
1231*8dd5e09dSSadaf Ebrahimi 		return CAPNG_PARTIAL;
1232*8dd5e09dSSadaf Ebrahimi 
1233*8dd5e09dSSadaf Ebrahimi 	if ((m.data.v3[1].permitted & UPPER_MASK) == 0 && !full)
1234*8dd5e09dSSadaf Ebrahimi 		empty = 1;
1235*8dd5e09dSSadaf Ebrahimi 	else if ((m.data.v3[1].permitted & UPPER_MASK) == UPPER_MASK && !empty)
1236*8dd5e09dSSadaf Ebrahimi 		full = 1;
1237*8dd5e09dSSadaf Ebrahimi 	else
1238*8dd5e09dSSadaf Ebrahimi 		return CAPNG_PARTIAL;
1239*8dd5e09dSSadaf Ebrahimi 
1240*8dd5e09dSSadaf Ebrahimi 	if (empty == 1 && full == 0)
1241*8dd5e09dSSadaf Ebrahimi 		return CAPNG_NONE;
1242*8dd5e09dSSadaf Ebrahimi 	else if (empty == 0 && full == 1)
1243*8dd5e09dSSadaf Ebrahimi 		return CAPNG_FULL;
1244*8dd5e09dSSadaf Ebrahimi 
1245*8dd5e09dSSadaf Ebrahimi 	return CAPNG_PARTIAL;
1246*8dd5e09dSSadaf Ebrahimi }
1247*8dd5e09dSSadaf Ebrahimi 
check_effective(unsigned int capability,unsigned int idx)1248*8dd5e09dSSadaf Ebrahimi static int check_effective(unsigned int capability, unsigned int idx)
1249*8dd5e09dSSadaf Ebrahimi {
1250*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & m.data.v3[idx].effective ? 1 : 0;
1251*8dd5e09dSSadaf Ebrahimi }
1252*8dd5e09dSSadaf Ebrahimi 
check_permitted(unsigned int capability,unsigned int idx)1253*8dd5e09dSSadaf Ebrahimi static int check_permitted(unsigned int capability, unsigned int idx)
1254*8dd5e09dSSadaf Ebrahimi {
1255*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & m.data.v3[idx].permitted ? 1 : 0;
1256*8dd5e09dSSadaf Ebrahimi }
1257*8dd5e09dSSadaf Ebrahimi 
check_inheritable(unsigned int capability,unsigned int idx)1258*8dd5e09dSSadaf Ebrahimi static int check_inheritable(unsigned int capability, unsigned int idx)
1259*8dd5e09dSSadaf Ebrahimi {
1260*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & m.data.v3[idx].inheritable ? 1 : 0;
1261*8dd5e09dSSadaf Ebrahimi }
1262*8dd5e09dSSadaf Ebrahimi 
bounds_bit_check(unsigned int capability,unsigned int idx)1263*8dd5e09dSSadaf Ebrahimi static int bounds_bit_check(unsigned int capability, unsigned int idx)
1264*8dd5e09dSSadaf Ebrahimi {
1265*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
1266*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
1267*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & m.bounds[idx] ? 1 : 0;
1268*8dd5e09dSSadaf Ebrahimi }
1269*8dd5e09dSSadaf Ebrahimi #endif
1270*8dd5e09dSSadaf Ebrahimi 	return 0;
1271*8dd5e09dSSadaf Ebrahimi }
1272*8dd5e09dSSadaf Ebrahimi 
ambient_bit_check(unsigned int capability,unsigned int idx)1273*8dd5e09dSSadaf Ebrahimi static int ambient_bit_check(unsigned int capability, unsigned int idx)
1274*8dd5e09dSSadaf Ebrahimi {
1275*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
1276*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
1277*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & m.ambient[idx] ? 1 : 0;
1278*8dd5e09dSSadaf Ebrahimi }
1279*8dd5e09dSSadaf Ebrahimi #endif
1280*8dd5e09dSSadaf Ebrahimi 	return 0;
1281*8dd5e09dSSadaf Ebrahimi }
1282*8dd5e09dSSadaf Ebrahimi 
v1_check(unsigned int capability,__u32 data)1283*8dd5e09dSSadaf Ebrahimi static int v1_check(unsigned int capability, __u32 data)
1284*8dd5e09dSSadaf Ebrahimi {
1285*8dd5e09dSSadaf Ebrahimi 	return MASK(capability) & data ? 1 : 0;
1286*8dd5e09dSSadaf Ebrahimi }
1287*8dd5e09dSSadaf Ebrahimi 
capng_have_capability(capng_type_t which,unsigned int capability)1288*8dd5e09dSSadaf Ebrahimi int capng_have_capability(capng_type_t which, unsigned int capability)
1289*8dd5e09dSSadaf Ebrahimi {
1290*8dd5e09dSSadaf Ebrahimi 	// First, try to init with current set
1291*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT) {
1292*8dd5e09dSSadaf Ebrahimi 		if (capng_get_caps_process())
1293*8dd5e09dSSadaf Ebrahimi 			return 0;
1294*8dd5e09dSSadaf Ebrahimi 	}
1295*8dd5e09dSSadaf Ebrahimi 
1296*8dd5e09dSSadaf Ebrahimi 	// If we still don't have anything, error out
1297*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
1298*8dd5e09dSSadaf Ebrahimi 		return 0;
1299*8dd5e09dSSadaf Ebrahimi 	if (m.cap_ver == 1 && capability > 31)
1300*8dd5e09dSSadaf Ebrahimi 		return 0;
1301*8dd5e09dSSadaf Ebrahimi 	if (!cap_valid(capability))
1302*8dd5e09dSSadaf Ebrahimi 		return 0;
1303*8dd5e09dSSadaf Ebrahimi 
1304*8dd5e09dSSadaf Ebrahimi 	if (m.cap_ver == 1) {
1305*8dd5e09dSSadaf Ebrahimi 		if (which == CAPNG_EFFECTIVE)
1306*8dd5e09dSSadaf Ebrahimi 			return v1_check(capability, m.data.v1.effective);
1307*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_PERMITTED)
1308*8dd5e09dSSadaf Ebrahimi 			return v1_check(capability, m.data.v1.permitted);
1309*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_INHERITABLE)
1310*8dd5e09dSSadaf Ebrahimi 			return v1_check(capability, m.data.v1.inheritable);
1311*8dd5e09dSSadaf Ebrahimi 	} else {
1312*8dd5e09dSSadaf Ebrahimi 		unsigned int idx;
1313*8dd5e09dSSadaf Ebrahimi 
1314*8dd5e09dSSadaf Ebrahimi 		if (capability > 31) {
1315*8dd5e09dSSadaf Ebrahimi 			idx = capability>>5;
1316*8dd5e09dSSadaf Ebrahimi 			capability %= 32;
1317*8dd5e09dSSadaf Ebrahimi 		} else
1318*8dd5e09dSSadaf Ebrahimi 			idx = 0;
1319*8dd5e09dSSadaf Ebrahimi 
1320*8dd5e09dSSadaf Ebrahimi 		if (which == CAPNG_EFFECTIVE)
1321*8dd5e09dSSadaf Ebrahimi 			return check_effective(capability, idx);
1322*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_PERMITTED)
1323*8dd5e09dSSadaf Ebrahimi 			return check_permitted(capability, idx);
1324*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_INHERITABLE)
1325*8dd5e09dSSadaf Ebrahimi 			return check_inheritable(capability, idx);
1326*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_BOUNDING_SET)
1327*8dd5e09dSSadaf Ebrahimi 			return bounds_bit_check(capability, idx);
1328*8dd5e09dSSadaf Ebrahimi 		else if (which == CAPNG_AMBIENT)
1329*8dd5e09dSSadaf Ebrahimi 			return ambient_bit_check(capability, idx);
1330*8dd5e09dSSadaf Ebrahimi 	}
1331*8dd5e09dSSadaf Ebrahimi 	return 0;
1332*8dd5e09dSSadaf Ebrahimi }
1333*8dd5e09dSSadaf Ebrahimi 
capng_print_caps_numeric(capng_print_t where,capng_select_t set)1334*8dd5e09dSSadaf Ebrahimi char *capng_print_caps_numeric(capng_print_t where, capng_select_t set)
1335*8dd5e09dSSadaf Ebrahimi {
1336*8dd5e09dSSadaf Ebrahimi 	char *ptr = NULL;
1337*8dd5e09dSSadaf Ebrahimi 
1338*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
1339*8dd5e09dSSadaf Ebrahimi 		return ptr;
1340*8dd5e09dSSadaf Ebrahimi 
1341*8dd5e09dSSadaf Ebrahimi 	if (where == CAPNG_PRINT_STDOUT) {
1342*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_CAPS) {
1343*8dd5e09dSSadaf Ebrahimi 			if (m.cap_ver == 1) {
1344*8dd5e09dSSadaf Ebrahimi 				printf( "Effective:    %08X\n"
1345*8dd5e09dSSadaf Ebrahimi 					"Permitted:    %08X\n"
1346*8dd5e09dSSadaf Ebrahimi 					"Inheritable:  %08X\n",
1347*8dd5e09dSSadaf Ebrahimi 					m.data.v1.effective,
1348*8dd5e09dSSadaf Ebrahimi 					m.data.v1.permitted,
1349*8dd5e09dSSadaf Ebrahimi 					m.data.v1.inheritable);
1350*8dd5e09dSSadaf Ebrahimi 			} else {
1351*8dd5e09dSSadaf Ebrahimi 				printf( "Effective:    %08X, %08X\n"
1352*8dd5e09dSSadaf Ebrahimi 					"Permitted:    %08X, %08X\n"
1353*8dd5e09dSSadaf Ebrahimi 					"Inheritable:  %08X, %08X\n",
1354*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].effective & UPPER_MASK,
1355*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].effective,
1356*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].permitted & UPPER_MASK,
1357*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].permitted,
1358*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].inheritable & UPPER_MASK,
1359*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].inheritable);
1360*8dd5e09dSSadaf Ebrahimi 			}
1361*8dd5e09dSSadaf Ebrahimi 		}
1362*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
1363*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
1364*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_BOUNDS)
1365*8dd5e09dSSadaf Ebrahimi 			printf("Bounding Set: %08X, %08X\n",
1366*8dd5e09dSSadaf Ebrahimi 				m.bounds[1] & UPPER_MASK, m.bounds[0]);
1367*8dd5e09dSSadaf Ebrahimi }
1368*8dd5e09dSSadaf Ebrahimi #endif
1369*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
1370*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
1371*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_AMBIENT)
1372*8dd5e09dSSadaf Ebrahimi 			printf("Ambient :     %08X, %08X\n",
1373*8dd5e09dSSadaf Ebrahimi 				m.ambient[1] & UPPER_MASK, m.ambient[0]);
1374*8dd5e09dSSadaf Ebrahimi }
1375*8dd5e09dSSadaf Ebrahimi #endif
1376*8dd5e09dSSadaf Ebrahimi 	} else if (where == CAPNG_PRINT_BUFFER) {
1377*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_CAPS) {
1378*8dd5e09dSSadaf Ebrahimi 			// Make it big enough for bounding & ambient set, too
1379*8dd5e09dSSadaf Ebrahimi 			ptr = malloc(160);
1380*8dd5e09dSSadaf Ebrahimi 			if (m.cap_ver == 1) {
1381*8dd5e09dSSadaf Ebrahimi 				snprintf(ptr, 160,
1382*8dd5e09dSSadaf Ebrahimi 					"Effective:   %08X\n"
1383*8dd5e09dSSadaf Ebrahimi 					"Permitted:   %08X\n"
1384*8dd5e09dSSadaf Ebrahimi 					"Inheritable: %08X\n",
1385*8dd5e09dSSadaf Ebrahimi 					m.data.v1.effective,
1386*8dd5e09dSSadaf Ebrahimi 					m.data.v1.permitted,
1387*8dd5e09dSSadaf Ebrahimi 					m.data.v1.inheritable);
1388*8dd5e09dSSadaf Ebrahimi 			} else {
1389*8dd5e09dSSadaf Ebrahimi 				snprintf(ptr, 160,
1390*8dd5e09dSSadaf Ebrahimi 					"Effective:   %08X, %08X\n"
1391*8dd5e09dSSadaf Ebrahimi 					"Permitted:   %08X, %08X\n"
1392*8dd5e09dSSadaf Ebrahimi 					"Inheritable: %08X, %08X\n",
1393*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].effective & UPPER_MASK,
1394*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].effective,
1395*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].permitted & UPPER_MASK,
1396*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].permitted,
1397*8dd5e09dSSadaf Ebrahimi 					m.data.v3[1].inheritable & UPPER_MASK,
1398*8dd5e09dSSadaf Ebrahimi 					m.data.v3[0].inheritable);
1399*8dd5e09dSSadaf Ebrahimi 			}
1400*8dd5e09dSSadaf Ebrahimi 		}
1401*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_BOUNDS) {
1402*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAPBSET_DROP
1403*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAPBSET_DROP) {
1404*8dd5e09dSSadaf Ebrahimi 			char *s;
1405*8dd5e09dSSadaf Ebrahimi 			// If ptr is NULL, we only room for bounding and ambient
1406*8dd5e09dSSadaf Ebrahimi 			if (ptr == NULL ) {
1407*8dd5e09dSSadaf Ebrahimi 				ptr = malloc(80);
1408*8dd5e09dSSadaf Ebrahimi 				if (ptr == NULL)
1409*8dd5e09dSSadaf Ebrahimi 					return ptr;
1410*8dd5e09dSSadaf Ebrahimi 				*ptr = 0;
1411*8dd5e09dSSadaf Ebrahimi 				s = ptr;
1412*8dd5e09dSSadaf Ebrahimi 			} else
1413*8dd5e09dSSadaf Ebrahimi 				s = ptr + strlen(ptr);
1414*8dd5e09dSSadaf Ebrahimi 			snprintf(s, 40, "Bounding Set: %08X, %08X\n",
1415*8dd5e09dSSadaf Ebrahimi 					m.bounds[1] & UPPER_MASK, m.bounds[0]);
1416*8dd5e09dSSadaf Ebrahimi }
1417*8dd5e09dSSadaf Ebrahimi #endif
1418*8dd5e09dSSadaf Ebrahimi 		}
1419*8dd5e09dSSadaf Ebrahimi 		if (set & CAPNG_SELECT_AMBIENT) {
1420*8dd5e09dSSadaf Ebrahimi #ifdef PR_CAP_AMBIENT
1421*8dd5e09dSSadaf Ebrahimi if (HAVE_PR_CAP_AMBIENT) {
1422*8dd5e09dSSadaf Ebrahimi 			char *s;
1423*8dd5e09dSSadaf Ebrahimi 			// If ptr is NULL, we only room for ambient
1424*8dd5e09dSSadaf Ebrahimi 			if (ptr == NULL ) {
1425*8dd5e09dSSadaf Ebrahimi 				ptr = malloc(40);
1426*8dd5e09dSSadaf Ebrahimi 				if (ptr == NULL)
1427*8dd5e09dSSadaf Ebrahimi 					return ptr;
1428*8dd5e09dSSadaf Ebrahimi 				*ptr = 0;
1429*8dd5e09dSSadaf Ebrahimi 				s = ptr;
1430*8dd5e09dSSadaf Ebrahimi 			} else
1431*8dd5e09dSSadaf Ebrahimi 				s = ptr + strlen(ptr);
1432*8dd5e09dSSadaf Ebrahimi 			snprintf(s, 40, "Ambient Set: %08X, %08X\n",
1433*8dd5e09dSSadaf Ebrahimi 					m.ambient[1] & UPPER_MASK,
1434*8dd5e09dSSadaf Ebrahimi 					m.ambient[0]);
1435*8dd5e09dSSadaf Ebrahimi }
1436*8dd5e09dSSadaf Ebrahimi #endif
1437*8dd5e09dSSadaf Ebrahimi 		}
1438*8dd5e09dSSadaf Ebrahimi 	}
1439*8dd5e09dSSadaf Ebrahimi 
1440*8dd5e09dSSadaf Ebrahimi 	return ptr;
1441*8dd5e09dSSadaf Ebrahimi }
1442*8dd5e09dSSadaf Ebrahimi 
capng_print_caps_text(capng_print_t where,capng_type_t which)1443*8dd5e09dSSadaf Ebrahimi char *capng_print_caps_text(capng_print_t where, capng_type_t which)
1444*8dd5e09dSSadaf Ebrahimi {
1445*8dd5e09dSSadaf Ebrahimi 	unsigned int i, once = 0, cnt = 0;
1446*8dd5e09dSSadaf Ebrahimi 	char *ptr = NULL;
1447*8dd5e09dSSadaf Ebrahimi 
1448*8dd5e09dSSadaf Ebrahimi 	if (m.state < CAPNG_INIT)
1449*8dd5e09dSSadaf Ebrahimi 		return ptr;
1450*8dd5e09dSSadaf Ebrahimi 
1451*8dd5e09dSSadaf Ebrahimi 	for (i=0; i<=last_cap; i++) {
1452*8dd5e09dSSadaf Ebrahimi 		if (capng_have_capability(which, i)) {
1453*8dd5e09dSSadaf Ebrahimi 			const char *n = capng_capability_to_name(i);
1454*8dd5e09dSSadaf Ebrahimi 			if (n == NULL)
1455*8dd5e09dSSadaf Ebrahimi 				n = "unknown";
1456*8dd5e09dSSadaf Ebrahimi 			if (where == CAPNG_PRINT_STDOUT) {
1457*8dd5e09dSSadaf Ebrahimi 				if (once == 0) {
1458*8dd5e09dSSadaf Ebrahimi 					printf("%s", n);
1459*8dd5e09dSSadaf Ebrahimi 					once++;
1460*8dd5e09dSSadaf Ebrahimi 				} else
1461*8dd5e09dSSadaf Ebrahimi 					printf(", %s", n);
1462*8dd5e09dSSadaf Ebrahimi 			} else if (where == CAPNG_PRINT_BUFFER) {
1463*8dd5e09dSSadaf Ebrahimi 				int len;
1464*8dd5e09dSSadaf Ebrahimi 				if (once == 0) {
1465*8dd5e09dSSadaf Ebrahimi 					ptr = malloc(last_cap*20);
1466*8dd5e09dSSadaf Ebrahimi 					if (ptr == NULL)
1467*8dd5e09dSSadaf Ebrahimi 						return ptr;
1468*8dd5e09dSSadaf Ebrahimi 					len = sprintf(ptr+cnt, "%s", n);
1469*8dd5e09dSSadaf Ebrahimi 					once++;
1470*8dd5e09dSSadaf Ebrahimi 				} else
1471*8dd5e09dSSadaf Ebrahimi 					len = sprintf(ptr+cnt, ", %s", n);
1472*8dd5e09dSSadaf Ebrahimi 				if (len > 0)
1473*8dd5e09dSSadaf Ebrahimi 					cnt+=len;
1474*8dd5e09dSSadaf Ebrahimi 			}
1475*8dd5e09dSSadaf Ebrahimi 		}
1476*8dd5e09dSSadaf Ebrahimi 	}
1477*8dd5e09dSSadaf Ebrahimi 	if (once == 0) {
1478*8dd5e09dSSadaf Ebrahimi 		if (where == CAPNG_PRINT_STDOUT)
1479*8dd5e09dSSadaf Ebrahimi 			printf("none");
1480*8dd5e09dSSadaf Ebrahimi 		else
1481*8dd5e09dSSadaf Ebrahimi 			ptr = strdup("none");
1482*8dd5e09dSSadaf Ebrahimi 	}
1483*8dd5e09dSSadaf Ebrahimi 	return ptr;
1484*8dd5e09dSSadaf Ebrahimi }
1485*8dd5e09dSSadaf Ebrahimi 
capng_save_state(void)1486*8dd5e09dSSadaf Ebrahimi void *capng_save_state(void)
1487*8dd5e09dSSadaf Ebrahimi {
1488*8dd5e09dSSadaf Ebrahimi 	void *ptr = malloc(sizeof(m));
1489*8dd5e09dSSadaf Ebrahimi 	if (ptr)
1490*8dd5e09dSSadaf Ebrahimi 		memcpy(ptr, &m, sizeof(m));
1491*8dd5e09dSSadaf Ebrahimi 	return ptr;
1492*8dd5e09dSSadaf Ebrahimi }
1493*8dd5e09dSSadaf Ebrahimi 
capng_restore_state(void ** state)1494*8dd5e09dSSadaf Ebrahimi void capng_restore_state(void **state)
1495*8dd5e09dSSadaf Ebrahimi {
1496*8dd5e09dSSadaf Ebrahimi 	if (state) {
1497*8dd5e09dSSadaf Ebrahimi 		void *ptr = *state;
1498*8dd5e09dSSadaf Ebrahimi 		if (ptr)
1499*8dd5e09dSSadaf Ebrahimi 			memcpy(&m, ptr, sizeof(m));
1500*8dd5e09dSSadaf Ebrahimi 		free(ptr);
1501*8dd5e09dSSadaf Ebrahimi 		*state = NULL;
1502*8dd5e09dSSadaf Ebrahimi 	}
1503*8dd5e09dSSadaf Ebrahimi }
1504*8dd5e09dSSadaf Ebrahimi 
1505