cap_file.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. #include <sys/types.h>
  7. #include <byteswap.h>
  8. #include <sys/stat.h>
  9. #include <unistd.h>
  10. #include <linux/xattr.h>
  11. /*
  12. * We hardcode the prototypes for the Linux system calls here since
  13. * there are no libcap library APIs that expose the user to these
  14. * details, and that way we don't need to foce clients to link any
  15. * other libraries to access them.
  16. */
  17. extern ssize_t getxattr(const char *, const char *, void *, size_t);
  18. extern ssize_t fgetxattr(int, const char *, void *, size_t);
  19. extern int setxattr(const char *, const char *, const void *, size_t, int);
  20. extern int fsetxattr(int, const char *, const void *, size_t, int);
  21. extern int removexattr(const char *, const char *);
  22. extern int fremovexattr(int, const char *);
  23. #include "libcap.h"
  24. #ifdef VFS_CAP_U32
  25. #if VFS_CAP_U32 != __CAP_BLKS
  26. # error VFS representation of capabilities is not the same size as kernel
  27. #endif
  28. #if __BYTE_ORDER == __BIG_ENDIAN
  29. #define FIXUP_32BITS(x) bswap_32(x)
  30. #else
  31. #define FIXUP_32BITS(x) (x)
  32. #endif
  33. static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result,
  34. int bytes)
  35. {
  36. __u32 magic_etc;
  37. unsigned tocopy, i;
  38. magic_etc = FIXUP_32BITS(rawvfscap->magic_etc);
  39. switch (magic_etc & VFS_CAP_REVISION_MASK) {
  40. #ifdef VFS_CAP_REVISION_1
  41. case VFS_CAP_REVISION_1:
  42. tocopy = VFS_CAP_U32_1;
  43. bytes -= XATTR_CAPS_SZ_1;
  44. break;
  45. #endif
  46. #ifdef VFS_CAP_REVISION_2
  47. case VFS_CAP_REVISION_2:
  48. tocopy = VFS_CAP_U32_2;
  49. bytes -= XATTR_CAPS_SZ_2;
  50. break;
  51. #endif
  52. default:
  53. cap_free(result);
  54. result = NULL;
  55. return result;
  56. }
  57. /*
  58. * Verify that we loaded exactly the right number of bytes
  59. */
  60. if (bytes != 0) {
  61. cap_free(result);
  62. result = NULL;
  63. return result;
  64. }
  65. for (i=0; i < tocopy; i++) {
  66. result->u[i].flat[CAP_INHERITABLE]
  67. = FIXUP_32BITS(rawvfscap->data[i].inheritable);
  68. result->u[i].flat[CAP_PERMITTED]
  69. = FIXUP_32BITS(rawvfscap->data[i].permitted);
  70. if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
  71. result->u[i].flat[CAP_EFFECTIVE]
  72. = result->u[i].flat[CAP_INHERITABLE]
  73. | result->u[i].flat[CAP_PERMITTED];
  74. }
  75. }
  76. while (i < __CAP_BLKS) {
  77. result->u[i].flat[CAP_INHERITABLE]
  78. = result->u[i].flat[CAP_PERMITTED]
  79. = result->u[i].flat[CAP_EFFECTIVE] = 0;
  80. i++;
  81. }
  82. return result;
  83. }
  84. static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d,
  85. int *bytes_p)
  86. {
  87. __u32 eff_not_zero, magic;
  88. unsigned tocopy, i;
  89. if (!good_cap_t(cap_d)) {
  90. errno = EINVAL;
  91. return -1;
  92. }
  93. switch (cap_d->head.version) {
  94. #ifdef _LINUX_CAPABILITY_VERSION_1
  95. case _LINUX_CAPABILITY_VERSION_1:
  96. magic = VFS_CAP_REVISION_1;
  97. tocopy = VFS_CAP_U32_1;
  98. *bytes_p = XATTR_CAPS_SZ_1;
  99. break;
  100. #endif
  101. #ifdef _LINUX_CAPABILITY_VERSION_2
  102. case _LINUX_CAPABILITY_VERSION_2:
  103. magic = VFS_CAP_REVISION_2;
  104. tocopy = VFS_CAP_U32_2;
  105. *bytes_p = XATTR_CAPS_SZ_2;
  106. break;
  107. #endif
  108. #ifdef _LINUX_CAPABILITY_VERSION_3
  109. case _LINUX_CAPABILITY_VERSION_3:
  110. magic = VFS_CAP_REVISION_2;
  111. tocopy = VFS_CAP_U32_2;
  112. *bytes_p = XATTR_CAPS_SZ_2;
  113. break;
  114. #endif
  115. default:
  116. errno = EINVAL;
  117. return -1;
  118. }
  119. _cap_debug("setting named file capabilities");
  120. for (eff_not_zero = 0, i = 0; i < tocopy; i++) {
  121. eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE];
  122. }
  123. while (i < __CAP_BLKS) {
  124. if ((cap_d->u[i].flat[CAP_EFFECTIVE]
  125. || cap_d->u[i].flat[CAP_INHERITABLE]
  126. || cap_d->u[i].flat[CAP_PERMITTED])) {
  127. /*
  128. * System does not support these capabilities
  129. */
  130. errno = EINVAL;
  131. return -1;
  132. }
  133. i++;
  134. }
  135. for (i=0; i < tocopy; i++) {
  136. rawvfscap->data[i].permitted
  137. = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]);
  138. rawvfscap->data[i].inheritable
  139. = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]);
  140. if (eff_not_zero
  141. && ((~(cap_d->u[i].flat[CAP_EFFECTIVE]))
  142. & (cap_d->u[i].flat[CAP_PERMITTED]
  143. | cap_d->u[i].flat[CAP_INHERITABLE]))) {
  144. errno = EINVAL;
  145. return -1;
  146. }
  147. }
  148. if (eff_not_zero == 0) {
  149. rawvfscap->magic_etc = FIXUP_32BITS(magic);
  150. } else {
  151. rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE);
  152. }
  153. return 0; /* success */
  154. }
  155. /*
  156. * Get the capabilities of an open file, as specified by its file
  157. * descriptor.
  158. */
  159. cap_t cap_get_fd(int fildes)
  160. {
  161. cap_t result;
  162. /* allocate a new capability set */
  163. result = cap_init();
  164. if (result) {
  165. struct vfs_cap_data rawvfscap;
  166. int sizeofcaps;
  167. _cap_debug("getting fildes capabilities");
  168. /* fill the capability sets via a system call */
  169. sizeofcaps = fgetxattr(fildes, XATTR_NAME_CAPS,
  170. &rawvfscap, sizeof(rawvfscap));
  171. if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
  172. cap_free(result);
  173. result = NULL;
  174. } else {
  175. result = _fcaps_load(&rawvfscap, result, sizeofcaps);
  176. }
  177. }
  178. return result;
  179. }
  180. /*
  181. * Get the capabilities from a named file.
  182. */
  183. cap_t cap_get_file(const char *filename)
  184. {
  185. cap_t result;
  186. /* allocate a new capability set */
  187. result = cap_init();
  188. if (result) {
  189. struct vfs_cap_data rawvfscap;
  190. int sizeofcaps;
  191. _cap_debug("getting filename capabilities");
  192. /* fill the capability sets via a system call */
  193. sizeofcaps = getxattr(filename, XATTR_NAME_CAPS,
  194. &rawvfscap, sizeof(rawvfscap));
  195. if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
  196. cap_free(result);
  197. result = NULL;
  198. } else {
  199. result = _fcaps_load(&rawvfscap, result, sizeofcaps);
  200. }
  201. }
  202. return result;
  203. }
  204. /*
  205. * Set the capabilities of an open file, as specified by its file
  206. * descriptor.
  207. */
  208. int cap_set_fd(int fildes, cap_t cap_d)
  209. {
  210. struct vfs_cap_data rawvfscap;
  211. int sizeofcaps;
  212. struct stat buf;
  213. if (fstat(fildes, &buf) != 0) {
  214. _cap_debug("unable to stat file descriptor %d", fildes);
  215. return -1;
  216. }
  217. if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
  218. _cap_debug("file descriptor %d for non-regular file", fildes);
  219. errno = EINVAL;
  220. return -1;
  221. }
  222. if (cap_d == NULL) {
  223. _cap_debug("deleting fildes capabilities");
  224. return fremovexattr(fildes, XATTR_NAME_CAPS);
  225. } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
  226. return -1;
  227. }
  228. _cap_debug("setting fildes capabilities");
  229. return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
  230. }
  231. /*
  232. * Set the capabilities of a named file.
  233. */
  234. int cap_set_file(const char *filename, cap_t cap_d)
  235. {
  236. struct vfs_cap_data rawvfscap;
  237. int sizeofcaps;
  238. struct stat buf;
  239. if (lstat(filename, &buf) != 0) {
  240. _cap_debug("unable to stat file [%s]", filename);
  241. return -1;
  242. }
  243. if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
  244. _cap_debug("file [%s] is not a regular file", filename);
  245. errno = EINVAL;
  246. return -1;
  247. }
  248. if (cap_d == NULL) {
  249. _cap_debug("removing filename capabilities");
  250. return removexattr(filename, XATTR_NAME_CAPS);
  251. } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
  252. return -1;
  253. }
  254. _cap_debug("setting filename capabilities");
  255. return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
  256. }
  257. #else /* ie. ndef VFS_CAP_U32 */
  258. cap_t cap_get_fd(int fildes)
  259. {
  260. errno = EINVAL;
  261. return NULL;
  262. }
  263. cap_t cap_get_file(const char *filename)
  264. {
  265. errno = EINVAL;
  266. return NULL;
  267. }
  268. int cap_set_fd(int fildes, cap_t cap_d)
  269. {
  270. errno = EINVAL;
  271. return -1;
  272. }
  273. int cap_set_file(const char *filename, cap_t cap_d)
  274. {
  275. errno = EINVAL;
  276. return -1;
  277. }
  278. #endif /* def VFS_CAP_U32 */