1 /* 2 * Copyright (c) 1997-8,2008 Andrew G. Morgan <morgan (at) kernel.org> 3 * 4 * This file deals with flipping of capabilities on internal 5 * capability sets as specified by POSIX.1e (formerlly, POSIX 6). 6 */ 7 8 #include "libcap.h" 9 10 /* 11 * Return the state of a specified capability flag. The state is 12 * returned as the contents of *raised. The capability is from one of 13 * the sets stored in cap_d as specified by set and value 14 */ 15 16 int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t set, 17 cap_flag_value_t *raised) 18 { 19 /* 20 * Do we have a set and a place to store its value? 21 * Is it a known capability? 22 */ 23 24 if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS 25 && set >= 0 && set < NUMBER_OF_CAP_SETS) { 26 *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR; 27 return 0; 28 } else { 29 _cap_debug("invalid arguments"); 30 errno = EINVAL; 31 return -1; 32 } 33 } 34 35 /* 36 * raise/lower a selection of capabilities 37 */ 38 39 int cap_set_flag(cap_t cap_d, cap_flag_t set, 40 int no_values, const cap_value_t *array_values, 41 cap_flag_value_t raise) 42 { 43 /* 44 * Do we have a set and a place to store its value? 45 * Is it a known capability? 46 */ 47 48 if (good_cap_t(cap_d) && no_values > 0 && no_values <= __CAP_BITS 49 && (set >= 0) && (set < NUMBER_OF_CAP_SETS) 50 && (raise == CAP_SET || raise == CAP_CLEAR) ) { 51 int i; 52 for (i=0; i<no_values; ++i) { 53 if (array_values[i] < 0 || array_values[i] >= __CAP_BITS) { 54 _cap_debug("weird capability (%d) - skipped", array_values[i]); 55 } else { 56 int value = array_values[i]; 57 58 if (raise == CAP_SET) { 59 cap_d->raise_cap(value,set); 60 } else { 61 cap_d->lower_cap(value,set); 62 } 63 } 64 } 65 return 0; 66 67 } else { 68 69 _cap_debug("invalid arguments"); 70 errno = EINVAL; 71 return -1; 72 73 } 74 } 75 76 /* 77 * Reset the capability to be empty (nothing raised) 78 */ 79 80 int cap_clear(cap_t cap_d) 81 { 82 if (good_cap_t(cap_d)) { 83 84 memset(&(cap_d->u), 0, sizeof(cap_d->u)); 85 return 0; 86 87 } else { 88 89 _cap_debug("invalid pointer"); 90 errno = EINVAL; 91 return -1; 92 93 } 94 } 95 96 /* 97 * Reset the all of the capability bits for one of the flag sets 98 */ 99 100 int cap_clear_flag(cap_t cap_d, cap_flag_t flag) 101 { 102 switch (flag) { 103 case CAP_EFFECTIVE: 104 case CAP_PERMITTED: 105 case CAP_INHERITABLE: 106 if (good_cap_t(cap_d)) { 107 unsigned i; 108 109 for (i=0; i<_LIBCAP_CAPABILITY_U32S; i++) { 110 cap_d->u[i].flat[flag] = 0; 111 } 112 return 0; 113 } 114 /* 115 * fall through 116 */ 117 118 default: 119 _cap_debug("invalid pointer"); 120 errno = EINVAL; 121 return -1; 122 } 123 } 124 125 /* 126 * Compare two capability sets 127 */ 128 129 int cap_compare(cap_t a, cap_t b) 130 { 131 unsigned i; 132 int result; 133 134 if (!(good_cap_t(a) && good_cap_t(b))) { 135 _cap_debug("invalid arguments"); 136 errno = EINVAL; 137 return -1; 138 } 139 140 for (i=0, result=0; i<_LIBCAP_CAPABILITY_U32S; i++) { 141 result |= 142 ((a->u[i].flat[CAP_EFFECTIVE] != b->u[i].flat[CAP_EFFECTIVE]) 143 ? LIBCAP_EFF : 0) 144 | ((a->u[i].flat[CAP_INHERITABLE] != b->u[i].flat[CAP_INHERITABLE]) 145 ? LIBCAP_INH : 0) 146 | ((a->u[i].flat[CAP_PERMITTED] != b->u[i].flat[CAP_PERMITTED]) 147 ? LIBCAP_PER : 0); 148 } 149 return result; 150 } 151