Hello,
I know this one is a long time coming. My last patch was critically
flawed in that the preallocation mechanism did not take into
consideration multiple references to an inode holding audit info.
This caused a complete melt down of the code. My first solution was a
miserable failure. This one works much better. I went through 40
different tests just to make sure things are behaving [more]
correctly. Two major scenarios that need to be thought over and most
likely need a fixing are the following:
1.
watch /etc/foo,filterkey=foo
watch /etc/bar,filterkey=bar
touch /etc/foo
ln /etc/foo /etc/bar
As of right now, /etc/bar will lose /etc/foo's watch information and
gain /etc/bar's. This is the natural behavior for all other scenarios
(ie: mv /etc/foo /etc/bar). I do not believe this should be allowed
for hardlinks. The filterkey=bar may be a weaker filtering key then
filterkey=foo and thus in any userspace filtering (we might decide to
do) could be subverted. Hardlinks should retain, always, the filter
information of what they're linking against, regardless of where they
are at. This also brings into consideration the need for multiple
watches on a single path? This way we get information for /etc/bar
for both /etc/foo AND /etc/bar.
2.
watch /etc/foo
touch /etc/foo
ln /etc/foo /tmp/foo
(remains audited)
mv /tmp/foo /tmp/bar
(loses audit)
This is also a natural side effect of the code. When we move we
always lose any watch information we are holding onto. If we move
into a location that's being watched we gain that watch information.
Since /tmp/bar was not being watched, the hardlink loses its watch to
/etc/foo. Is this acceptable? I don't think so. From my above
statement, the hardlink must always retain it's watch information to
what it is linked against.. We wouldn't want a user to be able to
create a hardlink and then move it to lose the watch.
But, we must also keep in mind that eventually it gets unreasonable.
For instance:
watch /etc/foo
ln /etc/foo /etc/bar
unwatch /etc/foo
rm /etc/foo
touch /etc/foo
watch /etc/foo
/etc/bar is no longer audited. There's no reasonable way around this.
The data structure for this has become much more complex as I've
incorporated the preallocation mechanism into the audit_watch
structure itself with the assertion, "One chunk of audit_data memory
per watch" -- This effectively introduces a circular data structure
(the audit_data within the audit_wentry (at one time called
audit_watch) is pointing at the audit_wentry itself. It'd take a long
time to explain why, but I intend on releasing to this list, diagrams
describing the data structure visually. I'll take a picture of my
white board and post it for the time being. You might get a good
laugh, I do. :)
Please review and provide comments.
PS: I did not use static inlines as Stephen suggested yet to keep the
code consistent with what is already there. So keep me in check. I
know I'm notorious for providing the wrong number of arguments to my
macros! :(
Patch #4:
This patch will address the above issues in some way. It will finally
take care of dynamic enable/disable of file system auditing from
userspace. It will add permission masks filtering. Fix bugs found in
Patch #3. Begin official Docbook comments. Figure out a good place
to hook so we can cover unlinks and similar syscalls that skip over
permission(). And anything else I'm presently forgetting :-)
Hopefully by then I'll have some userspace code for the public.
I originally wanted to remove some of Rik's code that hooked
path_lookup(), but I actually kind of like it. Even though the inode
he reports is wrong in some cases (ie: unlink()), the path information
is useful. Especially when looking at hardlinks that are being
watched. Might just take out the inode record. How does everyone
feel about this?
--
- Timothy R. Chavez
Show replies by date