/* * 0xCA910002 * CA91 - magic * 000 - ABI version * 2 - cr_rights[] array size */ #define CAP_RIGHTS_VERSION_00 0xCA910002 /* #define CAP_RIGHTS_VERSION_01 0xcA910013 */ #define CAP_RIGHTS_VERSION CAP_RIGHTS_VERSION_00 struct cap_rights { uint64_t cr_version; uint64_t cr_rights[CAP_RIGHTS_VERSION & 0xF]; }; typedef struct cap_rights cap_rights_t; /* * Documented prototypes: * * int cap_rights_limit(int fd, const cap_rights_t *rights); * int cap_rights_get(int fd, cap_rights_t *rights); * * void cap_rights_init(cap_rights_t *rights); * void cap_rights_set(cap_rights_t *rights, ...); * void cap_rights_clear(cap_rights_t *rights, ...); * void cap_rights_is_set(const cap_rights_t *rights, ...); * void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); */ /* System calls. */ int cap_rights_limit(int fd, const cap_rights_t *rights); int __cap_rights_limit(uint64_t version, int fd, const cap_rights_t *rights); #define cap_rights_limit(fd, rights) __cap_rights_limit(CAP_RIGHTS_VERSION, (fd), (rights)) #define cap_rights_init(rights) __cap_rights_init(CAP_RIGHTS_VERSION, (rights)) #define cap_rights_set(rights, ...) __cap_rights_set((rights), __VA_ARGS__, 0) #define cap_rights_clear(rights, ...) __cap_rights_clear((rights), __VA_ARGS__, 0) #define cap_rights_is_set(rights, ...) __cap_rights_is_set((rights), __VA_ARGS__, 0) void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); void __cap_rights_init(uint64_t version, cap_rights_t *rights); void __cap_rights_set(cap_rights_t *rights, ...); void __cap_rights_clear(cap_rights_t *rights, ...); void __cap_rights_is_set(uint64_t version, const cap_rights_t *rights, ...); void __cap_rights_init(uint64_t version, cap_rights_t *rights) { unsigned int n; assert(version == CAP_RIGHTS_VERSION_00); n = (version & 0xF); memset(rights->cr_rights, 0, sizeof(rights->cr_rights[0]) * n); rights->cr_version = version; } void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src) { unsigned int i, n; assert(dst->cr_version == CAP_RIGHTS_VERSION_00); assert(src->cr_version == CAP_RIGHTS_VERSION_00); assert(dst->cr_version == src->cr_version); n = (dst->cr_version & 0xF); for (i = 0; i < n; i++) dst->cr_rights[i] |= src->cr_rights[i]; } static __inline unsigned int right_to_index(uint64_t right) { static const int bit2idx[] = { -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1 }; int idx; idx = (int)(right >> 60); assert(idx == 1 || idx == 2 || idx == 4 || idx == 8); idx = bit2idx[idx]; assert(idx >= 0 && idx <= 3); return ((unsigned int)idx); } void __cap_rights_set(cap_rights_t *rights, ...) { unsigned int i, n; uint64_t right; va_list ap; assert(rights->cr_version == CAP_RIGHTS_VERSION_00); n = (rights->cr_version & 0xF); va_start(ap, rights); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; i = right_to_index(right); assert(i < n); rights->cr_rights[i] |= right; } va_end(ap); } void __cap_rights_clear(cap_rights_t *rights, ...) { unsigned int i, n; uint64_t right; va_list ap; assert(rights->cr_version == CAP_RIGHTS_VERSION_00); n = (rights->cr_version & 0xF); va_start(ap, rights); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; i = right_to_index(right); assert(i < n); rights->cr_rights[i] &= ~(right & 0x0FFFFFFFFFFFFFFFULL); } va_end(ap); } bool __cap_rights_is_set(const cap_rights_t *rights, ...) { unsigned int i, n; uint64_t right; va_list ap; assert(rights->cr_version == CAP_RIGHTS_VERSION_00); n = (rights->cr_version & 0xF); va_start(ap, rights); for (;;) { right = (uint64_t)va_arg(ap, unsigned long long); if (right == 0) break; i = right_to_index(right); assert(i < n); if ((rights->cr_rights[i] & right) != right) { va_end(ap); return (false); } } va_end(ap); return (true); }