Merge tag 'audit-pr-20220321' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 03:53:11 +0000 (20:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 03:53:11 +0000 (20:53 -0700)
Pull audit update from Paul Moore:
 "Just one audit patch queued for v5.18:

   - Change the AUDIT_TIME_* record generation so that they are
     generated at syscall exit time and subject to all of the normal
     syscall exit filtering.

     This should help reduce noise and ensure those records which are
     most relevant to the admin's audit configuration are recorded in
     the audit log"

* tag 'audit-pr-20220321' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: log AUDIT_TIME_* records only from rules

kernel/audit.h
kernel/auditsc.c

index c4498090a5bd66e5c620368381c89d4dda14d851..58b66543b4d57e6542f97900cc7809f4aea7de61 100644 (file)
@@ -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;
index a83928cbdcb7cd2e52d3bf40db5e794db39499a7..ea2ee1181921e13592f19aae0fc7a0d4f7857ac5 100644 (file)
@@ -1340,6 +1340,53 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
                         from_kuid(&init_user_ns, name->fcap.rootid));
 }
 
+static void audit_log_time(struct audit_context *context, struct audit_buffer **ab)
+{
+       const struct audit_ntp_data *ntp = &context->time.ntp_data;
+       const struct timespec64 *tk = &context->time.tk_injoffset;
+       static const char * const ntp_name[] = {
+               "offset",
+               "freq",
+               "status",
+               "tai",
+               "tick",
+               "adjust",
+       };
+       int type;
+
+       if (context->type == AUDIT_TIME_ADJNTPVAL) {
+               for (type = 0; type < AUDIT_NTP_NVALS; type++) {
+                       if (ntp->vals[type].newval != ntp->vals[type].oldval) {
+                               if (!*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);
+                               audit_log_end(*ab);
+                               *ab = NULL;
+                       }
+               }
+       }
+       if (tk->tv_sec != 0 || tk->tv_nsec != 0) {
+               if (!*ab) {
+                       *ab = audit_log_start(context, GFP_KERNEL,
+                                             AUDIT_TIME_INJOFFSET);
+                       if (!*ab)
+                               return;
+               }
+               audit_log_format(*ab, "sec=%lli nsec=%li",
+                                (long long)tk->tv_sec, tk->tv_nsec);
+               audit_log_end(*ab);
+               *ab = NULL;
+       }
+}
+
 static void show_special(struct audit_context *context, int *call_panic)
 {
        struct audit_buffer *ab;
@@ -1454,6 +1501,11 @@ 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:
+               /* this call deviates from the rest, eating the buffer */
+               audit_log_time(context, &ab);
+               break;
        }
        audit_log_end(ab);
 }
@@ -2849,31 +2901,26 @@ 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);
-}
-
-static void audit_log_ntp_val(const struct audit_ntp_data *ad,
-                             const char *op, enum audit_ntp_type type)
-{
-       const struct audit_ntp_val *val = &ad->vals[type];
-
-       if (val->newval == val->oldval)
-               return;
+       struct audit_context *context = audit_context();
 
-       audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_ADJNTPVAL,
-                 "op=%s old=%lli new=%lli", op, val->oldval, val->newval);
+       /* only set type if not already set by NTP */
+       if (!context->type)
+               context->type = AUDIT_TIME_INJOFFSET;
+       memcpy(&context->time.tk_injoffset, &offset, sizeof(offset));
 }
 
 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);
-       audit_log_ntp_val(ad, "status", AUDIT_NTP_STATUS);
-       audit_log_ntp_val(ad, "tai",    AUDIT_NTP_TAI);
-       audit_log_ntp_val(ad, "tick",   AUDIT_NTP_TICK);
-       audit_log_ntp_val(ad, "adjust", AUDIT_NTP_ADJUST);
+       struct audit_context *context = audit_context();
+       int type;
+
+       for (type = 0; type < AUDIT_NTP_NVALS; type++)
+               if (ad->vals[type].newval != ad->vals[type].oldval) {
+                       /* unconditionally set type, overwriting TK */
+                       context->type = AUDIT_TIME_ADJNTPVAL;
+                       memcpy(&context->time.ntp_data, ad, sizeof(*ad));
+                       break;
+               }
 }
 
 void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,