diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-07-08 00:22:41 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-07-10 21:05:32 -0400 |
commit | 8761afd49ebff8ae04c1a7888af090177441d07d (patch) | |
tree | f43b52e1b8467eeea465762d2f9d0b81a336faa0 /security/tomoyo/condition.c | |
parent | 2066a36125fcbf5220990173b9d8e8bc49ad7538 (diff) |
TOMOYO: Allow using owner/group etc. of file objects as conditions.
This patch adds support for permission checks using file object's DAC
attributes (e.g. owner/group) when checking file's pathnames. Hooks for passing
file object's pointers are in the last patch of this pathset.
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/condition.c')
-rw-r--r-- | security/tomoyo/condition.c | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 0692df3cddcc..ac7ebeb47d7d 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c | |||
@@ -244,6 +244,54 @@ out: | |||
244 | } | 244 | } |
245 | 245 | ||
246 | /** | 246 | /** |
247 | * tomoyo_get_attributes - Revalidate "struct inode". | ||
248 | * | ||
249 | * @obj: Pointer to "struct tomoyo_obj_info". | ||
250 | * | ||
251 | * Returns nothing. | ||
252 | */ | ||
253 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj) | ||
254 | { | ||
255 | u8 i; | ||
256 | struct dentry *dentry = NULL; | ||
257 | |||
258 | for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { | ||
259 | struct inode *inode; | ||
260 | switch (i) { | ||
261 | case TOMOYO_PATH1: | ||
262 | dentry = obj->path1.dentry; | ||
263 | if (!dentry) | ||
264 | continue; | ||
265 | break; | ||
266 | case TOMOYO_PATH2: | ||
267 | dentry = obj->path2.dentry; | ||
268 | if (!dentry) | ||
269 | continue; | ||
270 | break; | ||
271 | default: | ||
272 | if (!dentry) | ||
273 | continue; | ||
274 | dentry = dget_parent(dentry); | ||
275 | break; | ||
276 | } | ||
277 | inode = dentry->d_inode; | ||
278 | if (inode) { | ||
279 | struct tomoyo_mini_stat *stat = &obj->stat[i]; | ||
280 | stat->uid = inode->i_uid; | ||
281 | stat->gid = inode->i_gid; | ||
282 | stat->ino = inode->i_ino; | ||
283 | stat->mode = inode->i_mode; | ||
284 | stat->dev = inode->i_sb->s_dev; | ||
285 | stat->rdev = inode->i_rdev; | ||
286 | obj->stat_valid[i] = true; | ||
287 | } | ||
288 | if (i & 1) /* i == TOMOYO_PATH1_PARENT || | ||
289 | i == TOMOYO_PATH2_PARENT */ | ||
290 | dput(dentry); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /** | ||
247 | * tomoyo_condition - Check condition part. | 295 | * tomoyo_condition - Check condition part. |
248 | * | 296 | * |
249 | * @r: Pointer to "struct tomoyo_request_info". | 297 | * @r: Pointer to "struct tomoyo_request_info". |
@@ -261,16 +309,19 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
261 | unsigned long max_v[2] = { 0, 0 }; | 309 | unsigned long max_v[2] = { 0, 0 }; |
262 | const struct tomoyo_condition_element *condp; | 310 | const struct tomoyo_condition_element *condp; |
263 | const struct tomoyo_number_union *numbers_p; | 311 | const struct tomoyo_number_union *numbers_p; |
312 | struct tomoyo_obj_info *obj; | ||
264 | u16 condc; | 313 | u16 condc; |
265 | if (!cond) | 314 | if (!cond) |
266 | return true; | 315 | return true; |
267 | condc = cond->condc; | 316 | condc = cond->condc; |
317 | obj = r->obj; | ||
268 | condp = (struct tomoyo_condition_element *) (cond + 1); | 318 | condp = (struct tomoyo_condition_element *) (cond + 1); |
269 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); | 319 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); |
270 | for (i = 0; i < condc; i++) { | 320 | for (i = 0; i < condc; i++) { |
271 | const bool match = condp->equals; | 321 | const bool match = condp->equals; |
272 | const u8 left = condp->left; | 322 | const u8 left = condp->left; |
273 | const u8 right = condp->right; | 323 | const u8 right = condp->right; |
324 | bool is_bitop[2] = { false, false }; | ||
274 | u8 j; | 325 | u8 j; |
275 | condp++; | 326 | condp++; |
276 | /* Check numeric or bit-op expressions. */ | 327 | /* Check numeric or bit-op expressions. */ |
@@ -308,14 +359,185 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
308 | case TOMOYO_TASK_PPID: | 359 | case TOMOYO_TASK_PPID: |
309 | value = tomoyo_sys_getppid(); | 360 | value = tomoyo_sys_getppid(); |
310 | break; | 361 | break; |
362 | case TOMOYO_TYPE_IS_SOCKET: | ||
363 | value = S_IFSOCK; | ||
364 | break; | ||
365 | case TOMOYO_TYPE_IS_SYMLINK: | ||
366 | value = S_IFLNK; | ||
367 | break; | ||
368 | case TOMOYO_TYPE_IS_FILE: | ||
369 | value = S_IFREG; | ||
370 | break; | ||
371 | case TOMOYO_TYPE_IS_BLOCK_DEV: | ||
372 | value = S_IFBLK; | ||
373 | break; | ||
374 | case TOMOYO_TYPE_IS_DIRECTORY: | ||
375 | value = S_IFDIR; | ||
376 | break; | ||
377 | case TOMOYO_TYPE_IS_CHAR_DEV: | ||
378 | value = S_IFCHR; | ||
379 | break; | ||
380 | case TOMOYO_TYPE_IS_FIFO: | ||
381 | value = S_IFIFO; | ||
382 | break; | ||
383 | case TOMOYO_MODE_SETUID: | ||
384 | value = S_ISUID; | ||
385 | break; | ||
386 | case TOMOYO_MODE_SETGID: | ||
387 | value = S_ISGID; | ||
388 | break; | ||
389 | case TOMOYO_MODE_STICKY: | ||
390 | value = S_ISVTX; | ||
391 | break; | ||
392 | case TOMOYO_MODE_OWNER_READ: | ||
393 | value = S_IRUSR; | ||
394 | break; | ||
395 | case TOMOYO_MODE_OWNER_WRITE: | ||
396 | value = S_IWUSR; | ||
397 | break; | ||
398 | case TOMOYO_MODE_OWNER_EXECUTE: | ||
399 | value = S_IXUSR; | ||
400 | break; | ||
401 | case TOMOYO_MODE_GROUP_READ: | ||
402 | value = S_IRGRP; | ||
403 | break; | ||
404 | case TOMOYO_MODE_GROUP_WRITE: | ||
405 | value = S_IWGRP; | ||
406 | break; | ||
407 | case TOMOYO_MODE_GROUP_EXECUTE: | ||
408 | value = S_IXGRP; | ||
409 | break; | ||
410 | case TOMOYO_MODE_OTHERS_READ: | ||
411 | value = S_IROTH; | ||
412 | break; | ||
413 | case TOMOYO_MODE_OTHERS_WRITE: | ||
414 | value = S_IWOTH; | ||
415 | break; | ||
416 | case TOMOYO_MODE_OTHERS_EXECUTE: | ||
417 | value = S_IXOTH; | ||
418 | break; | ||
311 | case TOMOYO_NUMBER_UNION: | 419 | case TOMOYO_NUMBER_UNION: |
312 | /* Fetch values later. */ | 420 | /* Fetch values later. */ |
313 | break; | 421 | break; |
314 | default: | 422 | default: |
423 | if (!obj) | ||
424 | goto out; | ||
425 | if (!obj->validate_done) { | ||
426 | tomoyo_get_attributes(obj); | ||
427 | obj->validate_done = true; | ||
428 | } | ||
429 | { | ||
430 | u8 stat_index; | ||
431 | struct tomoyo_mini_stat *stat; | ||
432 | switch (index) { | ||
433 | case TOMOYO_PATH1_UID: | ||
434 | case TOMOYO_PATH1_GID: | ||
435 | case TOMOYO_PATH1_INO: | ||
436 | case TOMOYO_PATH1_MAJOR: | ||
437 | case TOMOYO_PATH1_MINOR: | ||
438 | case TOMOYO_PATH1_TYPE: | ||
439 | case TOMOYO_PATH1_DEV_MAJOR: | ||
440 | case TOMOYO_PATH1_DEV_MINOR: | ||
441 | case TOMOYO_PATH1_PERM: | ||
442 | stat_index = TOMOYO_PATH1; | ||
443 | break; | ||
444 | case TOMOYO_PATH2_UID: | ||
445 | case TOMOYO_PATH2_GID: | ||
446 | case TOMOYO_PATH2_INO: | ||
447 | case TOMOYO_PATH2_MAJOR: | ||
448 | case TOMOYO_PATH2_MINOR: | ||
449 | case TOMOYO_PATH2_TYPE: | ||
450 | case TOMOYO_PATH2_DEV_MAJOR: | ||
451 | case TOMOYO_PATH2_DEV_MINOR: | ||
452 | case TOMOYO_PATH2_PERM: | ||
453 | stat_index = TOMOYO_PATH2; | ||
454 | break; | ||
455 | case TOMOYO_PATH1_PARENT_UID: | ||
456 | case TOMOYO_PATH1_PARENT_GID: | ||
457 | case TOMOYO_PATH1_PARENT_INO: | ||
458 | case TOMOYO_PATH1_PARENT_PERM: | ||
459 | stat_index = | ||
460 | TOMOYO_PATH1_PARENT; | ||
461 | break; | ||
462 | case TOMOYO_PATH2_PARENT_UID: | ||
463 | case TOMOYO_PATH2_PARENT_GID: | ||
464 | case TOMOYO_PATH2_PARENT_INO: | ||
465 | case TOMOYO_PATH2_PARENT_PERM: | ||
466 | stat_index = | ||
467 | TOMOYO_PATH2_PARENT; | ||
468 | break; | ||
469 | default: | ||
470 | goto out; | ||
471 | } | ||
472 | if (!obj->stat_valid[stat_index]) | ||
473 | goto out; | ||
474 | stat = &obj->stat[stat_index]; | ||
475 | switch (index) { | ||
476 | case TOMOYO_PATH1_UID: | ||
477 | case TOMOYO_PATH2_UID: | ||
478 | case TOMOYO_PATH1_PARENT_UID: | ||
479 | case TOMOYO_PATH2_PARENT_UID: | ||
480 | value = stat->uid; | ||
481 | break; | ||
482 | case TOMOYO_PATH1_GID: | ||
483 | case TOMOYO_PATH2_GID: | ||
484 | case TOMOYO_PATH1_PARENT_GID: | ||
485 | case TOMOYO_PATH2_PARENT_GID: | ||
486 | value = stat->gid; | ||
487 | break; | ||
488 | case TOMOYO_PATH1_INO: | ||
489 | case TOMOYO_PATH2_INO: | ||
490 | case TOMOYO_PATH1_PARENT_INO: | ||
491 | case TOMOYO_PATH2_PARENT_INO: | ||
492 | value = stat->ino; | ||
493 | break; | ||
494 | case TOMOYO_PATH1_MAJOR: | ||
495 | case TOMOYO_PATH2_MAJOR: | ||
496 | value = MAJOR(stat->dev); | ||
497 | break; | ||
498 | case TOMOYO_PATH1_MINOR: | ||
499 | case TOMOYO_PATH2_MINOR: | ||
500 | value = MINOR(stat->dev); | ||
501 | break; | ||
502 | case TOMOYO_PATH1_TYPE: | ||
503 | case TOMOYO_PATH2_TYPE: | ||
504 | value = stat->mode & S_IFMT; | ||
505 | break; | ||
506 | case TOMOYO_PATH1_DEV_MAJOR: | ||
507 | case TOMOYO_PATH2_DEV_MAJOR: | ||
508 | value = MAJOR(stat->rdev); | ||
509 | break; | ||
510 | case TOMOYO_PATH1_DEV_MINOR: | ||
511 | case TOMOYO_PATH2_DEV_MINOR: | ||
512 | value = MINOR(stat->rdev); | ||
513 | break; | ||
514 | case TOMOYO_PATH1_PERM: | ||
515 | case TOMOYO_PATH2_PERM: | ||
516 | case TOMOYO_PATH1_PARENT_PERM: | ||
517 | case TOMOYO_PATH2_PARENT_PERM: | ||
518 | value = stat->mode & S_IALLUGO; | ||
519 | break; | ||
520 | } | ||
521 | } | ||
315 | break; | 522 | break; |
316 | } | 523 | } |
317 | max_v[j] = value; | 524 | max_v[j] = value; |
318 | min_v[j] = value; | 525 | min_v[j] = value; |
526 | switch (index) { | ||
527 | case TOMOYO_MODE_SETUID: | ||
528 | case TOMOYO_MODE_SETGID: | ||
529 | case TOMOYO_MODE_STICKY: | ||
530 | case TOMOYO_MODE_OWNER_READ: | ||
531 | case TOMOYO_MODE_OWNER_WRITE: | ||
532 | case TOMOYO_MODE_OWNER_EXECUTE: | ||
533 | case TOMOYO_MODE_GROUP_READ: | ||
534 | case TOMOYO_MODE_GROUP_WRITE: | ||
535 | case TOMOYO_MODE_GROUP_EXECUTE: | ||
536 | case TOMOYO_MODE_OTHERS_READ: | ||
537 | case TOMOYO_MODE_OTHERS_WRITE: | ||
538 | case TOMOYO_MODE_OTHERS_EXECUTE: | ||
539 | is_bitop[j] = true; | ||
540 | } | ||
319 | } | 541 | } |
320 | if (left == TOMOYO_NUMBER_UNION) { | 542 | if (left == TOMOYO_NUMBER_UNION) { |
321 | /* Fetch values now. */ | 543 | /* Fetch values now. */ |
@@ -339,6 +561,33 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
339 | } | 561 | } |
340 | goto out; | 562 | goto out; |
341 | } | 563 | } |
564 | /* | ||
565 | * Bit operation is valid only when counterpart value | ||
566 | * represents permission. | ||
567 | */ | ||
568 | if (is_bitop[0] && is_bitop[1]) { | ||
569 | goto out; | ||
570 | } else if (is_bitop[0]) { | ||
571 | switch (right) { | ||
572 | case TOMOYO_PATH1_PERM: | ||
573 | case TOMOYO_PATH1_PARENT_PERM: | ||
574 | case TOMOYO_PATH2_PERM: | ||
575 | case TOMOYO_PATH2_PARENT_PERM: | ||
576 | if (!(max_v[0] & max_v[1]) == !match) | ||
577 | continue; | ||
578 | } | ||
579 | goto out; | ||
580 | } else if (is_bitop[1]) { | ||
581 | switch (left) { | ||
582 | case TOMOYO_PATH1_PERM: | ||
583 | case TOMOYO_PATH1_PARENT_PERM: | ||
584 | case TOMOYO_PATH2_PERM: | ||
585 | case TOMOYO_PATH2_PARENT_PERM: | ||
586 | if (!(max_v[0] & max_v[1]) == !match) | ||
587 | continue; | ||
588 | } | ||
589 | goto out; | ||
590 | } | ||
342 | /* Normal value range comparison. */ | 591 | /* Normal value range comparison. */ |
343 | if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match) | 592 | if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match) |
344 | continue; | 593 | continue; |