aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/util.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-06-03 07:37:26 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:33:42 -0400
commit3f629636320dfa65804779a3fc333f3147f3b064 (patch)
treee44dc9f63ae8c6cd37d5471d014cd9b0449027e7 /security/tomoyo/util.c
parentc8c57e842720d8cc92ac8607f2d1c16d92314573 (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.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}