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