cap_text.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*
  2. * Copyright (c) 1997-8,2007-8 Andrew G Morgan <morgan@kernel.org>
  3. * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk>
  4. *
  5. * This file deals with exchanging internal and textual
  6. * representations of capability sets.
  7. */
  8. #define _GNU_SOURCE
  9. #include <stdio.h>
  10. #define LIBCAP_PLEASE_INCLUDE_ARRAY
  11. #include "libcap.h"
  12. #include <ctype.h>
  13. #include <limits.h>
  14. /* Maximum output text length (16 per cap) */
  15. #define CAP_TEXT_SIZE (16*__CAP_MAXBITS)
  16. /*
  17. * Parse a textual representation of capabilities, returning an internal
  18. * representation.
  19. */
  20. #define raise_cap_mask(flat, c) (flat)[CAP_TO_INDEX(c)] |= CAP_TO_MASK(c)
  21. static void setbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks)
  22. {
  23. int n;
  24. for (n = blks; n--; ) {
  25. a->u[n].flat[set] |= b[n];
  26. }
  27. }
  28. static void clrbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks)
  29. {
  30. int n;
  31. for (n = blks; n--; )
  32. a->u[n].flat[set] &= ~b[n];
  33. }
  34. static char const *namcmp(char const *str, char const *nam)
  35. {
  36. while (*nam && tolower((unsigned char)*str) == *nam) {
  37. str++;
  38. nam++;
  39. }
  40. if (*nam || isalnum((unsigned char)*str) || *str == '_')
  41. return NULL;
  42. return str;
  43. }
  44. static void forceall(__u32 *flat, __u32 value, unsigned blks)
  45. {
  46. unsigned n;
  47. for (n = blks; n--; flat[n] = value);
  48. return;
  49. }
  50. static int lookupname(char const **strp)
  51. {
  52. union {
  53. char const *constp;
  54. char *p;
  55. } str;
  56. str.constp = *strp;
  57. if (isdigit(*str.constp)) {
  58. unsigned long n = strtoul(str.constp, &str.p, 0);
  59. if (n >= __CAP_MAXBITS)
  60. return -1;
  61. *strp = str.constp;
  62. return n;
  63. } else {
  64. int c;
  65. unsigned len;
  66. for (len=0; (c = str.constp[len]); ++len) {
  67. if (!(isalpha(c) || (c == '_'))) {
  68. break;
  69. }
  70. }
  71. #ifdef GPERF_DOWNCASE
  72. const struct __cap_token_s *token_info;
  73. token_info = __cap_lookup_name(str.constp, len);
  74. if (token_info != NULL) {
  75. *strp = str.constp + len;
  76. return token_info->index;
  77. }
  78. #else /* ie., ndef GPERF_DOWNCASE */
  79. char const *s;
  80. unsigned n;
  81. for (n = __CAP_BITS; n--; )
  82. if (_cap_names[n] && (s = namcmp(str.constp, _cap_names[n]))) {
  83. *strp = s;
  84. return n;
  85. }
  86. #endif /* def GPERF_DOWNCASE */
  87. return -1; /* No definition available */
  88. }
  89. }
  90. cap_t cap_from_text(const char *str)
  91. {
  92. cap_t res;
  93. int n;
  94. unsigned cap_blks;
  95. if (str == NULL) {
  96. _cap_debug("bad argument");
  97. errno = EINVAL;
  98. return NULL;
  99. }
  100. if (!(res = cap_init()))
  101. return NULL;
  102. switch (res->head.version) {
  103. case _LINUX_CAPABILITY_VERSION_1:
  104. cap_blks = _LINUX_CAPABILITY_U32S_1;
  105. break;
  106. case _LINUX_CAPABILITY_VERSION_2:
  107. cap_blks = _LINUX_CAPABILITY_U32S_2;
  108. break;
  109. case _LINUX_CAPABILITY_VERSION_3:
  110. cap_blks = _LINUX_CAPABILITY_U32S_3;
  111. break;
  112. default:
  113. errno = EINVAL;
  114. return NULL;
  115. }
  116. _cap_debug("%s", str);
  117. for (;;) {
  118. __u32 list[__CAP_BLKS];
  119. char op;
  120. int flags = 0, listed=0;
  121. forceall(list, 0, __CAP_BLKS);
  122. /* skip leading spaces */
  123. while (isspace((unsigned char)*str))
  124. str++;
  125. if (!*str) {
  126. _cap_debugcap("e = ", *res, CAP_EFFECTIVE);
  127. _cap_debugcap("i = ", *res, CAP_INHERITABLE);
  128. _cap_debugcap("p = ", *res, CAP_PERMITTED);
  129. return res;
  130. }
  131. /* identify caps specified by this clause */
  132. if (isalnum((unsigned char)*str) || *str == '_') {
  133. for (;;) {
  134. if (namcmp(str, "all")) {
  135. str += 3;
  136. forceall(list, ~0, cap_blks);
  137. } else {
  138. n = lookupname(&str);
  139. if (n == -1)
  140. goto bad;
  141. raise_cap_mask(list, n);
  142. }
  143. if (*str != ',')
  144. break;
  145. if (!isalnum((unsigned char)*++str) && *str != '_')
  146. goto bad;
  147. }
  148. listed = 1;
  149. } else if (*str == '+' || *str == '-') {
  150. goto bad; /* require a list of capabilities */
  151. } else {
  152. forceall(list, ~0, cap_blks);
  153. }
  154. /* identify first operation on list of capabilities */
  155. op = *str++;
  156. if (op == '=' && (*str == '+' || *str == '-')) {
  157. if (!listed)
  158. goto bad;
  159. op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */
  160. } else if (op != '+' && op != '-' && op != '=')
  161. goto bad;
  162. /* cycle through list of actions */
  163. do {
  164. _cap_debug("next char = `%c'", *str);
  165. if (*str && !isspace(*str)) {
  166. switch (*str++) { /* Effective, Inheritable, Permitted */
  167. case 'e':
  168. flags |= LIBCAP_EFF;
  169. break;
  170. case 'i':
  171. flags |= LIBCAP_INH;
  172. break;
  173. case 'p':
  174. flags |= LIBCAP_PER;
  175. break;
  176. default:
  177. goto bad;
  178. }
  179. } else if (op != '=') {
  180. _cap_debug("only '=' can be followed by space");
  181. goto bad;
  182. }
  183. _cap_debug("how to read?");
  184. switch (op) { /* how do we interpret the caps? */
  185. case '=':
  186. case 'P': /* =+ */
  187. case 'M': /* =- */
  188. clrbits(res, list, CAP_EFFECTIVE, cap_blks);
  189. clrbits(res, list, CAP_PERMITTED, cap_blks);
  190. clrbits(res, list, CAP_INHERITABLE, cap_blks);
  191. if (op == 'M')
  192. goto minus;
  193. /* fall through */
  194. case '+':
  195. if (flags & LIBCAP_EFF)
  196. setbits(res, list, CAP_EFFECTIVE, cap_blks);
  197. if (flags & LIBCAP_PER)
  198. setbits(res, list, CAP_PERMITTED, cap_blks);
  199. if (flags & LIBCAP_INH)
  200. setbits(res, list, CAP_INHERITABLE, cap_blks);
  201. break;
  202. case '-':
  203. minus:
  204. if (flags & LIBCAP_EFF)
  205. clrbits(res, list, CAP_EFFECTIVE, cap_blks);
  206. if (flags & LIBCAP_PER)
  207. clrbits(res, list, CAP_PERMITTED, cap_blks);
  208. if (flags & LIBCAP_INH)
  209. clrbits(res, list, CAP_INHERITABLE, cap_blks);
  210. break;
  211. }
  212. /* new directive? */
  213. if (*str == '+' || *str == '-') {
  214. if (!listed) {
  215. _cap_debug("for + & - must list capabilities");
  216. goto bad;
  217. }
  218. flags = 0; /* reset the flags */
  219. op = *str++;
  220. if (!isalpha(*str))
  221. goto bad;
  222. }
  223. } while (*str && !isspace(*str));
  224. _cap_debug("next clause");
  225. }
  226. bad:
  227. cap_free(res);
  228. res = NULL;
  229. errno = EINVAL;
  230. return res;
  231. }
  232. /*
  233. * lookup a capability name and return its numerical value
  234. */
  235. int cap_from_name(const char *name, cap_value_t *value_p)
  236. {
  237. int n;
  238. if (((n = lookupname(&name)) >= 0) && (value_p != NULL)) {
  239. *value_p = (unsigned) n;
  240. }
  241. return -(n < 0);
  242. }
  243. /*
  244. * Convert a single capability index number into a string representation
  245. */
  246. char *cap_to_name(cap_value_t cap)
  247. {
  248. if ((cap < 0) || (cap >= __CAP_BITS)) {
  249. #if UINT_MAX != 4294967295U
  250. # error Recompile with correctly sized numeric array
  251. #endif
  252. char *tmp, *result;
  253. asprintf(&tmp, "%u", cap);
  254. result = _libcap_strdup(tmp);
  255. free(tmp);
  256. return result;
  257. } else {
  258. return _libcap_strdup(_cap_names[cap]);
  259. }
  260. }
  261. /*
  262. * Convert an internal representation to a textual one. The textual
  263. * representation is stored in static memory. It will be overwritten
  264. * on the next occasion that this function is called.
  265. */
  266. static int getstateflags(cap_t caps, int capno)
  267. {
  268. int f = 0;
  269. if (isset_cap(caps, capno, CAP_EFFECTIVE)) {
  270. f |= LIBCAP_EFF;
  271. }
  272. if (isset_cap(caps, capno, CAP_PERMITTED)) {
  273. f |= LIBCAP_PER;
  274. }
  275. if (isset_cap(caps, capno, CAP_INHERITABLE)) {
  276. f |= LIBCAP_INH;
  277. }
  278. return f;
  279. }
  280. #define CAP_TEXT_BUFFER_ZONE 100
  281. char *cap_to_text(cap_t caps, ssize_t *length_p)
  282. {
  283. char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
  284. char *p;
  285. int histo[8];
  286. int m, t;
  287. unsigned n;
  288. unsigned cap_maxbits, cap_blks;
  289. /* Check arguments */
  290. if (!good_cap_t(caps)) {
  291. errno = EINVAL;
  292. return NULL;
  293. }
  294. switch (caps->head.version) {
  295. case _LINUX_CAPABILITY_VERSION_1:
  296. cap_blks = _LINUX_CAPABILITY_U32S_1;
  297. break;
  298. case _LINUX_CAPABILITY_VERSION_2:
  299. cap_blks = _LINUX_CAPABILITY_U32S_2;
  300. break;
  301. case _LINUX_CAPABILITY_VERSION_3:
  302. cap_blks = _LINUX_CAPABILITY_U32S_3;
  303. break;
  304. default:
  305. errno = EINVAL;
  306. return NULL;
  307. }
  308. cap_maxbits = 32 * cap_blks;
  309. _cap_debugcap("e = ", *caps, CAP_EFFECTIVE);
  310. _cap_debugcap("i = ", *caps, CAP_INHERITABLE);
  311. _cap_debugcap("p = ", *caps, CAP_PERMITTED);
  312. memset(histo, 0, sizeof(histo));
  313. /* default prevailing state to the upper - unnamed bits */
  314. for (n = cap_maxbits-1; n > __CAP_BITS; n--)
  315. histo[getstateflags(caps, n)]++;
  316. /* find which combination of capability sets shares the most bits
  317. we bias to preferring non-set (m=0) with the >= 0 test. Failing
  318. to do this causes strange things to happen with older systems
  319. that don't know about bits 32+. */
  320. for (m=t=7; t--; )
  321. if (histo[t] >= histo[m])
  322. m = t;
  323. /* capture remaining bits - selecting m from only the unnamed bits,
  324. we maximize the likelihood that we won't see numeric capability
  325. values in the text output. */
  326. while (n--)
  327. histo[getstateflags(caps, n)]++;
  328. /* blank is not a valid capability set */
  329. p = sprintf(buf, "=%s%s%s",
  330. (m & LIBCAP_EFF) ? "e" : "",
  331. (m & LIBCAP_INH) ? "i" : "",
  332. (m & LIBCAP_PER) ? "p" : "" ) + buf;
  333. for (t = 8; t--; )
  334. if (t != m && histo[t]) {
  335. *p++ = ' ';
  336. for (n = 0; n < cap_maxbits; n++)
  337. if (getstateflags(caps, n) == t) {
  338. char *this_cap_name;
  339. this_cap_name = cap_to_name(n);
  340. if ((strlen(this_cap_name) + (p - buf)) > CAP_TEXT_SIZE) {
  341. cap_free(this_cap_name);
  342. errno = ERANGE;
  343. return NULL;
  344. }
  345. p += sprintf(p, "%s,", this_cap_name);
  346. cap_free(this_cap_name);
  347. }
  348. p--;
  349. n = t & ~m;
  350. if (n)
  351. p += sprintf(p, "+%s%s%s",
  352. (n & LIBCAP_EFF) ? "e" : "",
  353. (n & LIBCAP_INH) ? "i" : "",
  354. (n & LIBCAP_PER) ? "p" : "");
  355. n = ~t & m;
  356. if (n)
  357. p += sprintf(p, "-%s%s%s",
  358. (n & LIBCAP_EFF) ? "e" : "",
  359. (n & LIBCAP_INH) ? "i" : "",
  360. (n & LIBCAP_PER) ? "p" : "");
  361. if (p - buf > CAP_TEXT_SIZE) {
  362. errno = ERANGE;
  363. return NULL;
  364. }
  365. }
  366. _cap_debug("%s", buf);
  367. if (length_p) {
  368. *length_p = p - buf;
  369. }
  370. return (_libcap_strdup(buf));
  371. }