RBACPP FAU_SEL.1 Selective Audit
The TSF shall be able to include or exclude auditable events from the
set of audited events based on the following attributes:
(a) Object identity, user identity, subject identity, host identity, and
***event type***
I'm currently working on a design for a patch to the audit userspace and
kernel subsystem that provides this functionality. Additionally, I'm
conducting this work in conjunction with trying to provide extended
support for operators (such as > and <), as these would be useful in
this context.
To give credit where due, Steve Grubb and I have discussed a some of
these items in off hand conversations recently. I'm collecting those
thoughts and others here for review.
--
USER_SPACE
From a user-experience perspective, we're trying to enable a user to
exclude messages of a certain type (or ranges of messages of particular
types). If you're unclear what types of messages are currently defined,
see include/linux/audit.h. Given extended support for ranges and
comparative operators, this should be extensible to other audit record
keys, such the user, subject, etc.
I'm suggesting the ability to add new rules via auditctl to a new list,
perhaps called "exclude". The proposed interface would look like:
Exclude messages of a specific type:
auditctl -a exclude,always -F "type=AUDIT_IPC"
Exclude messages within range:
auditctl -a exclude,always -F "type=AUDIT_SYSCALL..AUDIT_CWD"
Exclude messages using auditctl helper terms (ALL_DAEMON interpreted by
auditctl to be a range of 1200-1299 as specified in the audit.h header):
auditctl -a exclude,always -F "type=ALL_DAEMON"
Use multiple rules to exclude audit system command messages:
auditctl -a exclude,always -F "type<1100"
Also, the same form should be usable for other parameters as well, such
as uid, pid, etc.
auditctl -a exclude,always -F "uid<500"
auditctl -a exclude,always -F "pid=464"
I have written the code necessary to create an ordered, compressed list
of ranges of numbers that the kernel could very efficiently filter on.
Given some arbitrary number of ranges (as small as a singularity and as
large as the enumerated space), the code creates a list of upper and
lower bounds, however few are necessary to properly express the list of
ranges. For instance, given the user input ranges:
10-20, 5, 15-25, 23, 50
The algorithm will produce an optimized list:
5,5
10,25
50,50
This is a key, inexpensive operation to perform in user space that is
potentially a valuable gain kernel space. Memory requirements are
minimized, matches are found quickly, and the traversal is aborted as
soon as a range greater than the current value is encountered.
Note that I've also written the code necessary to remove individual
elements or ranges from an existing range, such that given our previous
range: (5, 10-25, 50), one chooses to remove 7, 13, 40-60 would result
in: (5, 10-12, 14-25). This is needed for the user's ability to prune
and modify existing rules.
--
KERNEL_SPACE
The kernel piece of this is pretty straightforward, actually... Near
the very top of audit_log_start(), we basically do something like:
if (unlikely(audit_exclude_type(type)))
return NULL;
Where audit_exclude_type() traverses our list of ranges looking for a
match, returning 1 if is to be excluded, 0 if no matches found.
Remember, this is ordered such that we can end the traversal as soon as
possible.
--
NETLINK
I'm nearly ready to post a patch, but I'm waiting on some consensus on
Steve's previous thread (New operators for rules). As of this posting,
there's no consensus yet on how we go about passing these values to/from
the kernel/userspace.
I'm trying to work within struct audit_rule.
struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
uint32_t flags; /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
uint32_t action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
uint32_t field_count;
uint32_t mask[AUDIT_BITMASK_SIZE];
uint32_t fields[AUDIT_MAX_FIELDS];
uint32_t values[AUDIT_MAX_FIELDS];
};
There have been several propositions so far (utilize upper bits of
flags; utilize matching fields[]/values[] entries; hack in a zero-sized
array). If you have opinions on the conveyance of said operators,
please post to aforementioned thread.
Other comments on the design here proposed?
:-Dustin