diff options
author | Andrew Morgan <morgan@kernel.org> | 2007-10-31 23:18:09 -0700 |
---|---|---|
committer | Jorge Lucangeli Obes <jorgelo@google.com> | 2015-09-03 14:13:03 -0700 |
commit | 32423d46c83c639c2df7db7ee74b8ec7be2b1234 (patch) | |
tree | e54994e1dbb4f23a7dbdf3233486d24d035c11dd /libcap | |
parent | cfb5b56050a169ccb9744a886dc44d56eefdfea4 (diff) | |
download | libcap-32423d46c83c639c2df7db7ee74b8ec7be2b1234.tar.gz |
Add support for 64-bit (file) capabilities
This should compile with any iteration of a recent (2.6) kernel.
If your kernel has 64-bit capabilities support, and the kernel
headers indicate this, then it will include that. 32-bit legacy
kernel support is dynamically performed by such a build of libcap.
Diffstat (limited to 'libcap')
-rw-r--r-- | libcap/cap_alloc.c | 16 | ||||
-rw-r--r-- | libcap/cap_extint.c | 11 | ||||
-rw-r--r-- | libcap/cap_file.c | 145 | ||||
-rw-r--r-- | libcap/cap_flag.c | 16 | ||||
-rw-r--r-- | libcap/cap_proc.c | 12 | ||||
-rw-r--r-- | libcap/cap_text.c | 95 | ||||
-rw-r--r-- | libcap/include/sys/capability.h | 1 | ||||
-rw-r--r-- | libcap/libcap.h | 101 |
8 files changed, 282 insertions, 115 deletions
diff --git a/libcap/cap_alloc.c b/libcap/cap_alloc.c index a3b22a7..78df97c 100644 --- a/libcap/cap_alloc.c +++ b/libcap/cap_alloc.c @@ -29,6 +29,22 @@ cap_t cap_init(void) memset(result, 0, sizeof(*result)); result->head.version = _LINUX_CAPABILITY_VERSION; + capget(&result->head, NULL); /* load the kernel-capability version */ + + switch (result->head.version) { +#ifdef _LINUX_CAPABILITY_VERSION_1 + case _LINUX_CAPABILITY_VERSION_1: + break; +#endif +#ifdef _LINUX_CAPABILITY_VERSION_2 + case _LINUX_CAPABILITY_VERSION_2: + break; +#endif + default: /* No idea what to do */ + cap_free(result); + result = NULL; + break; + } return result; } diff --git a/libcap/cap_extint.c b/libcap/cap_extint.c index 1d858a1..4cf43ea 100644 --- a/libcap/cap_extint.c +++ b/libcap/cap_extint.c @@ -41,7 +41,6 @@ ssize_t cap_size(cap_t caps) ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length) { struct cap_ext_struct *result = (struct cap_ext_struct *) cap_ext; - __u32 *from = (__u32 *) &(cap_d->set); int i; /* valid arguments? */ @@ -58,7 +57,9 @@ ssize_t cap_copy_ext(void *cap_ext, cap_t cap_d, ssize_t length) for (i=0; i<NUMBER_OF_CAP_SETS; ++i) { int j; for (j=0; j<CAP_SET_SIZE; ) { - __u32 val = *from++; + __u32 val; + + val = cap_d->u[j/sizeof(__u32)].flat[i]; result->bytes[j++][i] = val & 0xFF; result->bytes[j++][i] = (val >>= 8) & 0xFF; @@ -87,7 +88,6 @@ cap_t cap_copy_int(const void *cap_ext) (const struct cap_ext_struct *) cap_ext; cap_t cap_d; int set, blen; - __u32 * to; /* Does the external representation make sense? */ if (export == NULL || !memcmp(export->magic, external_magic @@ -100,12 +100,11 @@ cap_t cap_copy_int(const void *cap_ext) if (!(cap_d = cap_init())) return NULL; - to = (__u32 *) &cap_d->set; blen = export->length_of_capset; for (set=0; set<=NUMBER_OF_CAP_SETS; ++set) { int blk; int bno = 0; - for (blk=0; blk<(CAP_SET_SIZE/4); ++blk) { + for (blk=0; blk<(CAP_SET_SIZE/sizeof(__u32)); ++blk) { __u32 val = 0; if (bno != blen) @@ -117,7 +116,7 @@ cap_t cap_copy_int(const void *cap_ext) if (bno != blen) val |= export->bytes[bno++][set] << 24; - *to++ = val; + cap_d->u[blk].flat[set]; } } diff --git a/libcap/cap_file.c b/libcap/cap_file.c index 90a2c40..f1020a9 100644 --- a/libcap/cap_file.c +++ b/libcap/cap_file.c @@ -12,6 +12,11 @@ #include "libcap.h" +#ifdef VFS_CAP_U32 +#if VFS_CAP_U32 != __CAP_BLKS +# error VFS representation of capabilities is not the same size as kernel +#endif + #if __BYTE_ORDER == __BIG_ENDIAN #define FIXUP_32BITS(x) bswap_32(x) #else @@ -21,22 +26,44 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result) { __u32 magic_etc; + unsigned tocopy, i; magic_etc = FIXUP_32BITS(rawvfscap->magic_etc); switch (magic_etc & VFS_CAP_REVISION_MASK) { +#ifdef VFS_CAP_REVISION_1 case VFS_CAP_REVISION_1: - result->set.inheritable = - FIXUP_32BITS(rawvfscap->data[0].inheritable); - result->set.permitted = - FIXUP_32BITS(rawvfscap->data[0].permitted); - if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) { - result->set.effective = - result->set.inheritable | result->set.permitted; - } + tocopy = VFS_CAP_U32_1; + break; +#endif + +#ifdef VFS_CAP_REVISION_2 + case VFS_CAP_REVISION_2: + tocopy = VFS_CAP_U32_2; break; +#endif + default: cap_free(result); result = NULL; + return result; + } + + for (i=0; i < tocopy; i++) { + result->u[i].flat[CAP_INHERITABLE] + = FIXUP_32BITS(rawvfscap->data[i].inheritable); + result->u[i].flat[CAP_PERMITTED] + = FIXUP_32BITS(rawvfscap->data[i].permitted); + if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) { + result->u[i].flat[CAP_EFFECTIVE] + = result->u[i].flat[CAP_INHERITABLE] + | result->u[i].flat[CAP_PERMITTED]; + } + } + while (i < __CAP_BLKS) { + result->u[i].flat[CAP_INHERITABLE] + = result->u[i].flat[CAP_PERMITTED] + = result->u[i].flat[CAP_EFFECTIVE] = 0; + i++; } return result; @@ -44,26 +71,72 @@ static cap_t _fcaps_load(struct vfs_cap_data *rawvfscap, cap_t result) static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d) { + __u32 eff_not_zero, magic; + unsigned tocopy, i; + if (!good_cap_t(cap_d)) { errno = EINVAL; return -1; } - _cap_debug("setting named file capabilities"); + switch (cap_d->head.version) { +#ifdef _LINUX_CAPABILITY_VERSION_1 + case _LINUX_CAPABILITY_VERSION_1: + magic = VFS_CAP_REVISION_1; + tocopy = VFS_CAP_U32_1; + break; +#endif + +#ifdef _LINUX_CAPABILITY_VERSION_2 + case _LINUX_CAPABILITY_VERSION_2: + magic = VFS_CAP_REVISION_2; + tocopy = VFS_CAP_U32_2; + break; +#endif - if (cap_d->set.effective == 0) { - rawvfscap->magic_etc = FIXUP_32BITS(VFS_CAP_REVISION); - } else if ((~(cap_d->set.effective)) - & (cap_d->set.inheritable|cap_d->set.permitted)) { + default: errno = EINVAL; return -1; - } else { - rawvfscap->magic_etc - = FIXUP_32BITS(VFS_CAP_REVISION|VFS_CAP_FLAGS_EFFECTIVE); } - rawvfscap->data[0].permitted = FIXUP_32BITS(cap_d->set.permitted); - rawvfscap->data[0].inheritable = FIXUP_32BITS(cap_d->set.inheritable); + _cap_debug("setting named file capabilities"); + + for (eff_not_zero = 0, i = 0; i < tocopy; i++) { + eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE]; + } + while (i < __CAP_BLKS) { + if ((cap_d->u[i].flat[CAP_EFFECTIVE] + || cap_d->u[i].flat[CAP_INHERITABLE] + || cap_d->u[i].flat[CAP_PERMITTED])) { + /* + * System does not support these capabilities + */ + errno = EINVAL; + return -1; + } + i++; + } + + for (i=0; i < tocopy; i++) { + rawvfscap->data[i].permitted + = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]); + rawvfscap->data[i].inheritable + = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]); + + if (eff_not_zero + && ((~(cap_d->u[i].flat[CAP_EFFECTIVE])) + & (cap_d->u[i].flat[CAP_PERMITTED] + | cap_d->u[i].flat[CAP_INHERITABLE]))) { + errno = EINVAL; + return -1; + } + } + + if (eff_not_zero == 0) { + rawvfscap->magic_etc = FIXUP_32BITS(magic); + } else { + rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE); + } return 0; /* success */ } @@ -89,9 +162,9 @@ cap_t cap_get_fd(int fildes) &rawvfscap, sizeof(rawvfscap))) { cap_free(result); result = NULL; + } else { + result = _fcaps_load(&rawvfscap, result); } - - result = _fcaps_load(&rawvfscap, result); } return result; @@ -117,9 +190,9 @@ cap_t cap_get_file(const char *filename) &rawvfscap, sizeof(rawvfscap))) { cap_free(result); result = NULL; + } else { + result = _fcaps_load(&rawvfscap, result); } - - result = _fcaps_load(&rawvfscap, result); } return result; @@ -166,3 +239,31 @@ int cap_set_file(const char *filename, cap_t cap_d) return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeof(rawvfscap), 0); } + +#else /* ie. ndef VFS_CAP_U32 */ + +cap_t cap_get_fd(int fildes) +{ + errno = EINVAL; + return NULL; +} + +cap_t cap_get_file(const char *filename) +{ + errno = EINVAL; + return NULL; +} + +int cap_set_fd(int fildes, cap_t cap_d) +{ + errno = EINVAL; + return -1; +} + +int cap_set_file(const char *filename, cap_t cap_d) +{ + errno = EINVAL; + return -1; +} + +#endif /* def VFS_CAP_U32 */ diff --git a/libcap/cap_flag.c b/libcap/cap_flag.c index a8567c0..e521fcd 100644 --- a/libcap/cap_flag.c +++ b/libcap/cap_flag.c @@ -23,18 +23,12 @@ int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set, if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS && set >= 0 && set < NUMBER_OF_CAP_SETS) { - __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE - + (__u8 *) &cap_d->set); - - *raised = isset_cap(cap_p,value) ? CAP_SET:CAP_CLEAR; + *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR; return 0; - } else { - _cap_debug("invalid arguments"); errno = EINVAL; return -1; - } } @@ -60,13 +54,11 @@ int cap_set_flag(cap_t cap_d, cap_flag_t set, _cap_debug("weird capability (%d) - skipped", array_values[i]); } else { int value = array_values[i]; - __cap_s *cap_p = (__cap_s *) (set*CAP_SET_SIZE - + (__u8 *) &cap_d->set); if (raise == CAP_SET) { - cap_p->raise_cap(value); + cap_d->raise_cap(value,set); } else { - cap_p->lower_cap(value); + cap_d->lower_cap(value,set); } } } @@ -89,7 +81,7 @@ int cap_clear(cap_t cap_d) { if (good_cap_t(cap_d)) { - memset(&(cap_d->set), 0, sizeof(cap_d->set)); + memset(&(cap_d->u), 0, sizeof(cap_d->u)); return 0; } else { diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c index 5c2ac48..40793b4 100644 --- a/libcap/cap_proc.c +++ b/libcap/cap_proc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 1997-8,2007 Andrew G Morgan <morgan@kernel.org> * * This file deals with setting capabilities on processes. */ @@ -16,7 +16,7 @@ cap_t cap_get_proc(void) _cap_debug("getting current process' capabilities"); /* fill the capability sets via a system call */ - if (capget(&result->head, &result->set)) { + if (capget(&result->head, &result->u[0].set)) { cap_free(result); result = NULL; } @@ -35,9 +35,8 @@ int cap_set_proc(cap_t cap_d) } _cap_debug("setting process capabilities"); - retval = capset(&cap_d->head, &cap_d->set); + retval = capset(&cap_d->head, &cap_d->u[0].set); - cap_d->head.version = _LINUX_CAPABILITY_VERSION; return retval; } @@ -57,8 +56,7 @@ int capgetp(pid_t pid, cap_t cap_d) _cap_debug("getting process capabilities for proc %d", pid); cap_d->head.pid = pid; - error = capget(&cap_d->head, &cap_d->set); - cap_d->head.version = _LINUX_CAPABILITY_VERSION; + error = capget(&cap_d->head, &cap_d->u[0].set); cap_d->head.pid = 0; return error; @@ -77,7 +75,7 @@ int capsetp(pid_t pid, cap_t cap_d) _cap_debug("setting process capabilities for proc %d", pid); cap_d->head.pid = pid; - error = capset(&cap_d->head, &cap_d->set); + error = capset(&cap_d->head, &cap_d->u[0].set); cap_d->head.version = _LINUX_CAPABILITY_VERSION; cap_d->head.pid = 0; diff --git a/libcap/cap_text.c b/libcap/cap_text.c index 5814093..06f61d9 100644 --- a/libcap/cap_text.c +++ b/libcap/cap_text.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-8 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 1997-8,2007 Andrew G Morgan <morgan@kernel.org> * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk> * * This file deals with exchanging internal and textual @@ -24,20 +24,21 @@ * representation. */ -#define setbits(A,B) _setbits((__cap_s *)A, (__cap_s *)B) -static void _setbits(__cap_s *a, __cap_s *b) +#define raise_cap_mask(flat, c) (flat)[CAP_TO_INDEX(c)] |= CAP_TO_MASK(c) + +static void setbits(cap_t a, const __u32 *b, cap_flag_t set) { int n; - for (n = __CAP_BLKS; n--; ) - a->_blk[n] |= b->_blk[n]; + for (n = __CAP_BLKS; n--; ) { + a->u[n].flat[set] |= b[n]; + } } -#define clrbits(A,B) _clrbits((__cap_s *)A, (__cap_s *)B) -static void _clrbits(__cap_s *a, __cap_s *b) +static void clrbits(cap_t a, const __u32 *b, cap_flag_t set) { int n; for (n = __CAP_BLKS; n--; ) - a->_blk[n] &= ~b->_blk[n]; + a->u[n].flat[set] &= ~b[n]; } static char const *namcmp(char const *str, char const *nam) @@ -51,6 +52,15 @@ static char const *namcmp(char const *str, char const *nam) return str; } +static void forceall(__u32 *flat, __u32 value) +{ + unsigned n; + + for (n = __CAP_BLKS; n--; flat[n] = value); + + return; +} + static int lookupname(char const **strp) { union { @@ -80,7 +90,6 @@ static int lookupname(char const **strp) cap_t cap_from_text(const char *str) { cap_t res; - __cap_s allones; int n; if (str == NULL) { @@ -91,22 +100,24 @@ cap_t cap_from_text(const char *str) if (!(res = cap_init())) return NULL; - for (n = __CAP_BLKS; n--; ) - allones._blk[n] = -1; + _cap_debug("%s", str); for (;;) { + __u32 list[__CAP_BLKS]; char op; int flags = 0, listed=0; - __cap_s list = {{0}}; + + forceall(list, 0); /* skip leading spaces */ while (isspace((unsigned char)*str)) str++; if (!*str) { - _cap_debugcap("e = ", &res->set.effective); - _cap_debugcap("i = ", &res->set.inheritable); - _cap_debugcap("p = ", &res->set.permitted); + _cap_debugcap("e = ", *res, CAP_EFFECTIVE); + _cap_debugcap("i = ", *res, CAP_INHERITABLE); + _cap_debugcap("p = ", *res, CAP_PERMITTED); + return res; } @@ -115,12 +126,12 @@ cap_t cap_from_text(const char *str) for (;;) { if (namcmp(str, "all")) { str += 3; - list = allones; + forceall(list, ~0); } else { n = lookupname(&str); if (n == -1) goto bad; - list.raise_cap(n); + raise_cap_mask(list, n); } if (*str != ',') break; @@ -128,10 +139,11 @@ cap_t cap_from_text(const char *str) goto bad; } listed = 1; - } else if (*str == '+' || *str == '-') + } else if (*str == '+' || *str == '-') { goto bad; /* require a list of capabilities */ - else - list = allones; + } else { + forceall(list, ~0); + } /* identify first operation on list of capabilities */ op = *str++; @@ -169,28 +181,28 @@ cap_t cap_from_text(const char *str) case '=': case 'P': /* =+ */ case 'M': /* =- */ - clrbits(&res->set.effective, &list); - clrbits(&res->set.inheritable, &list); - clrbits(&res->set.permitted, &list); - /* fall through */ + clrbits(res, list, CAP_EFFECTIVE); + clrbits(res, list, CAP_PERMITTED); + clrbits(res, list, CAP_INHERITABLE); if (op == 'M') goto minus; + /* fall through */ case '+': if (flags & LIBCAP_EFF) - setbits(&res->set.effective, &list); - if (flags & LIBCAP_INH) - setbits(&res->set.inheritable, &list); + setbits(res, list, CAP_EFFECTIVE); if (flags & LIBCAP_PER) - setbits(&res->set.permitted, &list); + setbits(res, list, CAP_PERMITTED); + if (flags & LIBCAP_INH) + setbits(res, list, CAP_INHERITABLE); break; case '-': minus: - if (flags & LIBCAP_EFF) - clrbits(&res->set.effective, &list); - if (flags & LIBCAP_INH) - clrbits(&res->set.inheritable, &list); + if (flags & LIBCAP_EFF) + clrbits(res, list, CAP_EFFECTIVE); if (flags & LIBCAP_PER) - clrbits(&res->set.permitted, &list); + clrbits(res, list, CAP_PERMITTED); + if (flags & LIBCAP_INH) + clrbits(res, list, CAP_INHERITABLE); break; } @@ -226,12 +238,15 @@ static int getstateflags(cap_t caps, int capno) { int f = 0; - if (isset_cap((__cap_s *)(&caps->set.effective),capno)) + if (isset_cap(caps, capno, CAP_EFFECTIVE)) { f |= LIBCAP_EFF; - if (isset_cap((__cap_s *)(&caps->set.inheritable),capno)) - f |= LIBCAP_INH; - if (isset_cap((__cap_s *)(&caps->set.permitted),capno)) + } + if (isset_cap(caps, capno, CAP_PERMITTED)) { f |= LIBCAP_PER; + } + if (isset_cap(caps, capno, CAP_INHERITABLE)) { + f |= LIBCAP_INH; + } return f; } @@ -251,9 +266,9 @@ char *cap_to_text(cap_t caps, ssize_t *length_p) return NULL; } - _cap_debugcap("e = ", &caps->set.effective); - _cap_debugcap("i = ", &caps->set.inheritable); - _cap_debugcap("p = ", &caps->set.permitted); + _cap_debugcap("e = ", *caps, CAP_EFFECTIVE); + _cap_debugcap("i = ", *caps, CAP_INHERITABLE); + _cap_debugcap("p = ", *caps, CAP_PERMITTED); for (n = __CAP_BITS; n--; ) histo[getstateflags(caps, n)]++; diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h index b9d2636..6dbe656 100644 --- a/libcap/include/sys/capability.h +++ b/libcap/include/sys/capability.h @@ -32,6 +32,7 @@ extern "C" { #define __user typedef unsigned int __u32; +typedef __u32 __le32; #include <linux/capability.h> diff --git a/libcap/libcap.h b/libcap/libcap.h index 20acb6b..820d61a 100644 --- a/libcap/libcap.h +++ b/libcap/libcap.h @@ -26,6 +26,31 @@ #include "cap_names.h" /* + * Do we match the local kernel? + */ + +#if !defined(_LINUX_CAPABILITY_VERSION) + +# error Kernel <linux/capability.h> does not support library +# error file "libcap.h" --> fix and recompile libcap + +#elif (_LINUX_CAPABILITY_VERSION == 0x19980330) + +# warning Kernel <linux/capability.h> does not support 64-bit capabilities +# warning and libcap is being built with no support for 64-bit capabilities + +# ifndef _LINUX_CAPABILITY_VERSION_1 +# define _LINUX_CAPABILITY_VERSION_1 0x19980330 +# endif + +#elif (_LINUX_CAPABILITY_VERSION != 0x20071026) + +# error Kernel <linux/capability.h> does not match library +# error file "libcap.h" --> fix and recompile libcap + +#endif + +/* * This is a pointer to a struct containing three consecutive * capability sets in the order of the cap_flag_t type: the are * effective,inheritable and permitted. This is the type that the @@ -34,40 +59,54 @@ * to processes. */ +#ifndef _LINUX_CAPABILITY_U32S +# define _LINUX_CAPABILITY_U32S 1 +#endif /* ndef _LINUX_CAPABILITY_U32S */ + +#if defined(VFS_CAP_REVISION_MASK) && !defined(VFS_CAP_U32) +# define VFS_CAP_U32_1 1 +# define VFS_CAP_U32 VFS_CAP_U32_1 +struct _cap_vfs_cap_data { + __le32 magic_etc; + struct { + __le32 permitted; + __le32 inheritable; + } data[VFS_CAP_U32_1]; +}; +# define vfs_cap_data _cap_vfs_cap_data +#endif + +#ifndef CAP_TO_INDEX +# define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */ +#endif /* ndef CAP_TO_INDEX */ + +#ifndef CAP_TO_MASK +# define CAP_TO_MASK(x) (1 << ((x) & 31)) +#endif /* ndef CAP_TO_MASK */ + +#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */ +#define __CAP_BLKS (_LINUX_CAPABILITY_U32S) +#define CAP_SET_SIZE (__CAP_BLKS * sizeof(__u32)) + #define CAP_T_MAGIC 0xCA90D0 struct _cap_struct { struct __user_cap_header_struct head; - struct __user_cap_data_struct set; + union { + struct __user_cap_data_struct set; + __u32 flat[NUMBER_OF_CAP_SETS]; + } u[_LINUX_CAPABILITY_U32S]; }; /* string magic for cap_free */ #define CAP_S_MAGIC 0xCA95D0 /* - * Do we match the local kernel? - */ - -#if !defined(_LINUX_CAPABILITY_VERSION) || \ - (_LINUX_CAPABILITY_VERSION != 0x19980330) - -# error "Kernel <linux/capability.h> does not match library" -# error "file "libcap.h" --> fix and recompile libcap" - -#endif - -/* * kernel API cap set abstraction */ -#define NUMBER_OF_CAP_SETS 3 /* effective, inheritable, permitted */ -#define CAP_SET_SIZE (sizeof(struct __user_cap_data_struct)/NUMBER_OF_CAP_SETS) -#define __CAP_BLKS (CAP_SET_SIZE/sizeof(__u32)) -typedef struct { - __u32 _blk[__CAP_BLKS]; -} __cap_s; -#define raise_cap(x) _blk[(x)>>5] |= (1<<((x)&31)) -#define lower_cap(x) _blk[(x)>>5] &= ~(1<<((x)&31)) -#define isset_cap(y,x) ((y)->_blk[(x)>>5] & (1<<((x)&31))) +#define raise_cap(x,set) u[(x)>>5].flat[set] |= (1<<((x)&31)) +#define lower_cap(x,set) u[(x)>>5].flat[set] &= ~(1<<((x)&31)) +#define isset_cap(y,x,set) ((y)->u[(x)>>5].flat[set] & (1<<((x)&31))) /* * Private definitions for internal use by the library. @@ -83,19 +122,25 @@ typedef struct { #ifdef DEBUG #include <stdio.h> -# define _cap_debug(f, x...) { \ +# define _cap_debug(f, x...) do { \ fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): ", __LINE__); \ fprintf(stderr, f, ## x); \ fprintf(stderr, "\n"); \ -} -# define _cap_debugcap(s, c) \ - fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): " s \ - "%08x\n", __LINE__, *(c)) +} while (0) + +# define _cap_debugcap(s, c, set) do { \ + unsigned _cap_index; \ + fprintf(stderr, __FUNCTION__ "(" __FILE__ ":%d): " s, __LINE__); \ + for (_cap_index=_LINUX_CAPABILITY_U32S; _cap_index-- > 0; ) { \ + fprintf(stderr, "%08x", (c).u[_cap_index].flat[set]); \ + } \ + fprintf(stderr, "\n"); \ +} while (0) #else /* !DEBUG */ # define _cap_debug(f, x...) -# define _cap_debugcap(s, c) +# define _cap_debugcap(s, c, set) #endif /* DEBUG */ |