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: [email protected]
Signed-off-by: Andy Lutomirski <[email protected]>
Signed-off-by: Eric Paris <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
amluto authored and torvalds committed Jun 10, 2014
1 parent 64b2d1f commit a3c5493
Showing 1 changed file with 18 additions and 9 deletions.
27 changes: 18 additions & 9 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,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 @@ -745,11 +761,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, false)) {
rcu_read_unlock();
Expand All @@ -769,20 +782,16 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
static int audit_filter_inode_name(struct task_struct *tsk,
struct audit_names *n,
struct audit_context *ctx) {
int word, bit;
int h = audit_hash_ino((u32)n->ino);
struct list_head *list = &audit_inode_hash[h];
struct audit_entry *e;
enum audit_state state;

word = AUDIT_WORD(ctx->major);
bit = AUDIT_BIT(ctx->major);

if (list_empty(list))
return 0;

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, false)) {
ctx->current_state = state;
return 1;
Expand Down

0 comments on commit a3c5493

Please sign in to comment.