Skip to content

Commit

Permalink
auditsc: audit_krule mask accesses need bounds checking
Browse files Browse the repository at this point in the history
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>
(cherry picked from commit a3c5493)
[wt: no audit_filter_inode_name(), applied to audit_filter_inodes() instead]
Signed-off-by: Willy Tarreau <w@1wt.eu>
  • Loading branch information
Andy Lutomirski authored and Willy Tarreau committed Jun 18, 2014
1 parent 07bc7fb commit a986d9c
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,22 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
return AUDIT_BUILD_CONTEXT;
}

static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
{
int word, bit;

if (val > 0xffffffff)
return false;

word = AUDIT_WORD(val);
if (word >= AUDIT_BITMASK_SIZE)
return false;

bit = AUDIT_BIT(val);

return rule->mask[word] & bit;
}

/* At syscall entry and exit time, this filter is called if the
* audit_state is not low enough that auditing cannot take place, but is
* also not high enough that we already know we have to write an audit
Expand All @@ -697,11 +713,8 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,

rcu_read_lock();
if (!list_empty(list)) {
int word = AUDIT_WORD(ctx->major);
int bit = AUDIT_BIT(ctx->major);

list_for_each_entry_rcu(e, list, list) {
if ((e->rule.mask[word] & bit) == bit &&
if (audit_in_mask(&e->rule, ctx->major) &&
audit_filter_rules(tsk, &e->rule, ctx, NULL,
&state)) {
rcu_read_unlock();
Expand Down Expand Up @@ -730,8 +743,6 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)

rcu_read_lock();
for (i = 0; i < ctx->name_count; i++) {
int word = AUDIT_WORD(ctx->major);
int bit = AUDIT_BIT(ctx->major);
struct audit_names *n = &ctx->names[i];
int h = audit_hash_ino((u32)n->ino);
struct list_head *list = &audit_inode_hash[h];
Expand All @@ -740,7 +751,7 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
continue;

list_for_each_entry_rcu(e, list, list) {
if ((e->rule.mask[word] & bit) == bit &&
if (audit_in_mask(&e->rule, ctx->major) &&
audit_filter_rules(tsk, &e->rule, ctx, n, &state)) {
rcu_read_unlock();
ctx->current_state = state;
Expand Down

0 comments on commit a986d9c

Please sign in to comment.