17baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan/* 27aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan * Copyright (c) 1997-8,2007-8 Andrew G Morgan <morgan@kernel.org> 37baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk> 47baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * 57baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * This file deals with exchanging internal and textual 67baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * representations of capability sets. 77baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan */ 87baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 9159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan#define _GNU_SOURCE 10159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan#include <stdio.h> 11159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 127baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan#define LIBCAP_PLEASE_INCLUDE_ARRAY 137baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan#include "libcap.h" 147baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 157baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan#include <ctype.h> 16907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan#include <limits.h> 177baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 187baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan/* Maximum output text length (16 per cap) */ 19c2a25909b2c4d989e49cdedcac4dd52c45f0570bAndrew G. Morgan#define CAP_TEXT_SIZE (16*__CAP_MAXBITS) 207baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 217baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan/* 227baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * Parse a textual representation of capabilities, returning an internal 237baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * representation. 247baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan */ 257baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 2632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan#define raise_cap_mask(flat, c) (flat)[CAP_TO_INDEX(c)] |= CAP_TO_MASK(c) 2732423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 283f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morganstatic void setbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks) 297baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 307baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan int n; 313f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan for (n = blks; n--; ) { 3232423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan a->u[n].flat[set] |= b[n]; 3332423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } 347baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 357baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 363f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morganstatic void clrbits(cap_t a, const __u32 *b, cap_flag_t set, unsigned blks) 377baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 387baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan int n; 393f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan for (n = blks; n--; ) 4032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan a->u[n].flat[set] &= ~b[n]; 417baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 427baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 437baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morganstatic char const *namcmp(char const *str, char const *nam) 447baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 457baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan while (*nam && tolower((unsigned char)*str) == *nam) { 467baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan str++; 477baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan nam++; 487baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 497baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (*nam || isalnum((unsigned char)*str) || *str == '_') 507baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 517baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return str; 527baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 537baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 543f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morganstatic void forceall(__u32 *flat, __u32 value, unsigned blks) 5532423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan{ 5632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan unsigned n; 5732423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 583f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan for (n = blks; n--; flat[n] = value); 5932423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 6032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan return; 6132423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan} 6232423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 637baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morganstatic int lookupname(char const **strp) 647baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 65ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan union { 66ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan char const *constp; 67ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan char *p; 68ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan } str; 69ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan 70ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan str.constp = *strp; 71ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan if (isdigit(*str.constp)) { 72ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan unsigned long n = strtoul(str.constp, &str.p, 0); 73c2a25909b2c4d989e49cdedcac4dd52c45f0570bAndrew G. Morgan if (n >= __CAP_MAXBITS) 747baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return -1; 75ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan *strp = str.constp; 767baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return n; 777baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } else { 783184213774c3fb3e467c7bea080a88f6b984b4e4Andrew G. Morgan int c; 797aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan unsigned len; 807aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan 817aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan for (len=0; (c = str.constp[len]); ++len) { 827aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan if (!(isalpha(c) || (c == '_'))) { 837aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan break; 847aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan } 857aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan } 86159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 87159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan#ifdef GPERF_DOWNCASE 88159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan const struct __cap_token_s *token_info; 89159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 907aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan token_info = __cap_lookup_name(str.constp, len); 917aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan if (token_info != NULL) { 927aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan *strp = str.constp + len; 937aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan return token_info->index; 947aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan } 957aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan#else /* ie., ndef GPERF_DOWNCASE */ 967baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan char const *s; 973184213774c3fb3e467c7bea080a88f6b984b4e4Andrew G. Morgan unsigned n; 98159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 997baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan for (n = __CAP_BITS; n--; ) 100ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan if (_cap_names[n] && (s = namcmp(str.constp, _cap_names[n]))) { 1017baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan *strp = s; 1027baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return n; 1037baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1047aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan#endif /* def GPERF_DOWNCASE */ 1057aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan 1067aff2edf61f96087e7ac47def97acb638bb7bca2Andrew G. Morgan return -1; /* No definition available */ 1077baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1087baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 1097baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1107baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgancap_t cap_from_text(const char *str) 1117baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 1127baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan cap_t res; 1137baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan int n; 1143f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan unsigned cap_blks; 1157baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1167baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (str == NULL) { 1177baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("bad argument"); 1187baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan errno = EINVAL; 1197baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 1207baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1217baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1227baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!(res = cap_init())) 1237baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 12432423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 1253f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan switch (res->head.version) { 1263f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_1: 1273f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_1; 1283f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan break; 1293f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_2: 1303f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_2; 1313f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan break; 132d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_3: 133d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_3; 134d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan break; 1353f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan default: 1363f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan errno = EINVAL; 1373f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan return NULL; 1383f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan } 1393f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan 1407baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("%s", str); 1417baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1427baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan for (;;) { 14332423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan __u32 list[__CAP_BLKS]; 1447baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan char op; 1457baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan int flags = 0, listed=0; 14632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 1473f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan forceall(list, 0, __CAP_BLKS); 1487baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1497baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* skip leading spaces */ 1507baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan while (isspace((unsigned char)*str)) 1517baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan str++; 1527baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!*str) { 15332423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("e = ", *res, CAP_EFFECTIVE); 15432423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("i = ", *res, CAP_INHERITABLE); 15532423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("p = ", *res, CAP_PERMITTED); 15632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan 1577baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return res; 1587baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1597baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1607baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* identify caps specified by this clause */ 1617baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (isalnum((unsigned char)*str) || *str == '_') { 1627baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan for (;;) { 1637baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (namcmp(str, "all")) { 1647baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan str += 3; 1653f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan forceall(list, ~0, cap_blks); 1667baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } else { 1677baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan n = lookupname(&str); 1687baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (n == -1) 1697baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 17032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan raise_cap_mask(list, n); 1717baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1727baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (*str != ',') 1737baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 1747baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!isalnum((unsigned char)*++str) && *str != '_') 1757baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 1767baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 1777baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan listed = 1; 17832423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } else if (*str == '+' || *str == '-') { 1797baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; /* require a list of capabilities */ 18032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } else { 1813f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan forceall(list, ~0, cap_blks); 18232423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } 1837baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1847baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* identify first operation on list of capabilities */ 1857baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan op = *str++; 1867baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (op == '=' && (*str == '+' || *str == '-')) { 1877baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!listed) 1887baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 1897baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */ 1907baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } else if (op != '+' && op != '-' && op != '=') 1917baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 1927baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 1937baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* cycle through list of actions */ 1947baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan do { 1957baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("next char = `%c'", *str); 1967baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (*str && !isspace(*str)) { 1977baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan switch (*str++) { /* Effective, Inheritable, Permitted */ 1987baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case 'e': 1997baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan flags |= LIBCAP_EFF; 2007baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 2017baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case 'i': 2027baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan flags |= LIBCAP_INH; 2037baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 2047baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case 'p': 2057baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan flags |= LIBCAP_PER; 2067baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 2077baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan default: 2087baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 2097baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2107baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } else if (op != '=') { 2117baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("only '=' can be followed by space"); 2127baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 2137baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2147baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 2157baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("how to read?"); 2167baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan switch (op) { /* how do we interpret the caps? */ 2177baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case '=': 2187baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case 'P': /* =+ */ 2197baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case 'M': /* =- */ 2203f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_EFFECTIVE, cap_blks); 2213f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_PERMITTED, cap_blks); 2223f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_INHERITABLE, cap_blks); 2237baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (op == 'M') 2247baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto minus; 22532423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan /* fall through */ 2267baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case '+': 2277baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (flags & LIBCAP_EFF) 2283f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan setbits(res, list, CAP_EFFECTIVE, cap_blks); 2297baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (flags & LIBCAP_PER) 2303f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan setbits(res, list, CAP_PERMITTED, cap_blks); 23132423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (flags & LIBCAP_INH) 2323f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan setbits(res, list, CAP_INHERITABLE, cap_blks); 2337baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 2347baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan case '-': 2357baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan minus: 23632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (flags & LIBCAP_EFF) 2373f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_EFFECTIVE, cap_blks); 2387baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (flags & LIBCAP_PER) 2393f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_PERMITTED, cap_blks); 24032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (flags & LIBCAP_INH) 2413f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan clrbits(res, list, CAP_INHERITABLE, cap_blks); 2427baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan break; 2437baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2447baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 2457baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* new directive? */ 2467baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (*str == '+' || *str == '-') { 2477baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!listed) { 2487baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("for + & - must list capabilities"); 2497baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 2507baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2517baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan flags = 0; /* reset the flags */ 2527baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan op = *str++; 2537baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (!isalpha(*str)) 2547baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan goto bad; 2557baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2567baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } while (*str && !isspace(*str)); 2577baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("next clause"); 2587baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 2597baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 2607baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morganbad: 261ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan cap_free(res); 262ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan res = NULL; 2637baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan errno = EINVAL; 264ec25bd9b420ab62bcc3ec709f467eb43d434b66dAndrew Morgan return res; 2657baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 2667baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 2677baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan/* 268907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan * lookup a capability name and return its numerical value 269907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan */ 270907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morganint cap_from_name(const char *name, cap_value_t *value_p) 271907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan{ 272907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan int n; 273907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan 274597369a007f20080e13ffbe3a4dfed38897c7edcAndrew G. Morgan if (((n = lookupname(&name)) >= 0) && (value_p != NULL)) { 275907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan *value_p = (unsigned) n; 276907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan } 277907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan return -(n < 0); 278907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan} 279907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan 280907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan/* 281907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan * Convert a single capability index number into a string representation 282907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan */ 283907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morganchar *cap_to_name(cap_value_t cap) 284907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan{ 285907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan if ((cap < 0) || (cap >= __CAP_BITS)) { 286907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan#if UINT_MAX != 4294967295U 287907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan# error Recompile with correctly sized numeric array 288907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan#endif 289159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan char *tmp, *result; 290907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan 2913184213774c3fb3e467c7bea080a88f6b984b4e4Andrew G. Morgan asprintf(&tmp, "%u", cap); 292159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan result = _libcap_strdup(tmp); 293159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan free(tmp); 294159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 295159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan return result; 296907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan } else { 297907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan return _libcap_strdup(_cap_names[cap]); 298907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan } 299907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan} 300907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan 301907393e8d611fc887440d77335bc87adc0bed0bdAndrew G. Morgan/* 3027baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * Convert an internal representation to a textual one. The textual 3037baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * representation is stored in static memory. It will be overwritten 3047baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan * on the next occasion that this function is called. 3057baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan */ 3067baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3077baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morganstatic int getstateflags(cap_t caps, int capno) 3087baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 3097baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan int f = 0; 3107baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 31132423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (isset_cap(caps, capno, CAP_EFFECTIVE)) { 3127baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan f |= LIBCAP_EFF; 31332423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } 31432423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (isset_cap(caps, capno, CAP_PERMITTED)) { 3157baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan f |= LIBCAP_PER; 31632423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } 31732423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan if (isset_cap(caps, capno, CAP_INHERITABLE)) { 31832423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan f |= LIBCAP_INH; 31932423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan } 3207baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3217baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return f; 3227baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 3237baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3247baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan#define CAP_TEXT_BUFFER_ZONE 100 3257baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3267baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morganchar *cap_to_text(cap_t caps, ssize_t *length_p) 3277baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan{ 3283f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE]; 3297baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan char *p; 3303f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan int histo[8]; 331c2a25909b2c4d989e49cdedcac4dd52c45f0570bAndrew G. Morgan int m, t; 332c2a25909b2c4d989e49cdedcac4dd52c45f0570bAndrew G. Morgan unsigned n; 3333f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan unsigned cap_maxbits, cap_blks; 3347baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3357baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* Check arguments */ 3362153ffce3a55344869504792a7aaf365990cc3f0Andrew Morgan if (!good_cap_t(caps)) { 3377baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan errno = EINVAL; 3387baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 3397baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 3407baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3413f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan switch (caps->head.version) { 3423f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_1: 3433f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_1; 3443f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan break; 3453f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_2: 3463f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_2; 3473f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan break; 348d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan case _LINUX_CAPABILITY_VERSION_3: 349d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan cap_blks = _LINUX_CAPABILITY_U32S_3; 350d62769b6fc69244bd9922b018787d8bb7e332118Andrew G. Morgan break; 3513f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan default: 3523f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan errno = EINVAL; 3533f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan return NULL; 3543f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan } 3553f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan 3563f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan cap_maxbits = 32 * cap_blks; 3573f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan 35832423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("e = ", *caps, CAP_EFFECTIVE); 35932423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("i = ", *caps, CAP_INHERITABLE); 36032423d46c83c639c2df7db7ee74b8ec7be2b1234Andrew Morgan _cap_debugcap("p = ", *caps, CAP_PERMITTED); 3617baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3623f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan memset(histo, 0, sizeof(histo)); 3633f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan 364e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan /* default prevailing state to the upper - unnamed bits */ 365e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan for (n = cap_maxbits-1; n > __CAP_BITS; n--) 3667baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan histo[getstateflags(caps, n)]++; 3677baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 368d718c084e9f95b793d16a66788670610a37774f9Andrew G. Morgan /* find which combination of capability sets shares the most bits 369d718c084e9f95b793d16a66788670610a37774f9Andrew G. Morgan we bias to preferring non-set (m=0) with the >= 0 test. Failing 370d718c084e9f95b793d16a66788670610a37774f9Andrew G. Morgan to do this causes strange things to happen with older systems 371d718c084e9f95b793d16a66788670610a37774f9Andrew G. Morgan that don't know about bits 32+. */ 3727baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan for (m=t=7; t--; ) 373d718c084e9f95b793d16a66788670610a37774f9Andrew G. Morgan if (histo[t] >= histo[m]) 3747baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan m = t; 3757baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 376e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan /* capture remaining bits - selecting m from only the unnamed bits, 377e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan we maximize the likelihood that we won't see numeric capability 378e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan values in the text output. */ 379e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan while (n--) 380e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan histo[getstateflags(caps, n)]++; 381e482cc22ad687f50882f0029ed4b9adebb01911cAndrew G. Morgan 3827baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan /* blank is not a valid capability set */ 3837baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan p = sprintf(buf, "=%s%s%s", 3847baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (m & LIBCAP_EFF) ? "e" : "", 3857baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (m & LIBCAP_INH) ? "i" : "", 3867baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (m & LIBCAP_PER) ? "p" : "" ) + buf; 3877baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 3887baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan for (t = 8; t--; ) 3897baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (t != m && histo[t]) { 3907baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan *p++ = ' '; 3913f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan for (n = 0; n < cap_maxbits; n++) 3927baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (getstateflags(caps, n) == t) { 393159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan char *this_cap_name; 394159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan 395159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan this_cap_name = cap_to_name(n); 3963f7da3c2259741354f4e55105c466ae1443a0490Andrew G. Morgan if ((strlen(this_cap_name) + (p - buf)) > CAP_TEXT_SIZE) { 397159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan cap_free(this_cap_name); 3987baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan errno = ERANGE; 3997baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 4007baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 401159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan p += sprintf(p, "%s,", this_cap_name); 402159fc80362a68a54ca72d1a0419975ac76333d4bAndrew G. Morgan cap_free(this_cap_name); 4037baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 4047baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan p--; 4057baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan n = t & ~m; 4067baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (n) 4077baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan p += sprintf(p, "+%s%s%s", 4087baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_EFF) ? "e" : "", 4097baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_INH) ? "i" : "", 4107baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_PER) ? "p" : ""); 4117baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan n = ~t & m; 4127baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (n) 4137baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan p += sprintf(p, "-%s%s%s", 4147baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_EFF) ? "e" : "", 4157baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_INH) ? "i" : "", 4167baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan (n & LIBCAP_PER) ? "p" : ""); 4177baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan if (p - buf > CAP_TEXT_SIZE) { 4187baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan errno = ERANGE; 4197baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan return NULL; 4207baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 4217baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan } 4227baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan 4237baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan _cap_debug("%s", buf); 4242153ffce3a55344869504792a7aaf365990cc3f0Andrew Morgan if (length_p) { 4252153ffce3a55344869504792a7aaf365990cc3f0Andrew Morgan *length_p = p - buf; 4262153ffce3a55344869504792a7aaf365990cc3f0Andrew Morgan } 4272153ffce3a55344869504792a7aaf365990cc3f0Andrew Morgan 428f9c44c45c23630bcf24135d7972a298aad5949eaAndrew Morgan return (_libcap_strdup(buf)); 4297baf3be8302d9a7ba63c8c57131ecbc3fbd6d3ebAndrew Morgan} 430