diff options
Diffstat (limited to 'security/tomoyo/util.c')
-rw-r--r-- | security/tomoyo/util.c | 154 |
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, | |||
89 | bool tomoyo_parse_name_union(const char *filename, | 89 | bool 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 | */ |
281 | bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | 276 | static 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 | */ | ||
353 | bool 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 | */ | ||
366 | bool 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 | */ |
388 | bool tomoyo_is_correct_domain(const unsigned char *domainname) | 378 | bool 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 | } |