• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Authors: Joshua Brindle <jbrindle@tresys.com>
2  * 	    Jason Tang <jtang@tresys.com>
3  *
4  * Copyright (C) 2005-2006 Tresys Technology, LLC
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 
27 #include <sepol/policydb/flask_types.h>
28 #include <sepol/policydb/policydb.h>
29 #include <sepol/policydb/util.h>
30 #include <dso.h>
31 
32 struct val_to_name {
33 	unsigned int val;
34 	char *name;
35 };
36 
37 /* Add an unsigned integer to a dynamically reallocated array.  *cnt
38  * is a reference pointer to the number of values already within array
39  * *a; it will be incremented upon successfully appending i.  If *a is
40  * NULL then this function will create a new array (*cnt is reset to
41  * 0).  Return 0 on success, -1 on out of memory. */
add_i_to_a(uint32_t i,uint32_t * cnt,uint32_t ** a)42 int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a)
43 {
44 	if (cnt == NULL || a == NULL)
45 		return -1;
46 
47 	/* FIX ME: This is not very elegant! We use an array that we
48 	 * grow as new uint32_t are added to an array.  But rather
49 	 * than be smart about it, for now we realloc() the array each
50 	 * time a new uint32_t is added! */
51 	if (*a != NULL)
52 		*a = (uint32_t *) realloc(*a, (*cnt + 1) * sizeof(uint32_t));
53 	else {			/* empty list */
54 
55 		*cnt = 0;
56 		*a = (uint32_t *) malloc(sizeof(uint32_t));
57 	}
58 	if (*a == NULL) {
59 		return -1;
60 	}
61 	(*a)[*cnt] = i;
62 	(*cnt)++;
63 	return 0;
64 }
65 
perm_name(hashtab_key_t key,hashtab_datum_t datum,void * data)66 static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
67 {
68 	struct val_to_name *v = data;
69 	perm_datum_t *perdatum;
70 
71 	perdatum = (perm_datum_t *) datum;
72 
73 	if (v->val == perdatum->s.value) {
74 		v->name = key;
75 		return 1;
76 	}
77 
78 	return 0;
79 }
80 
sepol_av_to_string(policydb_t * policydbp,uint32_t tclass,sepol_access_vector_t av)81 char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass,
82 			 sepol_access_vector_t av)
83 {
84 	struct val_to_name v;
85 	static char avbuf[1024];
86 	class_datum_t *cladatum;
87 	char *perm = NULL, *p;
88 	unsigned int i;
89 	int rc;
90 	int avlen = 0, len;
91 
92 	cladatum = policydbp->class_val_to_struct[tclass - 1];
93 	p = avbuf;
94 	for (i = 0; i < cladatum->permissions.nprim; i++) {
95 		if (av & (1 << i)) {
96 			v.val = i + 1;
97 			rc = hashtab_map(cladatum->permissions.table,
98 					 perm_name, &v);
99 			if (!rc && cladatum->comdatum) {
100 				rc = hashtab_map(cladatum->comdatum->
101 						 permissions.table, perm_name,
102 						 &v);
103 			}
104 			if (rc)
105 				perm = v.name;
106 			if (perm) {
107 				len =
108 				    snprintf(p, sizeof(avbuf) - avlen, " %s",
109 					     perm);
110 				if (len < 0
111 				    || (size_t) len >= (sizeof(avbuf) - avlen))
112 					return NULL;
113 				p += len;
114 				avlen += len;
115 			}
116 		}
117 	}
118 
119 	return avbuf;
120 }
121 
122 #define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p))
123 
sepol_extended_perms_to_string(avtab_extended_perms_t * xperms)124 char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms)
125 {
126 	uint16_t value;
127 	uint16_t low_bit;
128 	uint16_t low_value;
129 	unsigned int bit;
130 	unsigned int in_range = 0;
131 	static char xpermsbuf[2048];
132 	xpermsbuf[0] = '\0';
133 	char *p;
134 	int len, xpermslen = 0;
135 	p = xpermsbuf;
136 
137 	if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
138 		&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
139 		return NULL;
140 
141 	len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "ioctl { ");
142 	p += len;
143 	xpermslen += len;
144 
145 	for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
146 		if (!xperm_test(bit, xperms->perms))
147 			continue;
148 
149 		if (in_range && next_bit_in_range(bit, xperms->perms)) {
150 			/* continue until high value found */
151 			continue;
152 		} else if (next_bit_in_range(bit, xperms->perms)) {
153 			/* low value */
154 			low_bit = bit;
155 			in_range = 1;
156 			continue;
157 		}
158 
159 		if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
160 			value = xperms->driver<<8 | bit;
161 			low_value = xperms->driver<<8 | low_bit;
162 			if (in_range) {
163 				len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, value);
164 			} else {
165 				len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx ", value);
166 			}
167 		} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
168 			value = bit << 8;
169 			low_value = low_bit << 8;
170 			if (in_range) {
171 				len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff));
172 			} else {
173 				len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff));
174 			}
175 
176 		}
177 
178 		if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen))
179 			return NULL;
180 
181 		p += len;
182 		xpermslen += len;
183 		if (in_range)
184 			in_range = 0;
185 	}
186 
187 	len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "}");
188 	if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen))
189 		return NULL;
190 
191 	return xpermsbuf;
192 }
193 
194 /*
195  * The tokenize and tokenize_str functions may be used to
196  * replace sscanf to read tokens from buffers.
197  */
198 
199 /* Read a token from a buffer */
tokenize_str(char delim,char ** str,char ** ptr,size_t * len)200 static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len)
201 {
202 	char *tmp_buf = *ptr;
203 	*str = NULL;
204 
205 	while (**ptr != '\0') {
206 		if (isspace(delim) && isspace(**ptr)) {
207 			(*ptr)++;
208 			break;
209 		} else if (!isspace(delim) && **ptr == delim) {
210 			(*ptr)++;
211 			break;
212 		}
213 
214 		(*ptr)++;
215 	}
216 
217 	*len = *ptr - tmp_buf;
218 	/* If the end of the string has not been reached, this will ensure the
219 	 * delimiter is not included when returning the token.
220 	 */
221 	if (**ptr != '\0') {
222 		(*len)--;
223 	}
224 
225 	*str = strndup(tmp_buf, *len);
226 	if (!*str) {
227 		return -1;
228 	}
229 
230 	/* Squash spaces if the delimiter is a whitespace character */
231 	while (**ptr != '\0' && isspace(delim) && isspace(**ptr)) {
232 		(*ptr)++;
233 	}
234 
235 	return 0;
236 }
237 
238 /*
239  * line_buf - Buffer containing string to tokenize.
240  * delim - The delimiter used to tokenize line_buf. A whitespace delimiter will
241  *	    be tokenized using isspace().
242  * num_args - The number of parameter entries to process.
243  * ...      - A 'char **' for each parameter.
244  * returns  - The number of items processed.
245  *
246  * This function calls tokenize_str() to do the actual string processing. The
247  * caller is responsible for calling free() on each additional argument. The
248  * function will not tokenize more than num_args and the last argument will
249  * contain the remaining content of line_buf. If the delimiter is any whitespace
250  * character, then all whitespace will be squashed.
251  */
tokenize(char * line_buf,char delim,int num_args,...)252 int hidden tokenize(char *line_buf, char delim, int num_args, ...)
253 {
254 	char **arg, *buf_p;
255 	int rc, items;
256 	size_t arg_len = 0;
257 	va_list ap;
258 
259 	buf_p = line_buf;
260 
261 	/* Process the arguments */
262 	va_start(ap, num_args);
263 
264 	for (items = 0; items < num_args && *buf_p != '\0'; items++) {
265 		arg = va_arg(ap, char **);
266 
267 		/* Save the remainder of the string in arg */
268 		if (items == num_args - 1) {
269 			*arg = strdup(buf_p);
270 			if (*arg == NULL) {
271 				goto exit;
272 			}
273 
274 			continue;
275 		}
276 
277 		rc = tokenize_str(delim, arg, &buf_p, &arg_len);
278 		if (rc < 0) {
279 			goto exit;
280 		}
281 	}
282 
283 exit:
284 	va_end(ap);
285 	return items;
286 }
287