aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-05-28 23:09:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-10 11:44:40 -0400
commita3c54931199565930d6d84f4c3456f6440aefd41 (patch)
tree7c2360628766e160a56672eb20c57e69a9881a2d
parent64b2d1fbbfda07765dae3f601862796a61b2c451 (diff)
auditsc: audit_krule mask accesses need bounds checking
Fixes an easy DoS and possible information disclosure. This does nothing about the broken state of x32 auditing. eparis: If the admin has enabled auditd and has specifically loaded audit rules. This bug has been around since before git. Wow... Cc: stable@vger.kernel.org Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/auditsc.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index f251a5e8d17a..21eae3c05ec0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -728,6 +728,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
728 return AUDIT_BUILD_CONTEXT; 728 return AUDIT_BUILD_CONTEXT;
729} 729}
730 730
731static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
732{
733 int word, bit;
734
735 if (val > 0xffffffff)
736 return false;
737
738 word = AUDIT_WORD(val);
739 if (word >= AUDIT_BITMASK_SIZE)
740 return false;
741
742 bit = AUDIT_BIT(val);
743
744 return rule->mask[word] & bit;
745}
746
731/* At syscall entry and exit time, this filter is called if the 747/* At syscall entry and exit time, this filter is called if the
732 * audit_state is not low enough that auditing cannot take place, but is 748 * audit_state is not low enough that auditing cannot take place, but is
733 * also not high enough that we already know we have to write an audit 749 * also not high enough that we already know we have to write an audit
@@ -745,11 +761,8 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
745 761
746 rcu_read_lock(); 762 rcu_read_lock();
747 if (!list_empty(list)) { 763 if (!list_empty(list)) {
748 int word = AUDIT_WORD(ctx->major);
749 int bit = AUDIT_BIT(ctx->major);
750
751 list_for_each_entry_rcu(e, list, list) { 764 list_for_each_entry_rcu(e, list, list) {
752 if ((e->rule.mask[word] & bit) == bit && 765 if (audit_in_mask(&e->rule, ctx->major) &&
753 audit_filter_rules(tsk, &e->rule, ctx, NULL, 766 audit_filter_rules(tsk, &e->rule, ctx, NULL,
754 &state, false)) { 767 &state, false)) {
755 rcu_read_unlock(); 768 rcu_read_unlock();
@@ -769,20 +782,16 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
769static int audit_filter_inode_name(struct task_struct *tsk, 782static int audit_filter_inode_name(struct task_struct *tsk,
770 struct audit_names *n, 783 struct audit_names *n,
771 struct audit_context *ctx) { 784 struct audit_context *ctx) {
772 int word, bit;
773 int h = audit_hash_ino((u32)n->ino); 785 int h = audit_hash_ino((u32)n->ino);
774 struct list_head *list = &audit_inode_hash[h]; 786 struct list_head *list = &audit_inode_hash[h];
775 struct audit_entry *e; 787 struct audit_entry *e;
776 enum audit_state state; 788 enum audit_state state;
777 789
778 word = AUDIT_WORD(ctx->major);
779 bit = AUDIT_BIT(ctx->major);
780
781 if (list_empty(list)) 790 if (list_empty(list))
782 return 0; 791 return 0;
783 792
784 list_for_each_entry_rcu(e, list, list) { 793 list_for_each_entry_rcu(e, list, list) {
785 if ((e->rule.mask[word] & bit) == bit && 794 if (audit_in_mask(&e->rule, ctx->major) &&
786 audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) { 795 audit_filter_rules(tsk, &e->rule, ctx, n, &state, false)) {
787 ctx->current_state = state; 796 ctx->current_state = state;
788 return 1; 797 return 1;