1 /*
2  * Copyright (c) 1997-8,2008 Andrew G. Morgan <morgan@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 
cap_get_flag(cap_t cap_d,cap_value_t value,cap_flag_t set,cap_flag_value_t * raised)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 
cap_set_flag(cap_t cap_d,cap_flag_t set,int no_values,const cap_value_t * array_values,cap_flag_value_t raise)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 
cap_clear(cap_t cap_d)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 
cap_clear_flag(cap_t cap_d,cap_flag_t flag)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 
cap_compare(cap_t a,cap_t b)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