On Wed, Jan 12, 2022 at 4:06 PM Richard Guy Briggs <[email protected]> wrote:
> On 2021-12-29 17:51, Paul Moore wrote:
> > On Thu, Nov 4, 2021 at 5:00 PM Richard Guy Briggs <[email protected]> wrote:
> > > AUDIT_TIME_* events are generated when there are syscall rules present 
> > > that are
> > > not related to time keeping.  This will produce noisy log entries that 
> > > could
> > > flood the logs and hide events we really care about.
> > >
> > > Rather than immediately produce the AUDIT_TIME_* records, store the data 
> > > and
> > > log it at syscall exit time respecting the filter rules.
> > >
> > > Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> > >
> > > Signed-off-by: Richard Guy Briggs <[email protected]>
> > > ---
> > > Note: This is a quick and dirty proof-of-concept.  If this approach of
> > > storing the values in the audit_context for later filtering is
> > > acceptable I'll clean up the patch (re-name functions) and re-submit.
> > >
> > >  kernel/audit.h   |  6 ++++++
> > >  kernel/auditsc.c | 29 +++++++++++++++++++++++++----
> > >  2 files changed, 31 insertions(+), 4 deletions(-)
> >
> > Reviewing this now with a more critical eye since it is longer just a
> > quick-n-dirty proof of concept ...
> >
> > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > index 3b64a97f6091..25d63731b0e0 100644
> > > --- a/kernel/audit.h
> > > +++ b/kernel/audit.h
> > > @@ -196,6 +196,12 @@ struct audit_context {
> > >                 struct {
> > >                         char                    *name;
> > >                 } module;
> > > +               struct {
> > > +                       struct audit_ntp_data   data;
> > > +               } ntp;
> > > +               struct {
> > > +                       struct timespec64       injoffset;
> > > +               } tk;
> >
> > With the ntp and tk structs being separate parts of a union, are we
> > going to have a problem when ADJ_SETOFFSET is set in a call to
> > do_adjtimex()?
>
> Yes, so since both record types can exist in one event, either both
> pieces of data will need to be in one struct within the union, or
> one piece of data will need to go outside of the union (preferably the
> smaller one to avoid bloating struct audit_context more than necessary).
> The tk data is smaller and is easier to check if it is set, so that
> might be better to store outside the union.
>
> Since show_special is keyed off record type, it makes more sense to
> store one of those datum outside the union and process it outside
> show_special to avoid record type tricks in show_special.

It seems so much easier just to put both "data" and "injoffset" inside
a single struct within the union, and considering the size of
mq_getsetattr in that same union I doubt the size will increase
significantly (or at all, if my quick estimation stands up).

I believe our best approach is to stay consistent with how we handle
other things similar to this, I don't currently see any reason why the
NTP adjustments would require special handling.

As an aside, how did you test this and not run into this issue?

> > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > index 6efb0bb909d0..8983790ad86a 100644
> > > --- a/kernel/auditsc.c
> > > +++ b/kernel/auditsc.c
> > > @@ -1210,11 +1210,18 @@ static void audit_log_fcaps(struct audit_buffer 
> > > *ab, struct audit_names *name)
> > >                          from_kuid(&init_user_ns, name->fcap.rootid));
> > >  }
> > >
> > > +void __audit_ntp_log_(const struct audit_ntp_data *ad);
> > > +
> > >  static void show_special(struct audit_context *context, int *call_panic)
> > >  {
> > >         struct audit_buffer *ab;
> > >         int i;
> > >
> > > +       if (context->type == AUDIT_TIME_ADJNTPVAL) {
> > > +               __audit_ntp_log_(&context->ntp.data);
> > > +               return;
> > > +       }
> >
> > Can we find a way to move this down into the main switch statement in
> > show_special() like you did with AUDIT_TIME_INJOFFSET?  This looks
> > *really* hacky to me.  Why should AUDIT_TIME_ADJNTPVAL be different
> > from the other "special" bits?
>
> Agreed, it *looked* hacky to me too.  As previously noted, this was the
> most expedient way to do this due to the unknown number of records being
> generated, minimum of zero (max 6).  show_special allocates an
> audit_buffer before processing the specific record type, assuming it
> exists.  In the case of audit_ntp_data, it may all be equal and not need
> to be logged.
>
> Ideally, the old vs new data should be compared at the time of the call
> from do_adjtimex() to find out if we even need to store that data
> when all old and new values are equal.
>
> So, a bit more pre-processing during the call to avoid storing the
> information if it isn't needed will avoid it at syscall exit.  Are you
> ok with that?

The currently proposed approach is ugly enough that I think it is
worth looking at alternatives, let's see what you can come up with in
the next version and make a decision then.

> > > @@ -2588,7 +2609,7 @@ static void audit_log_ntp_val(const struct 
> > > audit_ntp_data *ad,
> > >                   "op=%s old=%lli new=%lli", op, val->oldval, 
> > > val->newval);
> > >  }
> > >
> > > -void __audit_ntp_log(const struct audit_ntp_data *ad)
> > > +void __audit_ntp_log_(const struct audit_ntp_data *ad)
> > >  {
> > >         audit_log_ntp_val(ad, "offset", AUDIT_NTP_OFFSET);
> > >         audit_log_ntp_val(ad, "freq",   AUDIT_NTP_FREQ);
> >
> > Ooof, *please* don't end a function, or any symbol for that matter,
> > with an underscore.
>
> Ok, renamed to be consistent with others called from show_special().

Thanks.

-- 
paul moore
paul-moore.com

--
Linux-audit mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/linux-audit

Reply via email to