Hello Steve,
> I tried to change our rules to "exit,always" from
"entry,always", but it
> didn't make a difference. Can you confirm that only one exit is traced
> and do you think audit can be enhanced to trace these extra exits of
> syscalls like FORK.
Yes, I think the kernel could be updated to return twice. This would need
to be sent upstream and I think 2.6.28 is the next chance.
The missing FORK return is incidentally the one we care about. We have no
concern if a process forks or not, we only want to know and see the new
process. It doesn't matter if the parent ever got to notice it.
Is there any hope such a patch could be part of RHEL 5.3, given that Redhat
has its own kernel release process? I am not that much into security, but I
could imagine that it's possible to carefully craft a process that escapes
the audit trail with SIGKILL to a forker.
All you got to do is to fork a process that will fork another and with
increasingly bigger times, you SIGKILL the process until its child will
secretely survive.
> > ausyscall x86_64 clone
> > 56
> >
> > ausyscall i386 clone
> > 120
>
> Very good. We have initially defined a hash in Python manually with what
> we encounter, but we can rather use that to create them. We specifically
> have the problem of visiting a s390 site, where it will handy to have
> these already in place. There is no such function in libaudit, is there?
For what?
Well for the functionality of ausyscall. If we could query the current arch,
well it's b32/b64 arches, then we could build that table at run time,
couldn't we?
That would be a whole lot nicer than hardcoded values, even if they are
generated using ausyscall.
> > We have an audit parsing library. It takes this into
account.
>
> I have looked at it, and auparse_init doesn't seem to support reading
> from the socket itself, does it?
You mean the netlink socket?
No, when opening the socket the to the sub deamon audisp. I couldn't convice
myself how the API would work with a socket. Does it?
> In an ideal world, we would like to note that the audit socket
is
> readable, hand it (or an arbitrarily truncated chunk of data) from it to
> libaudit, ask it for events until it says there are not more. That would
> leave the truncated line/event issue to libaudit. Is that part of the
> code?
libaudit should pull complete events from the kernel unless an execve has
an excessive number of arguments or large sized arguments.
I read that as that we can use the netlink socket with the libaudit directly,
which sort of could be exactly what we want. That would mean we wouldn't use
audit user space (processes) at all, right?
> Note that we get a SYSCALL with 2 items, and then in order the
items -
> from the socket. But inbetween we get type=EXECVE it doesn't have an item
> number,
I suppose that could be fixed.
> and worse the new line before 'a1=--color-auto' is real and so is
> the empty line after it. I have another example of a "gnash" call from
> Konqueror with no less than 29 arguments.
That is coming from here, and I think a patch was submitted fixing it.
http://lxr.linux.no/linux+v2.6.26.2/kernel/auditsc.c#L1114
I see. Strange to see line formatting like that in the kernel in the first
place. But libaudit doesn't care about them anyway I suppose.
> > > I have no idea how much it represents and existing
external
> > > interface, but I can imagine you can't change it (easily). Probably
> > > the end of type= must be detected by terminating empty line in case
> > > of those that can be continued. But it would be very ugly to have to
> > > know the event types that have this so early in the decoding process.
> >
> > We have a parsing library, auparse, that handles the rules of audit
> > parsing. Look for auparse.h for the API.
>
> If you confirm that can handles the parsing from the socket, as suggested
> above, we may persue that path and can ignore strangeness of the format
> once its handled by the library.
The audit parsing library wants to read text strings as you would find them
on disk. The kernel keeps type separate as an integer so that decisions can
be made about what the record means without having to do a text to int
conversion. So, the audit daemon does the reformatting after it decides
that it a record type that we are interested in.
And I read that as the libaudit library being unable to use the netlink socket
directly.
[ Options for listening]
You have 4 points to get the audit stream, in order of distance from
the
event generation: the audit netlink socket, auditd realtime interface,
audisp plugin interface, and the af_unix socket created by the af_unix
plugin from audispd. For higher reliability where you don't want of need
any other audit processing interfering, I would say use either of the first
2.
The latency is getting higher with each step. For optimal performance we would
listen to the netlink socket and duplicate only the code essential to process
what we are interested it.
For extra points and hurt, we would do it in Ada and inside the target
process, really achieving the low latency. It may be the only realistic
option, but it also feels like duplication of effort. We have done netlink
interfaces in Ada before, but also have on our mind that it was said that the
netlink interface was said (not by you) to be still in flux. Is that still
true?
It certainly would be nice if the audisp had some form of output that can be
fed directly into libaudit parsing as it comes in. But that may be an
unrealistic expectation, is it?
> > > or for the whole job, that means our supervision
process?
> >
> > The supervision process. Then again, maybe you want to replace the
> > audit daemon and handle events your own way. libaudit has all the
> > primitives for that. So, I guess that brings up the question of how you
> > are accessing the audit event stream. Are you reading straight from
> > netlink or the disk?
>
> From the files is out of question. We thought of the audit sub deamon as
> something that simply allows to access the audit stream live, but that it
> is otherwise the same as the file.
The data can be either binary or string. Binary means that its exactly the
same format that comes from thekernel unchanged. String means that its been
formatted just like you would see on disk. But it appears that its not
stripping the 0X0A out of the text. It probably should.
Well, as it is, the parsing must be done in lines, and you must be stateful to
know how many of them to expect, because of two bugs only:
a) "Random" newlines for some type=xxx values.
b) No item= for type=EXECVE and similar.
If it were not for that, the parsing of socket output would be much easier. I
understand both issues will be addressed in future releases, which is a good
outcome.
> Like auditd would accept things from the kernel, write it to a
file and
> hand it to audisp as well which would then provide it to others. Isn't
> that the design?
Yes.
The difference between disk and audisp socket was also confusing to us. Some
corrections (removal of newlines) were applied to only one part.
Overall I would like to thank you for clarifying the supposed workings,
addressing found bugs, and advising us very well.
If we choose to use the netlink socket for audit messages, we are of course
interested about the kernel changes. The missing fork exits more so than the
EXECVE extra newlines which should be easy enough to compensate.
Best regards,
Kay Hayen