aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/util.c')
-rw-r--r--security/tomoyo/util.c154
1 files changed, 59 insertions, 95 deletions
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 7b023f5e1314..592b76a2bce8 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -89,7 +89,7 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
89bool tomoyo_parse_name_union(const char *filename, 89bool tomoyo_parse_name_union(const char *filename,
90 struct tomoyo_name_union *ptr) 90 struct tomoyo_name_union *ptr)
91{ 91{
92 if (!tomoyo_is_correct_path(filename, 0, 0, 0)) 92 if (!tomoyo_is_correct_word(filename))
93 return false; 93 return false;
94 if (filename[0] == '@') { 94 if (filename[0] == '@') {
95 ptr->group = tomoyo_get_path_group(filename + 1); 95 ptr->group = tomoyo_get_path_group(filename + 1);
@@ -115,7 +115,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
115 unsigned long v; 115 unsigned long v;
116 memset(num, 0, sizeof(*num)); 116 memset(num, 0, sizeof(*num));
117 if (data[0] == '@') { 117 if (data[0] == '@') {
118 if (!tomoyo_is_correct_path(data, 0, 0, 0)) 118 if (!tomoyo_is_correct_word(data))
119 return false; 119 return false;
120 num->group = tomoyo_get_number_group(data + 1); 120 num->group = tomoyo_get_number_group(data + 1);
121 num->is_group = true; 121 num->is_group = true;
@@ -265,54 +265,29 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
265} 265}
266 266
267/** 267/**
268 * tomoyo_is_correct_path - Validate a pathname. 268 * tomoyo_is_correct_word2 - Validate a string.
269 * 269 *
270 * @filename: The pathname to check. 270 * @string: The string to check. May be non-'\0'-terminated.
271 * @start_type: Should the pathname start with '/'? 271 * @len: Length of @string.
272 * 1 = must / -1 = must not / 0 = don't care
273 * @pattern_type: Can the pathname contain a wildcard?
274 * 1 = must / -1 = must not / 0 = don't care
275 * @end_type: Should the pathname end with '/'?
276 * 1 = must / -1 = must not / 0 = don't care
277 * 272 *
278 * Check whether the given filename follows the naming rules. 273 * Check whether the given string follows the naming rules.
279 * Returns true if @filename follows the naming rules, false otherwise. 274 * Returns true if @string follows the naming rules, false otherwise.
280 */ 275 */
281bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 276static bool tomoyo_is_correct_word2(const char *string, size_t len)
282 const s8 pattern_type, const s8 end_type)
283{ 277{
284 const char *const start = filename; 278 const char *const start = string;
285 bool in_repetition = false; 279 bool in_repetition = false;
286 bool contains_pattern = false;
287 unsigned char c; 280 unsigned char c;
288 unsigned char d; 281 unsigned char d;
289 unsigned char e; 282 unsigned char e;
290 283 if (!len)
291 if (!filename)
292 goto out; 284 goto out;
293 c = *filename; 285 while (len--) {
294 if (start_type == 1) { /* Must start with '/' */ 286 c = *string++;
295 if (c != '/')
296 goto out;
297 } else if (start_type == -1) { /* Must not start with '/' */
298 if (c == '/')
299 goto out;
300 }
301 if (c)
302 c = *(filename + strlen(filename) - 1);
303 if (end_type == 1) { /* Must end with '/' */
304 if (c != '/')
305 goto out;
306 } else if (end_type == -1) { /* Must not end with '/' */
307 if (c == '/')
308 goto out;
309 }
310 while (1) {
311 c = *filename++;
312 if (!c)
313 break;
314 if (c == '\\') { 287 if (c == '\\') {
315 c = *filename++; 288 if (!len--)
289 goto out;
290 c = *string++;
316 switch (c) { 291 switch (c) {
317 case '\\': /* "\\" */ 292 case '\\': /* "\\" */
318 continue; 293 continue;
@@ -326,21 +301,14 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
326 case 'a': /* "\a" */ 301 case 'a': /* "\a" */
327 case 'A': /* "\A" */ 302 case 'A': /* "\A" */
328 case '-': /* "\-" */ 303 case '-': /* "\-" */
329 if (pattern_type == -1)
330 break; /* Must not contain pattern */
331 contains_pattern = true;
332 continue; 304 continue;
333 case '{': /* "/\{" */ 305 case '{': /* "/\{" */
334 if (filename - 3 < start || 306 if (string - 3 < start || *(string - 3) != '/')
335 *(filename - 3) != '/')
336 break; 307 break;
337 if (pattern_type == -1)
338 break; /* Must not contain pattern */
339 contains_pattern = true;
340 in_repetition = true; 308 in_repetition = true;
341 continue; 309 continue;
342 case '}': /* "\}/" */ 310 case '}': /* "\}/" */
343 if (*filename != '/') 311 if (*string != '/')
344 break; 312 break;
345 if (!in_repetition) 313 if (!in_repetition)
346 break; 314 break;
@@ -350,11 +318,11 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
350 case '1': 318 case '1':
351 case '2': 319 case '2':
352 case '3': 320 case '3':
353 d = *filename++; 321 if (!len-- || !len--)
354 if (d < '0' || d > '7')
355 break; 322 break;
356 e = *filename++; 323 d = *string++;
357 if (e < '0' || e > '7') 324 e = *string++;
325 if (d < '0' || d > '7' || e < '0' || e > '7')
358 break; 326 break;
359 c = tomoyo_make_byte(c, d, e); 327 c = tomoyo_make_byte(c, d, e);
360 if (tomoyo_is_invalid(c)) 328 if (tomoyo_is_invalid(c))
@@ -367,10 +335,6 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
367 goto out; 335 goto out;
368 } 336 }
369 } 337 }
370 if (pattern_type == 1) { /* Must contain pattern */
371 if (!contains_pattern)
372 goto out;
373 }
374 if (in_repetition) 338 if (in_repetition)
375 goto out; 339 goto out;
376 return true; 340 return true;
@@ -379,58 +343,58 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
379} 343}
380 344
381/** 345/**
346 * tomoyo_is_correct_word - Validate a string.
347 *
348 * @string: The string to check.
349 *
350 * Check whether the given string follows the naming rules.
351 * Returns true if @string follows the naming rules, false otherwise.
352 */
353bool tomoyo_is_correct_word(const char *string)
354{
355 return tomoyo_is_correct_word2(string, strlen(string));
356}
357
358/**
359 * tomoyo_is_correct_path - Validate a pathname.
360 *
361 * @filename: The pathname to check.
362 *
363 * Check whether the given pathname follows the naming rules.
364 * Returns true if @filename follows the naming rules, false otherwise.
365 */
366bool tomoyo_is_correct_path(const char *filename)
367{
368 return *filename == '/' && tomoyo_is_correct_word(filename);
369}
370
371/**
382 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. 372 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
383 * 373 *
384 * @domainname: The domainname to check. 374 * @domainname: The domainname to check.
385 * 375 *
386 * Returns true if @domainname follows the naming rules, false otherwise. 376 * Returns true if @domainname follows the naming rules, false otherwise.
387 */ 377 */
388bool tomoyo_is_correct_domain(const unsigned char *domainname) 378bool tomoyo_is_correct_domain(const unsigned char *domainname)
389{ 379{
390 unsigned char c;
391 unsigned char d;
392 unsigned char e;
393
394 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 380 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
395 TOMOYO_ROOT_NAME_LEN)) 381 TOMOYO_ROOT_NAME_LEN))
396 goto out; 382 goto out;
397 domainname += TOMOYO_ROOT_NAME_LEN; 383 domainname += TOMOYO_ROOT_NAME_LEN;
398 if (!*domainname) 384 if (!*domainname)
399 return true; 385 return true;
400 do { 386 if (*domainname++ != ' ')
401 if (*domainname++ != ' ') 387 goto out;
402 goto out; 388 while (1) {
403 if (*domainname++ != '/') 389 const unsigned char *cp = strchr(domainname, ' ');
390 if (!cp)
391 break;
392 if (*domainname != '/' ||
393 !tomoyo_is_correct_word2(domainname, cp - domainname - 1))
404 goto out; 394 goto out;
405 while ((c = *domainname) != '\0' && c != ' ') { 395 domainname = cp + 1;
406 domainname++; 396 }
407 if (c == '\\') { 397 return tomoyo_is_correct_path(domainname);
408 c = *domainname++;
409 switch ((c)) {
410 case '\\': /* "\\" */
411 continue;
412 case '0': /* "\ooo" */
413 case '1':
414 case '2':
415 case '3':
416 d = *domainname++;
417 if (d < '0' || d > '7')
418 break;
419 e = *domainname++;
420 if (e < '0' || e > '7')
421 break;
422 c = tomoyo_make_byte(c, d, e);
423 if (tomoyo_is_invalid(c))
424 /* pattern is not \000 */
425 continue;
426 }
427 goto out;
428 } else if (tomoyo_is_invalid(c)) {
429 goto out;
430 }
431 }
432 } while (*domainname);
433 return true;
434 out: 398 out:
435 return false; 399 return false;
436} 400}