[PATCH] Fix audit operators

Darrel Goeddel initiated a discussion on IRC regarding the possibility
of audit_comparator() returning -EINVAL signaling an invalid operator.

It is possible when creating the rule to assure that the operator is one
of the 6 sane values.  Here's a snip from include/linux/audit.h  Note
that 0 (nonsense) and 7 (all operators) are not valid values for an
operator.

...

/* These are the supported operators.
 *      4  2  1
 *      =  >  <
 *      -------
 *      0  0  0         0       nonsense
 *      0  0  1         1       <
 *      0  1  0         2       >
 *      0  1  1         3       !=
 *      1  0  0         4       =
 *      1  0  1         5       <=
 *      1  1  0         6       >=
 *      1  1  1         7       all operators
 */
...

Furthermore, prior to adding these extended operators, flagging the
AUDIT_NEGATE bit implied !=, and otherwise == was assumed.

The following code forces the operator to be != if the AUDIT_NEGATE bit
was flipped on.  And if no operator was specified, == is assumed.  The
only invalid condition is if the AUDIT_NEGATE bit is off and all of the
AUDIT_EQUAL, AUDIT_LESS_THAN, and AUDIT_GREATER_THAN bits are
on--clearly a nonsensical operator.

Now that this is handled at rule insertion time, the default -EINVAL
return of audit_comparator() is eliminated such that the function can
only return 1 or 0.

If this is acceptable, let's get this applied to the current tree.

:-Dustin

--

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
(cherry picked from 9bf0a8e137040f87d1b563336d4194e38fb2ba1a commit)
This commit is contained in:
Dustin Kirkland 2006-02-16 13:40:01 -06:00 committed by Al Viro
parent 5bdb988680
commit d9d9ec6e2c

View file

@ -160,11 +160,17 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
f->val = rule->values[i]; f->val = rule->values[i];
entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1; entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
/* Support for legacy operators where
* AUDIT_NEGATE bit signifies != and otherwise assumes == */
if (f->op & AUDIT_NEGATE) if (f->op & AUDIT_NEGATE)
f->op |= AUDIT_NOT_EQUAL; f->op = AUDIT_NOT_EQUAL;
else if (!(f->op & AUDIT_OPERATORS)) else if (!f->op)
f->op |= AUDIT_EQUAL; f->op = AUDIT_EQUAL;
f->op &= ~AUDIT_NEGATE; else if (f->op == AUDIT_OPERATORS) {
err = -EINVAL;
goto exit_free;
}
} }
exit_nofree: exit_nofree:
@ -533,9 +539,9 @@ int audit_comparator(const u32 left, const u32 op, const u32 right)
return (left > right); return (left > right);
case AUDIT_GREATER_THAN_OR_EQUAL: case AUDIT_GREATER_THAN_OR_EQUAL:
return (left >= right); return (left >= right);
default:
return -EINVAL;
} }
BUG();
return 0;
} }