diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-06-03 07:37:26 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-08-02 01:33:42 -0400 |
commit | 3f629636320dfa65804779a3fc333f3147f3b064 (patch) | |
tree | e44dc9f63ae8c6cd37d5471d014cd9b0449027e7 /security/tomoyo/util.c | |
parent | c8c57e842720d8cc92ac8607f2d1c16d92314573 (diff) |
TOMOYO: Allow wildcard for execute permission.
Some applications create and execute programs dynamically. We need to accept
wildcard for execute permission because such programs contain random suffix
in their filenames. This patch loosens up regulation of string parameters.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
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 | } |