diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit_tree.c | 100 | ||||
-rw-r--r-- | kernel/auditsc.c | 7 | ||||
-rw-r--r-- | kernel/sysctl_binary.c | 7 |
3 files changed, 32 insertions, 82 deletions
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 4b05bd9479db..028e85663f27 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -548,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule) | |||
548 | return 0; | 548 | return 0; |
549 | } | 549 | } |
550 | 550 | ||
551 | static int compare_root(struct vfsmount *mnt, void *arg) | ||
552 | { | ||
553 | return mnt->mnt_root->d_inode == arg; | ||
554 | } | ||
555 | |||
551 | void audit_trim_trees(void) | 556 | void audit_trim_trees(void) |
552 | { | 557 | { |
553 | struct list_head cursor; | 558 | struct list_head cursor; |
@@ -559,7 +564,6 @@ void audit_trim_trees(void) | |||
559 | struct path path; | 564 | struct path path; |
560 | struct vfsmount *root_mnt; | 565 | struct vfsmount *root_mnt; |
561 | struct node *node; | 566 | struct node *node; |
562 | struct list_head list; | ||
563 | int err; | 567 | int err; |
564 | 568 | ||
565 | tree = container_of(cursor.next, struct audit_tree, list); | 569 | tree = container_of(cursor.next, struct audit_tree, list); |
@@ -577,24 +581,16 @@ void audit_trim_trees(void) | |||
577 | if (!root_mnt) | 581 | if (!root_mnt) |
578 | goto skip_it; | 582 | goto skip_it; |
579 | 583 | ||
580 | list_add_tail(&list, &root_mnt->mnt_list); | ||
581 | spin_lock(&hash_lock); | 584 | spin_lock(&hash_lock); |
582 | list_for_each_entry(node, &tree->chunks, list) { | 585 | list_for_each_entry(node, &tree->chunks, list) { |
583 | struct audit_chunk *chunk = find_chunk(node); | 586 | struct inode *inode = find_chunk(node)->watch.inode; |
584 | struct inode *inode = chunk->watch.inode; | ||
585 | struct vfsmount *mnt; | ||
586 | node->index |= 1U<<31; | 587 | node->index |= 1U<<31; |
587 | list_for_each_entry(mnt, &list, mnt_list) { | 588 | if (iterate_mounts(compare_root, inode, root_mnt)) |
588 | if (mnt->mnt_root->d_inode == inode) { | 589 | node->index &= ~(1U<<31); |
589 | node->index &= ~(1U<<31); | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | } | 590 | } |
594 | spin_unlock(&hash_lock); | 591 | spin_unlock(&hash_lock); |
595 | trim_marked(tree); | 592 | trim_marked(tree); |
596 | put_tree(tree); | 593 | put_tree(tree); |
597 | list_del_init(&list); | ||
598 | drop_collected_mounts(root_mnt); | 594 | drop_collected_mounts(root_mnt); |
599 | skip_it: | 595 | skip_it: |
600 | mutex_lock(&audit_filter_mutex); | 596 | mutex_lock(&audit_filter_mutex); |
@@ -603,22 +599,6 @@ skip_it: | |||
603 | mutex_unlock(&audit_filter_mutex); | 599 | mutex_unlock(&audit_filter_mutex); |
604 | } | 600 | } |
605 | 601 | ||
606 | static int is_under(struct vfsmount *mnt, struct dentry *dentry, | ||
607 | struct path *path) | ||
608 | { | ||
609 | if (mnt != path->mnt) { | ||
610 | for (;;) { | ||
611 | if (mnt->mnt_parent == mnt) | ||
612 | return 0; | ||
613 | if (mnt->mnt_parent == path->mnt) | ||
614 | break; | ||
615 | mnt = mnt->mnt_parent; | ||
616 | } | ||
617 | dentry = mnt->mnt_mountpoint; | ||
618 | } | ||
619 | return is_subdir(dentry, path->dentry); | ||
620 | } | ||
621 | |||
622 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) | 602 | int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) |
623 | { | 603 | { |
624 | 604 | ||
@@ -638,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree) | |||
638 | put_tree(tree); | 618 | put_tree(tree); |
639 | } | 619 | } |
640 | 620 | ||
621 | static int tag_mount(struct vfsmount *mnt, void *arg) | ||
622 | { | ||
623 | return tag_chunk(mnt->mnt_root->d_inode, arg); | ||
624 | } | ||
625 | |||
641 | /* called with audit_filter_mutex */ | 626 | /* called with audit_filter_mutex */ |
642 | int audit_add_tree_rule(struct audit_krule *rule) | 627 | int audit_add_tree_rule(struct audit_krule *rule) |
643 | { | 628 | { |
644 | struct audit_tree *seed = rule->tree, *tree; | 629 | struct audit_tree *seed = rule->tree, *tree; |
645 | struct path path; | 630 | struct path path; |
646 | struct vfsmount *mnt, *p; | 631 | struct vfsmount *mnt; |
647 | struct list_head list; | ||
648 | int err; | 632 | int err; |
649 | 633 | ||
650 | list_for_each_entry(tree, &tree_list, list) { | 634 | list_for_each_entry(tree, &tree_list, list) { |
@@ -670,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule) | |||
670 | err = -ENOMEM; | 654 | err = -ENOMEM; |
671 | goto Err; | 655 | goto Err; |
672 | } | 656 | } |
673 | list_add_tail(&list, &mnt->mnt_list); | ||
674 | 657 | ||
675 | get_tree(tree); | 658 | get_tree(tree); |
676 | list_for_each_entry(p, &list, mnt_list) { | 659 | err = iterate_mounts(tag_mount, tree, mnt); |
677 | err = tag_chunk(p->mnt_root->d_inode, tree); | ||
678 | if (err) | ||
679 | break; | ||
680 | } | ||
681 | |||
682 | list_del(&list); | ||
683 | drop_collected_mounts(mnt); | 660 | drop_collected_mounts(mnt); |
684 | 661 | ||
685 | if (!err) { | 662 | if (!err) { |
@@ -714,31 +691,23 @@ int audit_tag_tree(char *old, char *new) | |||
714 | { | 691 | { |
715 | struct list_head cursor, barrier; | 692 | struct list_head cursor, barrier; |
716 | int failed = 0; | 693 | int failed = 0; |
717 | struct path path; | 694 | struct path path1, path2; |
718 | struct vfsmount *tagged; | 695 | struct vfsmount *tagged; |
719 | struct list_head list; | ||
720 | struct vfsmount *mnt; | ||
721 | struct dentry *dentry; | ||
722 | int err; | 696 | int err; |
723 | 697 | ||
724 | err = kern_path(new, 0, &path); | 698 | err = kern_path(new, 0, &path2); |
725 | if (err) | 699 | if (err) |
726 | return err; | 700 | return err; |
727 | tagged = collect_mounts(&path); | 701 | tagged = collect_mounts(&path2); |
728 | path_put(&path); | 702 | path_put(&path2); |
729 | if (!tagged) | 703 | if (!tagged) |
730 | return -ENOMEM; | 704 | return -ENOMEM; |
731 | 705 | ||
732 | err = kern_path(old, 0, &path); | 706 | err = kern_path(old, 0, &path1); |
733 | if (err) { | 707 | if (err) { |
734 | drop_collected_mounts(tagged); | 708 | drop_collected_mounts(tagged); |
735 | return err; | 709 | return err; |
736 | } | 710 | } |
737 | mnt = mntget(path.mnt); | ||
738 | dentry = dget(path.dentry); | ||
739 | path_put(&path); | ||
740 | |||
741 | list_add_tail(&list, &tagged->mnt_list); | ||
742 | 711 | ||
743 | mutex_lock(&audit_filter_mutex); | 712 | mutex_lock(&audit_filter_mutex); |
744 | list_add(&barrier, &tree_list); | 713 | list_add(&barrier, &tree_list); |
@@ -746,7 +715,7 @@ int audit_tag_tree(char *old, char *new) | |||
746 | 715 | ||
747 | while (cursor.next != &tree_list) { | 716 | while (cursor.next != &tree_list) { |
748 | struct audit_tree *tree; | 717 | struct audit_tree *tree; |
749 | struct vfsmount *p; | 718 | int good_one = 0; |
750 | 719 | ||
751 | tree = container_of(cursor.next, struct audit_tree, list); | 720 | tree = container_of(cursor.next, struct audit_tree, list); |
752 | get_tree(tree); | 721 | get_tree(tree); |
@@ -754,30 +723,19 @@ int audit_tag_tree(char *old, char *new) | |||
754 | list_add(&cursor, &tree->list); | 723 | list_add(&cursor, &tree->list); |
755 | mutex_unlock(&audit_filter_mutex); | 724 | mutex_unlock(&audit_filter_mutex); |
756 | 725 | ||
757 | err = kern_path(tree->pathname, 0, &path); | 726 | err = kern_path(tree->pathname, 0, &path2); |
758 | if (err) { | 727 | if (!err) { |
759 | put_tree(tree); | 728 | good_one = path_is_under(&path1, &path2); |
760 | mutex_lock(&audit_filter_mutex); | 729 | path_put(&path2); |
761 | continue; | ||
762 | } | 730 | } |
763 | 731 | ||
764 | spin_lock(&vfsmount_lock); | 732 | if (!good_one) { |
765 | if (!is_under(mnt, dentry, &path)) { | ||
766 | spin_unlock(&vfsmount_lock); | ||
767 | path_put(&path); | ||
768 | put_tree(tree); | 733 | put_tree(tree); |
769 | mutex_lock(&audit_filter_mutex); | 734 | mutex_lock(&audit_filter_mutex); |
770 | continue; | 735 | continue; |
771 | } | 736 | } |
772 | spin_unlock(&vfsmount_lock); | ||
773 | path_put(&path); | ||
774 | |||
775 | list_for_each_entry(p, &list, mnt_list) { | ||
776 | failed = tag_chunk(p->mnt_root->d_inode, tree); | ||
777 | if (failed) | ||
778 | break; | ||
779 | } | ||
780 | 737 | ||
738 | failed = iterate_mounts(tag_mount, tree, tagged); | ||
781 | if (failed) { | 739 | if (failed) { |
782 | put_tree(tree); | 740 | put_tree(tree); |
783 | mutex_lock(&audit_filter_mutex); | 741 | mutex_lock(&audit_filter_mutex); |
@@ -818,10 +776,8 @@ int audit_tag_tree(char *old, char *new) | |||
818 | } | 776 | } |
819 | list_del(&barrier); | 777 | list_del(&barrier); |
820 | list_del(&cursor); | 778 | list_del(&cursor); |
821 | list_del(&list); | ||
822 | mutex_unlock(&audit_filter_mutex); | 779 | mutex_unlock(&audit_filter_mutex); |
823 | dput(dentry); | 780 | path_put(&path1); |
824 | mntput(mnt); | ||
825 | drop_collected_mounts(tagged); | 781 | drop_collected_mounts(tagged); |
826 | return failed; | 782 | return failed; |
827 | } | 783 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fc0f928167e7..f3a461c0970a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1988,7 +1988,6 @@ void __audit_inode(const char *name, const struct dentry *dentry) | |||
1988 | 1988 | ||
1989 | /** | 1989 | /** |
1990 | * audit_inode_child - collect inode info for created/removed objects | 1990 | * audit_inode_child - collect inode info for created/removed objects |
1991 | * @dname: inode's dentry name | ||
1992 | * @dentry: dentry being audited | 1991 | * @dentry: dentry being audited |
1993 | * @parent: inode of dentry parent | 1992 | * @parent: inode of dentry parent |
1994 | * | 1993 | * |
@@ -2000,13 +1999,14 @@ void __audit_inode(const char *name, const struct dentry *dentry) | |||
2000 | * must be hooked prior, in order to capture the target inode during | 1999 | * must be hooked prior, in order to capture the target inode during |
2001 | * unsuccessful attempts. | 2000 | * unsuccessful attempts. |
2002 | */ | 2001 | */ |
2003 | void __audit_inode_child(const char *dname, const struct dentry *dentry, | 2002 | void __audit_inode_child(const struct dentry *dentry, |
2004 | const struct inode *parent) | 2003 | const struct inode *parent) |
2005 | { | 2004 | { |
2006 | int idx; | 2005 | int idx; |
2007 | struct audit_context *context = current->audit_context; | 2006 | struct audit_context *context = current->audit_context; |
2008 | const char *found_parent = NULL, *found_child = NULL; | 2007 | const char *found_parent = NULL, *found_child = NULL; |
2009 | const struct inode *inode = dentry->d_inode; | 2008 | const struct inode *inode = dentry->d_inode; |
2009 | const char *dname = dentry->d_name.name; | ||
2010 | int dirlen = 0; | 2010 | int dirlen = 0; |
2011 | 2011 | ||
2012 | if (!context->in_syscall) | 2012 | if (!context->in_syscall) |
@@ -2014,9 +2014,6 @@ void __audit_inode_child(const char *dname, const struct dentry *dentry, | |||
2014 | 2014 | ||
2015 | if (inode) | 2015 | if (inode) |
2016 | handle_one(inode); | 2016 | handle_one(inode); |
2017 | /* determine matching parent */ | ||
2018 | if (!dname) | ||
2019 | goto add_names; | ||
2020 | 2017 | ||
2021 | /* parent is more likely, look for it first */ | 2018 | /* parent is more likely, look for it first */ |
2022 | for (idx = 0; idx < context->name_count; idx++) { | 2019 | for (idx = 0; idx < context->name_count; idx++) { |
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index 8f5d16e0707a..8cd50d8f9bde 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c | |||
@@ -1331,7 +1331,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1331 | ssize_t result; | 1331 | ssize_t result; |
1332 | char *pathname; | 1332 | char *pathname; |
1333 | int flags; | 1333 | int flags; |
1334 | int acc_mode, fmode; | 1334 | int acc_mode; |
1335 | 1335 | ||
1336 | pathname = sysctl_getname(name, nlen, &table); | 1336 | pathname = sysctl_getname(name, nlen, &table); |
1337 | result = PTR_ERR(pathname); | 1337 | result = PTR_ERR(pathname); |
@@ -1342,15 +1342,12 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1342 | if (oldval && oldlen && newval && newlen) { | 1342 | if (oldval && oldlen && newval && newlen) { |
1343 | flags = O_RDWR; | 1343 | flags = O_RDWR; |
1344 | acc_mode = MAY_READ | MAY_WRITE; | 1344 | acc_mode = MAY_READ | MAY_WRITE; |
1345 | fmode = FMODE_READ | FMODE_WRITE; | ||
1346 | } else if (newval && newlen) { | 1345 | } else if (newval && newlen) { |
1347 | flags = O_WRONLY; | 1346 | flags = O_WRONLY; |
1348 | acc_mode = MAY_WRITE; | 1347 | acc_mode = MAY_WRITE; |
1349 | fmode = FMODE_WRITE; | ||
1350 | } else if (oldval && oldlen) { | 1348 | } else if (oldval && oldlen) { |
1351 | flags = O_RDONLY; | 1349 | flags = O_RDONLY; |
1352 | acc_mode = MAY_READ; | 1350 | acc_mode = MAY_READ; |
1353 | fmode = FMODE_READ; | ||
1354 | } else { | 1351 | } else { |
1355 | result = 0; | 1352 | result = 0; |
1356 | goto out_putname; | 1353 | goto out_putname; |
@@ -1361,7 +1358,7 @@ static ssize_t binary_sysctl(const int *name, int nlen, | |||
1361 | if (result) | 1358 | if (result) |
1362 | goto out_putname; | 1359 | goto out_putname; |
1363 | 1360 | ||
1364 | result = may_open(&nd.path, acc_mode, fmode); | 1361 | result = may_open(&nd.path, acc_mode, flags); |
1365 | if (result) | 1362 | if (result) |
1366 | goto out_putpath; | 1363 | goto out_putpath; |
1367 | 1364 | ||