1 /*
2  * Copyright (c) 1997,2007,2016 Andrew G Morgan <morgan@kernel.org>
3  *
4  * This file deals with setting capabilities on files.
5  */
6 
7 #ifndef _DEFAULT_SOURCE
8 #define _DEFAULT_SOURCE
9 #endif
10 
11 #include <sys/types.h>
12 #include <byteswap.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <linux/xattr.h>
16 
17 /*
18  * We hardcode the prototypes for the Linux system calls here since
19  * there are no libcap library APIs that expose the user to these
20  * details, and that way we don't need to force clients to link any
21  * other libraries to access them.
22  */
23 extern ssize_t getxattr(const char *, const char *, void *, size_t);
24 extern ssize_t fgetxattr(int, const char *, void *, size_t);
25 extern int setxattr(const char *, const char *, const void *, size_t, int);
26 extern int fsetxattr(int, const char *, const void *, size_t, int);
27 extern int removexattr(const char *, const char *);
28 extern int fremovexattr(int, const char *);
29 
30 /*
31  * This public API was moved to include/uapi/linux/xattr.h . For just
32  * these definitions, it isn't really worth managing this in our build
33  * system with yet another copy of a header file. We just, provide
34  * fallback definitions here.
35  */
36 #ifndef XATTR_CAPS_SUFFIX
37 #define XATTR_CAPS_SUFFIX "capability"
38 #endif
39 #ifndef XATTR_SECURITY_PREFIX
40 #define XATTR_SECURITY_PREFIX "security."
41 #endif
42 #ifndef XATTR_NAME_CAPS
43 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
44 #endif
45 
46 #include "libcap.h"
47 
48 #ifdef VFS_CAP_U32
49 
50 #if VFS_CAP_U32 != __CAP_BLKS
51 # error VFS representation of capabilities is not the same size as kernel
52 #endif
53 
54 #if __BYTE_ORDER == __BIG_ENDIAN
55 #define FIXUP_32BITS(x) bswap_32(x)
56 #else
57 #define FIXUP_32BITS(x) (x)
58 #endif
59 
_fcaps_load(struct vfs_ns_cap_data * rawvfscap,cap_t result,int bytes)60 static cap_t _fcaps_load(struct vfs_ns_cap_data *rawvfscap, cap_t result,
61 			 int bytes)
62 {
63     __u32 magic_etc;
64     unsigned tocopy, i;
65 
66     magic_etc = FIXUP_32BITS(rawvfscap->magic_etc);
67     switch (magic_etc & VFS_CAP_REVISION_MASK) {
68     case VFS_CAP_REVISION_1:
69 	tocopy = VFS_CAP_U32_1;
70 	bytes -= XATTR_CAPS_SZ_1;
71 	break;
72 
73     case VFS_CAP_REVISION_2:
74 	tocopy = VFS_CAP_U32_2;
75 	bytes -= XATTR_CAPS_SZ_2;
76 	break;
77 
78     case VFS_CAP_REVISION_3:
79 	tocopy = VFS_CAP_U32_3;
80 	bytes -= XATTR_CAPS_SZ_3;
81 	result->rootid = FIXUP_32BITS(rawvfscap->rootid);
82 	break;
83 
84     default:
85 	cap_free(result);
86 	result = NULL;
87 	return result;
88     }
89 
90     /*
91      * Verify that we loaded exactly the right number of bytes
92      */
93     if (bytes != 0) {
94 	cap_free(result);
95 	result = NULL;
96 	return result;
97     }
98 
99     for (i=0; i < tocopy; i++) {
100 	result->u[i].flat[CAP_INHERITABLE]
101 	    = FIXUP_32BITS(rawvfscap->data[i].inheritable);
102 	result->u[i].flat[CAP_PERMITTED]
103 	    = FIXUP_32BITS(rawvfscap->data[i].permitted);
104 	if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
105 	    result->u[i].flat[CAP_EFFECTIVE]
106 		= result->u[i].flat[CAP_INHERITABLE]
107 		| result->u[i].flat[CAP_PERMITTED];
108 	}
109     }
110     while (i < __CAP_BLKS) {
111 	result->u[i].flat[CAP_INHERITABLE]
112 	    = result->u[i].flat[CAP_PERMITTED]
113 	    = result->u[i].flat[CAP_EFFECTIVE] = 0;
114 	i++;
115     }
116 
117     return result;
118 }
119 
_fcaps_save(struct vfs_ns_cap_data * rawvfscap,cap_t cap_d,int * bytes_p)120 static int _fcaps_save(struct vfs_ns_cap_data *rawvfscap, cap_t cap_d,
121 		       int *bytes_p)
122 {
123     __u32 eff_not_zero, magic;
124     unsigned tocopy, i;
125 
126     if (!good_cap_t(cap_d)) {
127 	errno = EINVAL;
128 	return -1;
129     }
130 
131     switch (cap_d->head.version) {
132     case _LINUX_CAPABILITY_VERSION_1:
133 	magic = VFS_CAP_REVISION_1;
134 	tocopy = VFS_CAP_U32_1;
135 	*bytes_p = XATTR_CAPS_SZ_1;
136 	break;
137 
138     case _LINUX_CAPABILITY_VERSION_2:
139     case _LINUX_CAPABILITY_VERSION_3:
140 	magic = VFS_CAP_REVISION_2;
141 	tocopy = VFS_CAP_U32_2;
142 	*bytes_p = XATTR_CAPS_SZ_2;
143 	break;
144 
145     default:
146 	errno = EINVAL;
147 	return -1;
148     }
149 
150     if (cap_d->rootid != 0) {
151 	if (cap_d->head.version < _LINUX_CAPABILITY_VERSION_3) {
152 	    _cap_debug("namespaces with non-0 rootid unsupported by kernel");
153 	    errno = EINVAL;
154 	    return -1;
155 	}
156 	magic = VFS_CAP_REVISION_3;
157 	tocopy = VFS_CAP_U32_3;
158 	*bytes_p = XATTR_CAPS_SZ_3;
159 	rawvfscap->rootid = FIXUP_32BITS(cap_d->rootid);
160     }
161 
162     _cap_debug("setting named file capabilities");
163 
164     for (eff_not_zero = 0, i = 0; i < tocopy; i++) {
165 	eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE];
166     }
167     while (i < __CAP_BLKS) {
168 	if ((cap_d->u[i].flat[CAP_EFFECTIVE]
169 	     || cap_d->u[i].flat[CAP_INHERITABLE]
170 	     || cap_d->u[i].flat[CAP_PERMITTED])) {
171 	    /*
172 	     * System does not support these capabilities
173 	     */
174 	    errno = EINVAL;
175 	    return -1;
176 	}
177 	i++;
178     }
179 
180     for (i=0; i < tocopy; i++) {
181 	rawvfscap->data[i].permitted
182 	    = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]);
183 	rawvfscap->data[i].inheritable
184 	    = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]);
185 
186 	if (eff_not_zero
187 	    && ((~(cap_d->u[i].flat[CAP_EFFECTIVE]))
188 		& (cap_d->u[i].flat[CAP_PERMITTED]
189 		   | cap_d->u[i].flat[CAP_INHERITABLE]))) {
190 	    errno = EINVAL;
191 	    return -1;
192 	}
193     }
194 
195     if (eff_not_zero == 0) {
196 	rawvfscap->magic_etc = FIXUP_32BITS(magic);
197     } else {
198 	rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE);
199     }
200 
201     return 0;      /* success */
202 }
203 
204 /*
205  * Get the capabilities of an open file, as specified by its file
206  * descriptor.
207  */
208 
cap_get_fd(int fildes)209 cap_t cap_get_fd(int fildes)
210 {
211     cap_t result;
212 
213     /* allocate a new capability set */
214     result = cap_init();
215     if (result) {
216 	struct vfs_ns_cap_data rawvfscap;
217 	int sizeofcaps;
218 
219 	_cap_debug("getting fildes capabilities");
220 
221 	/* fill the capability sets via a system call */
222 	sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS,
223 			       &rawvfscap, sizeof(rawvfscap));
224 	if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
225 	    cap_free(result);
226 	    result = NULL;
227 	} else {
228 	    result = _fcaps_load(&rawvfscap, result, sizeofcaps);
229 	}
230     }
231 
232     return result;
233 }
234 
235 /*
236  * Get the capabilities from a named file.
237  */
238 
cap_get_file(const char * filename)239 cap_t cap_get_file(const char *filename)
240 {
241     cap_t result;
242 
243     /* allocate a new capability set */
244     result = cap_init();
245     if (result) {
246 	struct vfs_ns_cap_data rawvfscap;
247 	int sizeofcaps;
248 
249 	_cap_debug("getting filename capabilities");
250 
251 	/* fill the capability sets via a system call */
252 	sizeofcaps = getxattr(filename, XATTR_NAME_CAPS,
253 			      &rawvfscap, sizeof(rawvfscap));
254 	if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
255 	    cap_free(result);
256 	    result = NULL;
257 	} else {
258 	    result = _fcaps_load(&rawvfscap, result, sizeofcaps);
259 	}
260     }
261 
262     return result;
263 }
264 
265 /*
266  * Get rootid as seen in the current user namespace for the file capability
267  * sets.
268  */
269 
cap_get_nsowner(cap_t cap_d)270 uid_t cap_get_nsowner(cap_t cap_d)
271 {
272 	return cap_d->rootid;
273 }
274 
275 /*
276  * Set the capabilities of an open file, as specified by its file
277  * descriptor.
278  */
279 
cap_set_fd(int fildes,cap_t cap_d)280 int cap_set_fd(int fildes, cap_t cap_d)
281 {
282     struct vfs_ns_cap_data rawvfscap;
283     int sizeofcaps;
284     struct stat buf;
285 
286     if (fstat(fildes, &buf) != 0) {
287 	_cap_debug("unable to stat file descriptor %d", fildes);
288 	return -1;
289     }
290     if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
291 	_cap_debug("file descriptor %d for non-regular file", fildes);
292 	errno = EINVAL;
293 	return -1;
294     }
295 
296     if (cap_d == NULL) {
297 	_cap_debug("deleting fildes capabilities");
298 	return fremovexattr(fildes, XATTR_NAME_CAPS);
299     } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
300 	return -1;
301     }
302 
303     _cap_debug("setting fildes capabilities");
304 
305     return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
306 }
307 
308 /*
309  * Set the capabilities of a named file.
310  */
311 
cap_set_file(const char * filename,cap_t cap_d)312 int cap_set_file(const char *filename, cap_t cap_d)
313 {
314     struct vfs_ns_cap_data rawvfscap;
315     int sizeofcaps;
316     struct stat buf;
317 
318     if (lstat(filename, &buf) != 0) {
319 	_cap_debug("unable to stat file [%s]", filename);
320 	return -1;
321     }
322     if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
323 	_cap_debug("file [%s] is not a regular file", filename);
324 	errno = EINVAL;
325 	return -1;
326     }
327 
328     if (cap_d == NULL) {
329 	_cap_debug("removing filename capabilities");
330 	return removexattr(filename, XATTR_NAME_CAPS);
331     } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
332 	return -1;
333     }
334 
335     _cap_debug("setting filename capabilities");
336     return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
337 }
338 
339 /*
340  * Set rootid for the file capability sets.
341  */
342 
cap_set_nsowner(cap_t cap_d,uid_t rootuid)343 int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
344 {
345 	cap_d->rootid = rootuid;
346 	return 0;
347 }
348 
349 #else /* ie. ndef VFS_CAP_U32 */
350 
cap_get_fd(int fildes)351 cap_t cap_get_fd(int fildes)
352 {
353     errno = EINVAL;
354     return NULL;
355 }
356 
cap_get_file(const char * filename)357 cap_t cap_get_file(const char *filename)
358 {
359     errno = EINVAL;
360     return NULL;
361 }
362 
cap_get_nsowner(cap_t cap_d)363 uid_t cap_get_nsowner(cap_t cap_d)
364 {
365     errno = EINVAL;
366     return -1;
367 }
368 
cap_set_fd(int fildes,cap_t cap_d)369 int cap_set_fd(int fildes, cap_t cap_d)
370 {
371     errno = EINVAL;
372     return -1;
373 }
374 
cap_set_file(const char * filename,cap_t cap_d)375 int cap_set_file(const char *filename, cap_t cap_d)
376 {
377     errno = EINVAL;
378     return -1;
379 }
380 
cap_set_nsowner(cap_t cap_d,uid_t rootuid)381 int cap_set_nsowner(cap_t cap_d, uid_t rootuid)
382 {
383 	errno = EINVAL;
384 	return -1;
385 }
386 
387 #endif /* def VFS_CAP_U32 */
388