Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-02-11 Thread Paul Moore
On Fri, Feb 11, 2022 at 9:15 AM Richard Guy Briggs  wrote:
>
> On 2022-02-10 21:08, Paul Moore wrote:
> > On Thu, Feb 10, 2022 at 6:46 PM Richard Guy Briggs  wrote:
> > > On 2022-01-31 20:29, Paul Moore wrote:
> > > > On Mon, Jan 31, 2022 at 6:29 PM Richard Guy Briggs  
> > > > wrote:
> > > > > On 2022-01-31 17:02, Paul Moore wrote:
> > > > > > On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs 
> > > > > >  wrote:
> > > > > > > On 2022-01-25 22:24, Richard Guy Briggs wrote:
> >
> > This isn't as complete of a response as I would like, but I wanted to
> > get *something* back to you same-day since the delays are getting a
> > bit long ...
> >
> > > > > > [WARNING: not compiled, tested, yadda yadda]
> > > > > >
> > > > > > void audit_log_time(struct audit_context ctx, struct audit_buffer 
> > > > > > **abp)
> > > > > > {
> > > > > >   int i;
> > > > > >   int type = ctx->type;
> > > > > >   struct audit_buffer *ab = *abp;
> > > > > >   struct audit_ntp_val *ntp;
> > > > > >   const struct timespec64 *tk;
> > > > > >   const char *ntp_name[] = {
> > > > > > "offset",
> > > > > > "freq",
> > > > > > "status",
> > > > > > "tai",
> > > > > > "tick",
> > > > > > "adjust",
> > > > > >   };
> > > > > >
> > > > > >   do {
> > > > > > if (type == AUDIT_TIME_ADJNTPVAL) {
> > > > > >   ntp = ctx->time.ntp_data.val;
> > > > > >   for (i = 0; i < AUDIT_NTP_NVALS; i++) {
> > > > > > if (ntp[i].newval != ntp[i].oldval) {
> > > > > >   audit_log_format(ab,
> > > > > > "op=%s old=%lli new=%lli",
> > > > > > ntp_name[type],
> > > > > > ntp[i].oldval, ntp[i].newval);
> > > > > > }
> > > > > >   }
> > > > > > } else {
> > > > > >   tk = >time.tk_injoffset;
> > > > > >   audit_log_format(ab, "sec=%lli nsec=%li",
> > > > > > (long long)tk->tv_sec, tk->tv_nsec);
> > > > > > }
> > > > > > audit_log_end(ab);
> > > > >
> > > > > There is an audit_log_end() in the calling function, show_special(), 
> > > > > so
> > > > > it should only be called here if there is another buffer allocated in
> > > > > this function after it.  audit_log_end() is protected should it be
> > > > > called with no valid buffer so this wouldn't create a bug.
> > > >
> > > > As audit_log_end() can safely take a NULL audit_buffer I don't care if 
> > > > we
> > > > send it back a valid buffer or a NULL.  IMO it happens to be easier (and
> > > > cleaner) to send back a NULL.
> > >
> > > None of the other callees in show_special() do that, so this would be
> > > surprising behaviour that could cause a future bug ...
> >
> > To be both honest and frank: I disagree with your assessment.  If you
> > really want to be concerned about this, there are plenty of ways to
> > mitigate the "risk" depending on your comfort level; comments and
> > returning within the switch/case block are just some of the options.
> >
> > > > > > if (*abp) {
> > > > > >   *abp = NULL;
> > > > > >   type = (type == AUDIT_TIME_ADJNTPVAL ?
> > > > > > AUDIT_TIME_INJOFFSET : AUDIT_TIME_ADJNTPVAL);
> > > > >
> > > > > This cannot be allocated if there are no more needed above ...
> > > >
> > > > My mistake, I was distracted a few times while typing up my reply and 
> > > > the
> > > > code within; while I had that detail in mind when I started I lost it
> > > > during one of the interruptions.  As penance, I wrote up some slightly 
> > > > more
> > > > proper code and at least made sure it complied, although I've not tried
> > > > booting it ...
> > >
> > > Did you test the code I submitted?  It compiles and works.  I found this
> > > code harder to follow.  This was partly why I wanted to leave one of the
> > > record types outside of show_special() but I did find a way to
> > > accomodate both with a minimum of overhead.
> >
> > Once again, I disagree with your assessment of the code.  I'm not sure
> > how to put this politely, but I personally found your audit_log_time()
> > implementation to be awkward; the AUDIT_TIME_INJOFFSET goto/jump to
> > "tk" at the top of the function was not something I'm going to merge.
> > You don't have to like my suggestion, but please send me a patch that
> > has a somewhat reasonable code flow.  I know you often want, or at
> > least ask for explicit suggestions (hence my untested code example),
> > but since you didn't like that let me just say this: when in doubt,
> > limit your use of gotos/jumps to error handling unless there is
> > something significantly unusual about the function.  In my opinion
> > there is nothing significantly unusual about the audit_log_time()
> > function to require a jump as you've currently done.
>
> I hate gotos.  I first learned to program on Waterloo Structured BASIC
> 4.0 on a Commodore PET 2001 where the language structure provided the
> tools to be able to avoid them.  I've avoided them and reluctantly used
> them at your urging, so now I'm a bit confused.

If you're confused 

Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-02-11 Thread Richard Guy Briggs
On 2022-02-10 21:08, Paul Moore wrote:
> On Thu, Feb 10, 2022 at 6:46 PM Richard Guy Briggs  wrote:
> > On 2022-01-31 20:29, Paul Moore wrote:
> > > On Mon, Jan 31, 2022 at 6:29 PM Richard Guy Briggs  
> > > wrote:
> > > > On 2022-01-31 17:02, Paul Moore wrote:
> > > > > On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs  
> > > > > wrote:
> > > > > > On 2022-01-25 22:24, Richard Guy Briggs wrote:
> 
> This isn't as complete of a response as I would like, but I wanted to
> get *something* back to you same-day since the delays are getting a
> bit long ...
> 
> > > > > [WARNING: not compiled, tested, yadda yadda]
> > > > >
> > > > > void audit_log_time(struct audit_context ctx, struct audit_buffer 
> > > > > **abp)
> > > > > {
> > > > >   int i;
> > > > >   int type = ctx->type;
> > > > >   struct audit_buffer *ab = *abp;
> > > > >   struct audit_ntp_val *ntp;
> > > > >   const struct timespec64 *tk;
> > > > >   const char *ntp_name[] = {
> > > > > "offset",
> > > > > "freq",
> > > > > "status",
> > > > > "tai",
> > > > > "tick",
> > > > > "adjust",
> > > > >   };
> > > > >
> > > > >   do {
> > > > > if (type == AUDIT_TIME_ADJNTPVAL) {
> > > > >   ntp = ctx->time.ntp_data.val;
> > > > >   for (i = 0; i < AUDIT_NTP_NVALS; i++) {
> > > > > if (ntp[i].newval != ntp[i].oldval) {
> > > > >   audit_log_format(ab,
> > > > > "op=%s old=%lli new=%lli",
> > > > > ntp_name[type],
> > > > > ntp[i].oldval, ntp[i].newval);
> > > > > }
> > > > >   }
> > > > > } else {
> > > > >   tk = >time.tk_injoffset;
> > > > >   audit_log_format(ab, "sec=%lli nsec=%li",
> > > > > (long long)tk->tv_sec, tk->tv_nsec);
> > > > > }
> > > > > audit_log_end(ab);
> > > >
> > > > There is an audit_log_end() in the calling function, show_special(), so
> > > > it should only be called here if there is another buffer allocated in
> > > > this function after it.  audit_log_end() is protected should it be
> > > > called with no valid buffer so this wouldn't create a bug.
> > >
> > > As audit_log_end() can safely take a NULL audit_buffer I don't care if we
> > > send it back a valid buffer or a NULL.  IMO it happens to be easier (and
> > > cleaner) to send back a NULL.
> >
> > None of the other callees in show_special() do that, so this would be
> > surprising behaviour that could cause a future bug ...
> 
> To be both honest and frank: I disagree with your assessment.  If you
> really want to be concerned about this, there are plenty of ways to
> mitigate the "risk" depending on your comfort level; comments and
> returning within the switch/case block are just some of the options.
> 
> > > > > if (*abp) {
> > > > >   *abp = NULL;
> > > > >   type = (type == AUDIT_TIME_ADJNTPVAL ?
> > > > > AUDIT_TIME_INJOFFSET : AUDIT_TIME_ADJNTPVAL);
> > > >
> > > > This cannot be allocated if there are no more needed above ...
> > >
> > > My mistake, I was distracted a few times while typing up my reply and the
> > > code within; while I had that detail in mind when I started I lost it
> > > during one of the interruptions.  As penance, I wrote up some slightly 
> > > more
> > > proper code and at least made sure it complied, although I've not tried
> > > booting it ...
> >
> > Did you test the code I submitted?  It compiles and works.  I found this
> > code harder to follow.  This was partly why I wanted to leave one of the
> > record types outside of show_special() but I did find a way to
> > accomodate both with a minimum of overhead.
> 
> Once again, I disagree with your assessment of the code.  I'm not sure
> how to put this politely, but I personally found your audit_log_time()
> implementation to be awkward; the AUDIT_TIME_INJOFFSET goto/jump to
> "tk" at the top of the function was not something I'm going to merge.
> You don't have to like my suggestion, but please send me a patch that
> has a somewhat reasonable code flow.  I know you often want, or at
> least ask for explicit suggestions (hence my untested code example),
> but since you didn't like that let me just say this: when in doubt,
> limit your use of gotos/jumps to error handling unless there is
> something significantly unusual about the function.  In my opinion
> there is nothing significantly unusual about the audit_log_time()
> function to require a jump as you've currently done.

I hate gotos.  I first learned to program on Waterloo Structured BASIC
4.0 on a Commodore PET 2001 where the language structure provided the
tools to be able to avoid them.  I've avoided them and reluctantly used
them at your urging, so now I'm a bit confused.

> paul-moore.com

- RGB

--
Richard Guy Briggs 
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
IRC: rgb, SunRaycer
Voice: +1.647.777.2635, Internal: (81) 32635

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-02-10 Thread Paul Moore
On Thu, Feb 10, 2022 at 6:46 PM Richard Guy Briggs  wrote:
> On 2022-01-31 20:29, Paul Moore wrote:
> > On Mon, Jan 31, 2022 at 6:29 PM Richard Guy Briggs  wrote:
> > > On 2022-01-31 17:02, Paul Moore wrote:
> > > > On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs  
> > > > wrote:
> > > > > On 2022-01-25 22:24, Richard Guy Briggs wrote:

This isn't as complete of a response as I would like, but I wanted to
get *something* back to you same-day since the delays are getting a
bit long ...

> > > > [WARNING: not compiled, tested, yadda yadda]
> > > >
> > > > void audit_log_time(struct audit_context ctx, struct audit_buffer **abp)
> > > > {
> > > >   int i;
> > > >   int type = ctx->type;
> > > >   struct audit_buffer *ab = *abp;
> > > >   struct audit_ntp_val *ntp;
> > > >   const struct timespec64 *tk;
> > > >   const char *ntp_name[] = {
> > > > "offset",
> > > > "freq",
> > > > "status",
> > > > "tai",
> > > > "tick",
> > > > "adjust",
> > > >   };
> > > >
> > > >   do {
> > > > if (type == AUDIT_TIME_ADJNTPVAL) {
> > > >   ntp = ctx->time.ntp_data.val;
> > > >   for (i = 0; i < AUDIT_NTP_NVALS; i++) {
> > > > if (ntp[i].newval != ntp[i].oldval) {
> > > >   audit_log_format(ab,
> > > > "op=%s old=%lli new=%lli",
> > > > ntp_name[type],
> > > > ntp[i].oldval, ntp[i].newval);
> > > > }
> > > >   }
> > > > } else {
> > > >   tk = >time.tk_injoffset;
> > > >   audit_log_format(ab, "sec=%lli nsec=%li",
> > > > (long long)tk->tv_sec, tk->tv_nsec);
> > > > }
> > > > audit_log_end(ab);
> > >
> > > There is an audit_log_end() in the calling function, show_special(), so
> > > it should only be called here if there is another buffer allocated in
> > > this function after it.  audit_log_end() is protected should it be
> > > called with no valid buffer so this wouldn't create a bug.
> >
> > As audit_log_end() can safely take a NULL audit_buffer I don't care if we
> > send it back a valid buffer or a NULL.  IMO it happens to be easier (and
> > cleaner) to send back a NULL.
>
> None of the other callees in show_special() do that, so this would be
> surprising behaviour that could cause a future bug ...

To be both honest and frank: I disagree with your assessment.  If you
really want to be concerned about this, there are plenty of ways to
mitigate the "risk" depending on your comfort level; comments and
returning within the switch/case block are just some of the options.

> > > > if (*abp) {
> > > >   *abp = NULL;
> > > >   type = (type == AUDIT_TIME_ADJNTPVAL ?
> > > > AUDIT_TIME_INJOFFSET : AUDIT_TIME_ADJNTPVAL);
> > >
> > > This cannot be allocated if there are no more needed above ...
> >
> > My mistake, I was distracted a few times while typing up my reply and the
> > code within; while I had that detail in mind when I started I lost it
> > during one of the interruptions.  As penance, I wrote up some slightly more
> > proper code and at least made sure it complied, although I've not tried
> > booting it ...
>
> Did you test the code I submitted?  It compiles and works.  I found this
> code harder to follow.  This was partly why I wanted to leave one of the
> record types outside of show_special() but I did find a way to
> accomodate both with a minimum of overhead.

Once again, I disagree with your assessment of the code.  I'm not sure
how to put this politely, but I personally found your audit_log_time()
implementation to be awkward; the AUDIT_TIME_INJOFFSET goto/jump to
"tk" at the top of the function was not something I'm going to merge.
You don't have to like my suggestion, but please send me a patch that
has a somewhat reasonable code flow.  I know you often want, or at
least ask for explicit suggestions (hence my untested code example),
but since you didn't like that let me just say this: when in doubt,
limit your use of gotos/jumps to error handling unless there is
something significantly unusual about the function.  In my opinion
there is nothing significantly unusual about the audit_log_time()
function to require a jump as you've currently done.

--
paul-moore.com

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-02-10 Thread Richard Guy Briggs
On 2022-01-31 20:29, Paul Moore wrote:
> On Mon, Jan 31, 2022 at 6:29 PM Richard Guy Briggs  wrote:
> > On 2022-01-31 17:02, Paul Moore wrote:
> > > On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs  
> > > wrote:
> > > > On 2022-01-25 22:24, Richard Guy Briggs 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 in the
> > > > > context and log it at syscall exit time respecting the filter rules.
> > > > >
> > > > > Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> > > > >
> > > > > Fixes: 7e8eda734d30 ("ntp: Audit NTP parameters adjustment")
> > > > > Fixes: 2d87a0674bd6 ("timekeeping: Audit clock adjustments")
> > > > > Signed-off-by: Richard Guy Briggs 
> > > > > ---
> > > > > Changelog:
> > > > > v2:
> > > > > - rename __audit_ntp_log_ to audit_log_ntp
> > > > > - pre-check ntp before storing
> > > > > - move tk out of the context union and move ntp logging to the bottom 
> > > > > of audit_show_special()
> > > > > - restructure logging of ntp to use ab and allocate more only if more
> > > > > - add Fixes lines
> > > > > v3
> > > > > - move tk into union
> > > > > - rename audit_log_ntp() to audit_log_time() and add tk
> > > > > - key off both AUDIT_TIME_* but favour NTP
> > > > >
> > > > >  kernel/audit.h   |  4 +++
> > > > >  kernel/auditsc.c | 86 
> > > > > +---
> > > > >  2 files changed, 70 insertions(+), 20 deletions(-)
> > >
> > > ...
> > >
> > > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > > > index b517947bfa48..9c6c55a81fdb 100644
> > > > > --- a/kernel/auditsc.c
> > > > > +++ b/kernel/auditsc.c
> > > > > @@ -1331,6 +1331,55 @@ static void audit_log_fcaps(struct 
> > > > > audit_buffer *ab, struct audit_names *name)
> > > > >from_kuid(_user_ns, name->fcap.rootid));
> > > > >  }
> > > > >
> > > > > +void audit_log_time(struct audit_context *context, struct 
> > > > > audit_buffer **ab)
> > > > > +{
> > > > > + const struct audit_ntp_data *ntp = >time.ntp_data;
> > > > > + const struct timespec64 *tk = >time.tk_injoffset;
> > > > > + const char *ntp_name[] = {
> > > > > + "offset",
> > > > > + "freq",
> > > > > + "status",
> > > > > + "tai",
> > > > > + "tick",
> > > > > + "adjust",
> > > > > + };
> > > > > + int type, first = 1;
> > > > > +
> > > > > + if (context->type == AUDIT_TIME_INJOFFSET)
> > > > > + goto tk;
> > > > > +
> > > > > + /* use up allocated ab from show_special before new one */
> > > > > + for (type = 0; type < AUDIT_NTP_NVALS; type++) {
> > > > > + if (ntp->vals[type].newval != ntp->vals[type].oldval) {
> > > > > + if (first) {
> > > > > + first = 0;
> > > > > + } else {
> > > > > + audit_log_end(*ab);
> > > > > + *ab = audit_log_start(context, 
> > > > > GFP_KERNEL,
> > > > > +   
> > > > > AUDIT_TIME_ADJNTPVAL);
> > > > > + if (!*ab)
> > > > > + return;
> > > > > + }
> > > > > + audit_log_format(*ab, "op=%s old=%lli new=%lli",
> > > > > +  ntp_name[type], 
> > > > > ntp->vals[type].oldval,
> > > > > +  ntp->vals[type].newval);
> > > > > + }
> > > > > + }
> > > > > +
> > > > > +tk:
> > > > > + if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
> > > > > + if (!first) {
> > > > > + audit_log_end(*ab);
> > > > > + *ab = audit_log_start(context, GFP_KERNEL,
> > > > > +   AUDIT_TIME_INJOFFSET);
> > > > > + if (!*ab)
> > > > > + return;
> > > > > + }
> > > >
> > > > It occurs to me that a slight improvement could be made to move the
> > > > "tk:" label here.  And better yet, change the tk condition above to:
> > > >
> > > > if (!tk->tv_sec && !tk->tv_nsec)
> > > > return;
> > >
> > > Honestly, I've looked at this a few times over different days trying
> > > to make sure I'm not missing something, but there is a lot of
> > > complexity in audit_log_time() that I don't believe is necessary.
> > > What about something like below?
> > >
> > > [WARNING: not compiled, tested, yadda yadda]
> > >
> > > void audit_log_time(struct audit_context ctx, struct audit_buffer **abp)
> > > {
> > >   int i;
> > >   int type = 

Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-01-31 Thread Paul Moore
On Mon, Jan 31, 2022 at 6:29 PM Richard Guy Briggs  wrote:
> On 2022-01-31 17:02, Paul Moore wrote:
> > On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs 
wrote:
> > > On 2022-01-25 22:24, Richard Guy Briggs 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 in the
> > > > context and log it at syscall exit time respecting the filter rules.
> > > >
> > > > Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> > > >
> > > > Fixes: 7e8eda734d30 ("ntp: Audit NTP parameters adjustment")
> > > > Fixes: 2d87a0674bd6 ("timekeeping: Audit clock adjustments")
> > > > Signed-off-by: Richard Guy Briggs 
> > > > ---
> > > > Changelog:
> > > > v2:
> > > > - rename __audit_ntp_log_ to audit_log_ntp
> > > > - pre-check ntp before storing
> > > > - move tk out of the context union and move ntp logging to the
bottom of audit_show_special()
> > > > - restructure logging of ntp to use ab and allocate more only if
more
> > > > - add Fixes lines
> > > > v3
> > > > - move tk into union
> > > > - rename audit_log_ntp() to audit_log_time() and add tk
> > > > - key off both AUDIT_TIME_* but favour NTP
> > > >
> > > >  kernel/audit.h   |  4 +++
> > > >  kernel/auditsc.c | 86
+---
> > > >  2 files changed, 70 insertions(+), 20 deletions(-)
> >
> > ...
> >
> > > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > > index b517947bfa48..9c6c55a81fdb 100644
> > > > --- a/kernel/auditsc.c
> > > > +++ b/kernel/auditsc.c
> > > > @@ -1331,6 +1331,55 @@ static void audit_log_fcaps(struct
audit_buffer *ab, struct audit_names *name)
> > > >from_kuid(_user_ns, name->fcap.rootid));
> > > >  }
> > > >
> > > > +void audit_log_time(struct audit_context *context, struct
audit_buffer **ab)
> > > > +{
> > > > + const struct audit_ntp_data *ntp = >time.ntp_data;
> > > > + const struct timespec64 *tk = >time.tk_injoffset;
> > > > + const char *ntp_name[] = {
> > > > + "offset",
> > > > + "freq",
> > > > + "status",
> > > > + "tai",
> > > > + "tick",
> > > > + "adjust",
> > > > + };
> > > > + int type, first = 1;
> > > > +
> > > > + if (context->type == AUDIT_TIME_INJOFFSET)
> > > > + goto tk;
> > > > +
> > > > + /* use up allocated ab from show_special before new one */
> > > > + for (type = 0; type < AUDIT_NTP_NVALS; type++) {
> > > > + if (ntp->vals[type].newval != ntp->vals[type].oldval)
{
> > > > + if (first) {
> > > > + first = 0;
> > > > + } else {
> > > > + audit_log_end(*ab);
> > > > + *ab = audit_log_start(context,
GFP_KERNEL,
> > > > +
AUDIT_TIME_ADJNTPVAL);
> > > > + if (!*ab)
> > > > + return;
> > > > + }
> > > > + audit_log_format(*ab, "op=%s old=%lli
new=%lli",
> > > > +  ntp_name[type],
ntp->vals[type].oldval,
> > > > +  ntp->vals[type].newval);
> > > > + }
> > > > + }
> > > > +
> > > > +tk:
> > > > + if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
> > > > + if (!first) {
> > > > + audit_log_end(*ab);
> > > > + *ab = audit_log_start(context, GFP_KERNEL,
> > > > +   AUDIT_TIME_INJOFFSET);
> > > > + if (!*ab)
> > > > + return;
> > > > + }
> > >
> > > It occurs to me that a slight improvement could be made to move the
> > > "tk:" label here.  And better yet, change the tk condition above to:
> > >
> > > if (!tk->tv_sec && !tk->tv_nsec)
> > > return;
> >
> > Honestly, I've looked at this a few times over different days trying
> > to make sure I'm not missing something, but there is a lot of
> > complexity in audit_log_time() that I don't believe is necessary.
> > What about something like below?
> >
> > [WARNING: not compiled, tested, yadda yadda]
> >
> > void audit_log_time(struct audit_context ctx, struct audit_buffer **abp)
> > {
> >   int i;
> >   int type = ctx->type;
> >   struct audit_buffer *ab = *abp;
> >   struct audit_ntp_val *ntp;
> >   const struct timespec64 *tk;
> >   const char *ntp_name[] = {
> > "offset",
> > "freq",
> > "status",
> > "tai",
> > "tick",
> > "adjust",
> >   };
> >
> >   do {
> > if (type == AUDIT_TIME_ADJNTPVAL) {
> >   ntp = ctx->time.ntp_data.val;
> >   for (i = 0; i < AUDIT_NTP_NVALS; i++) {
> > if 

Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-01-31 Thread Richard Guy Briggs
On 2022-01-31 17:02, Paul Moore wrote:
> On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs  wrote:
> > On 2022-01-25 22:24, Richard Guy Briggs 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 
> > > in the
> > > context and log it at syscall exit time respecting the filter rules.
> > >
> > > Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> > >
> > > Fixes: 7e8eda734d30 ("ntp: Audit NTP parameters adjustment")
> > > Fixes: 2d87a0674bd6 ("timekeeping: Audit clock adjustments")
> > > Signed-off-by: Richard Guy Briggs 
> > > ---
> > > Changelog:
> > > v2:
> > > - rename __audit_ntp_log_ to audit_log_ntp
> > > - pre-check ntp before storing
> > > - move tk out of the context union and move ntp logging to the bottom of 
> > > audit_show_special()
> > > - restructure logging of ntp to use ab and allocate more only if more
> > > - add Fixes lines
> > > v3
> > > - move tk into union
> > > - rename audit_log_ntp() to audit_log_time() and add tk
> > > - key off both AUDIT_TIME_* but favour NTP
> > >
> > >  kernel/audit.h   |  4 +++
> > >  kernel/auditsc.c | 86 +---
> > >  2 files changed, 70 insertions(+), 20 deletions(-)
> 
> ...
> 
> > > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > > index b517947bfa48..9c6c55a81fdb 100644
> > > --- a/kernel/auditsc.c
> > > +++ b/kernel/auditsc.c
> > > @@ -1331,6 +1331,55 @@ static void audit_log_fcaps(struct audit_buffer 
> > > *ab, struct audit_names *name)
> > >from_kuid(_user_ns, name->fcap.rootid));
> > >  }
> > >
> > > +void audit_log_time(struct audit_context *context, struct audit_buffer 
> > > **ab)
> > > +{
> > > + const struct audit_ntp_data *ntp = >time.ntp_data;
> > > + const struct timespec64 *tk = >time.tk_injoffset;
> > > + const char *ntp_name[] = {
> > > + "offset",
> > > + "freq",
> > > + "status",
> > > + "tai",
> > > + "tick",
> > > + "adjust",
> > > + };
> > > + int type, first = 1;
> > > +
> > > + if (context->type == AUDIT_TIME_INJOFFSET)
> > > + goto tk;
> > > +
> > > + /* use up allocated ab from show_special before new one */
> > > + for (type = 0; type < AUDIT_NTP_NVALS; type++) {
> > > + if (ntp->vals[type].newval != ntp->vals[type].oldval) {
> > > + if (first) {
> > > + first = 0;
> > > + } else {
> > > + audit_log_end(*ab);
> > > + *ab = audit_log_start(context, GFP_KERNEL,
> > > +   AUDIT_TIME_ADJNTPVAL);
> > > + if (!*ab)
> > > + return;
> > > + }
> > > + audit_log_format(*ab, "op=%s old=%lli new=%lli",
> > > +  ntp_name[type], 
> > > ntp->vals[type].oldval,
> > > +  ntp->vals[type].newval);
> > > + }
> > > + }
> > > +
> > > +tk:
> > > + if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
> > > + if (!first) {
> > > + audit_log_end(*ab);
> > > + *ab = audit_log_start(context, GFP_KERNEL,
> > > +   AUDIT_TIME_INJOFFSET);
> > > + if (!*ab)
> > > + return;
> > > + }
> >
> > It occurs to me that a slight improvement could be made to move the
> > "tk:" label here.  And better yet, change the tk condition above to:
> >
> > if (!tk->tv_sec && !tk->tv_nsec)
> > return;
> 
> Honestly, I've looked at this a few times over different days trying
> to make sure I'm not missing something, but there is a lot of
> complexity in audit_log_time() that I don't believe is necessary.
> What about something like below?
> 
> [WARNING: not compiled, tested, yadda yadda]
> 
> void audit_log_time(struct audit_context ctx, struct audit_buffer **abp)
> {
>   int i;
>   int type = ctx->type;
>   struct audit_buffer *ab = *abp;
>   struct audit_ntp_val *ntp;
>   const struct timespec64 *tk;
>   const char *ntp_name[] = {
> "offset",
> "freq",
> "status",
> "tai",
> "tick",
> "adjust",
>   };
> 
>   do {
> if (type == AUDIT_TIME_ADJNTPVAL) {
>   ntp = ctx->time.ntp_data.val;
>   for (i = 0; i < AUDIT_NTP_NVALS; i++) {
> if (ntp[i].newval != ntp[i].oldval) {
>   audit_log_format(ab,
> "op=%s old=%lli new=%lli",
> ntp_name[type],
> ntp[i].oldval, ntp[i].newval);
> }

Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-01-31 Thread Paul Moore
On Wed, Jan 26, 2022 at 8:52 AM Richard Guy Briggs  wrote:
> On 2022-01-25 22:24, Richard Guy Briggs 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 in 
> > the
> > context and log it at syscall exit time respecting the filter rules.
> >
> > Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> >
> > Fixes: 7e8eda734d30 ("ntp: Audit NTP parameters adjustment")
> > Fixes: 2d87a0674bd6 ("timekeeping: Audit clock adjustments")
> > Signed-off-by: Richard Guy Briggs 
> > ---
> > Changelog:
> > v2:
> > - rename __audit_ntp_log_ to audit_log_ntp
> > - pre-check ntp before storing
> > - move tk out of the context union and move ntp logging to the bottom of 
> > audit_show_special()
> > - restructure logging of ntp to use ab and allocate more only if more
> > - add Fixes lines
> > v3
> > - move tk into union
> > - rename audit_log_ntp() to audit_log_time() and add tk
> > - key off both AUDIT_TIME_* but favour NTP
> >
> >  kernel/audit.h   |  4 +++
> >  kernel/auditsc.c | 86 +---
> >  2 files changed, 70 insertions(+), 20 deletions(-)

...

> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index b517947bfa48..9c6c55a81fdb 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -1331,6 +1331,55 @@ static void audit_log_fcaps(struct audit_buffer *ab, 
> > struct audit_names *name)
> >from_kuid(_user_ns, name->fcap.rootid));
> >  }
> >
> > +void audit_log_time(struct audit_context *context, struct audit_buffer 
> > **ab)
> > +{
> > + const struct audit_ntp_data *ntp = >time.ntp_data;
> > + const struct timespec64 *tk = >time.tk_injoffset;
> > + const char *ntp_name[] = {
> > + "offset",
> > + "freq",
> > + "status",
> > + "tai",
> > + "tick",
> > + "adjust",
> > + };
> > + int type, first = 1;
> > +
> > + if (context->type == AUDIT_TIME_INJOFFSET)
> > + goto tk;
> > +
> > + /* use up allocated ab from show_special before new one */
> > + for (type = 0; type < AUDIT_NTP_NVALS; type++) {
> > + if (ntp->vals[type].newval != ntp->vals[type].oldval) {
> > + if (first) {
> > + first = 0;
> > + } else {
> > + audit_log_end(*ab);
> > + *ab = audit_log_start(context, GFP_KERNEL,
> > +   AUDIT_TIME_ADJNTPVAL);
> > + if (!*ab)
> > + return;
> > + }
> > + audit_log_format(*ab, "op=%s old=%lli new=%lli",
> > +  ntp_name[type], 
> > ntp->vals[type].oldval,
> > +  ntp->vals[type].newval);
> > + }
> > + }
> > +
> > +tk:
> > + if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
> > + if (!first) {
> > + audit_log_end(*ab);
> > + *ab = audit_log_start(context, GFP_KERNEL,
> > +   AUDIT_TIME_INJOFFSET);
> > + if (!*ab)
> > + return;
> > + }
>
> It occurs to me that a slight improvement could be made to move the
> "tk:" label here.  And better yet, change the tk condition above to:
>
> if (!tk->tv_sec && !tk->tv_nsec)
> return;

Honestly, I've looked at this a few times over different days trying
to make sure I'm not missing something, but there is a lot of
complexity in audit_log_time() that I don't believe is necessary.
What about something like below?

[WARNING: not compiled, tested, yadda yadda]

void audit_log_time(struct audit_context ctx, struct audit_buffer **abp)
{
  int i;
  int type = ctx->type;
  struct audit_buffer *ab = *abp;
  struct audit_ntp_val *ntp;
  const struct timespec64 *tk;
  const char *ntp_name[] = {
"offset",
"freq",
"status",
"tai",
"tick",
"adjust",
  };

  do {
if (type == AUDIT_TIME_ADJNTPVAL) {
  ntp = ctx->time.ntp_data.val;
  for (i = 0; i < AUDIT_NTP_NVALS; i++) {
if (ntp[i].newval != ntp[i].oldval) {
  audit_log_format(ab,
"op=%s old=%lli new=%lli",
ntp_name[type],
ntp[i].oldval, ntp[i].newval);
}
  }
} else {
  tk = >time.tk_injoffset;
  audit_log_format(ab, "sec=%lli nsec=%li",
(long long)tk->tv_sec, tk->tv_nsec);
}
audit_log_end(ab);

if (*abp) {
  *abp = NULL;
  type = (type == AUDIT_TIME_ADJNTPVAL ?
AUDIT_TIME_INJOFFSET : 

Re: [PATCH v3] audit: log AUDIT_TIME_* records only from rules

2022-01-26 Thread Richard Guy Briggs
On 2022-01-25 22:24, Richard Guy Briggs 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 in 
> the
> context and log it at syscall exit time respecting the filter rules.
> 
> Please see https://bugzilla.redhat.com/show_bug.cgi?id=1991919
> 
> Fixes: 7e8eda734d30 ("ntp: Audit NTP parameters adjustment")
> Fixes: 2d87a0674bd6 ("timekeeping: Audit clock adjustments")
> Signed-off-by: Richard Guy Briggs 
> ---
> Changelog:
> v2:
> - rename __audit_ntp_log_ to audit_log_ntp
> - pre-check ntp before storing
> - move tk out of the context union and move ntp logging to the bottom of 
> audit_show_special()
> - restructure logging of ntp to use ab and allocate more only if more
> - add Fixes lines
> v3
> - move tk into union
> - rename audit_log_ntp() to audit_log_time() and add tk
> - key off both AUDIT_TIME_* but favour NTP
> 
>  kernel/audit.h   |  4 +++
>  kernel/auditsc.c | 86 +---
>  2 files changed, 70 insertions(+), 20 deletions(-)
> 
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c4498090a5bd..58b66543b4d5 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -201,6 +201,10 @@ struct audit_context {
>   struct {
>   char*name;
>   } module;
> + struct {
> + struct audit_ntp_data   ntp_data;
> + struct timespec64   tk_injoffset;
> + } time;
>   };
>   int fds[2];
>   struct audit_proctitle proctitle;
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index b517947bfa48..9c6c55a81fdb 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -1331,6 +1331,55 @@ static void audit_log_fcaps(struct audit_buffer *ab, 
> struct audit_names *name)
>from_kuid(_user_ns, name->fcap.rootid));
>  }
>  
> +void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
> +{
> + const struct audit_ntp_data *ntp = >time.ntp_data;
> + const struct timespec64 *tk = >time.tk_injoffset;
> + const char *ntp_name[] = {
> + "offset",
> + "freq",
> + "status",
> + "tai",
> + "tick",
> + "adjust",
> + };
> + int type, first = 1;
> +
> + if (context->type == AUDIT_TIME_INJOFFSET)
> + goto tk;
> +
> + /* use up allocated ab from show_special before new one */
> + for (type = 0; type < AUDIT_NTP_NVALS; type++) {
> + if (ntp->vals[type].newval != ntp->vals[type].oldval) {
> + if (first) {
> + first = 0;
> + } else {
> + audit_log_end(*ab);
> + *ab = audit_log_start(context, GFP_KERNEL,
> +   AUDIT_TIME_ADJNTPVAL);
> + if (!*ab)
> + return;
> + }
> + audit_log_format(*ab, "op=%s old=%lli new=%lli",
> +  ntp_name[type], ntp->vals[type].oldval,
> +  ntp->vals[type].newval);
> + }
> + }
> +
> +tk:
> + if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
> + if (!first) {
> + audit_log_end(*ab);
> + *ab = audit_log_start(context, GFP_KERNEL,
> +   AUDIT_TIME_INJOFFSET);
> + if (!*ab)
> + return;
> + }

It occurs to me that a slight improvement could be made to move the
"tk:" label here.  And better yet, change the tk condition above to:

if (!tk->tv_sec && !tk->tv_nsec)
return;

> + audit_log_format(*ab, "sec=%lli nsec=%li",
> +  (long long)tk->tv_sec, tk->tv_nsec);
> + }
> +}
> +
>  static void show_special(struct audit_context *context, int *call_panic)
>  {
>   struct audit_buffer *ab;
> @@ -1445,6 +1494,10 @@ static void show_special(struct audit_context 
> *context, int *call_panic)
>   audit_log_format(ab, "(null)");
>  
>   break;
> + case AUDIT_TIME_ADJNTPVAL:
> + case AUDIT_TIME_INJOFFSET:
> + audit_log_time(context, );
> + break;
>   }
>   audit_log_end(ab);
>  }
> @@ -2840,31 +2893,24 @@ void __audit_fanotify(unsigned int response)
>  
>  void __audit_tk_injoffset(struct timespec64 offset)
>  {
> - audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET,
> -   "sec=%lli nsec=%li",
> -   (long long)offset.tv_sec, offset.tv_nsec);
> -}
> -
>