audit.47 kernel -- add serial number to non-syscall messages.

David Woodhouse dwmw2 at infradead.org
Sat May 21 20:35:18 UTC 2005


Steve pointed out that all user messages are getting logged with a
serial number of zero -- so in the relatively unlikely event that more
than one such message is generated with precisely the same timestamp
(i.e. in the same millisecond), they'd have the same stamp. 

He provided a patch which I mangled somewhat till I was happy with it,
and the result is in the audit.47 kernel which is uploading to the yum
repository now. What's below is the version I committed to the git tree,
which is slightly different because there were related changes in that
area already. The resulting code should be the same in each case.

Index: include/linux/audit.h
===================================================================
--- 8ab8eef2e8c3629c46d29ffb9c618d87c5e1a02c/include/linux/audit.h  (mode:100644)
+++ uncommitted/include/linux/audit.h  (mode:100644)
@@ -219,8 +219,9 @@
 				/* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 				 void *data, uid_t loginuid);
-extern int audit_get_stamp(struct audit_context *ctx,
-			    struct timespec *t, unsigned int *serial);
+extern unsigned int audit_serial(void);
+extern void auditsc_get_stamp(struct audit_context *ctx,
+			      struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
 extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
@@ -237,7 +238,7 @@
 #define audit_putname(n) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
 #define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
-#define audit_get_stamp(c,t,s) ({ 0; })
+#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_perms(q,u,g,m) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
Index: kernel/audit.c
===================================================================
--- 8ab8eef2e8c3629c46d29ffb9c618d87c5e1a02c/kernel/audit.c  (mode:100644)
+++ uncommitted/kernel/audit.c  (mode:100644)
@@ -597,6 +597,47 @@
 	return NULL;
 }
 
+/* Compute a serial number for the audit record.  Audit records are
+ * written to user-space as soon as they are generated, so a complete
+ * audit record may be written in several pieces.  The timestamp of the
+ * record and this serial number are used by the user-space tools to
+ * determine which pieces belong to the same audit record.  The
+ * (timestamp,serial) tuple is unique for each syscall and is live from
+ * syscall entry to syscall exit.
+ *
+ * Atomic values are only guaranteed to be 24-bit, so we count down.
+ *
+ * NOTE: Another possibility is to store the formatted records off the
+ * audit context (for those records that have a context), and emit them
+ * all at syscall exit.  However, this could delay the reporting of
+ * significant errors until syscall exit (or never, if the system
+ * halts). */
+unsigned int audit_serial(void)
+{
+	static atomic_t serial = ATOMIC_INIT(0xffffff);
+	unsigned int a, b;
+
+	do {
+		a = atomic_read(&serial);
+		if (atomic_dec_and_test(&serial))
+			atomic_set(&serial, 0xffffff);
+		b = atomic_read(&serial);
+	} while (b != a - 1);
+
+	return 0xffffff - b;
+}
+
+static inline void audit_get_stamp(struct audit_context *ctx, 
+				   struct timespec *t, unsigned int *serial)
+{
+	if (ctx)
+		auditsc_get_stamp(ctx, t, serial);
+	else {
+		*t = CURRENT_TIME;
+		*serial = audit_serial();
+	}
+}
+
 /* Obtain an audit buffer.  This routine does locking to obtain the
  * audit buffer, but then no locking is required for calls to
  * audit_log_*format.  If the tsk is a task that is currently in a
@@ -630,10 +671,7 @@
 		return NULL;
 	}
 
-	if (!audit_get_stamp(ab->ctx, &t, &serial)) {
-		t = CURRENT_TIME;
-		serial = 0;
-	}
+	audit_get_stamp(ab->ctx, &t, &serial);
 
 	audit_log_format(ab, "audit(%lu.%03lu:%u): ",
 			 t.tv_sec, t.tv_nsec/1000000, serial);
Index: kernel/auditsc.c
===================================================================
--- 8ab8eef2e8c3629c46d29ffb9c618d87c5e1a02c/kernel/auditsc.c  (mode:100644)
+++ uncommitted/kernel/auditsc.c  (mode:100644)
@@ -795,36 +795,6 @@
 	audit_free_context(context);
 }
 
-/* Compute a serial number for the audit record.  Audit records are
- * written to user-space as soon as they are generated, so a complete
- * audit record may be written in several pieces.  The timestamp of the
- * record and this serial number are used by the user-space tools to
- * determine which pieces belong to the same audit record.  The
- * (timestamp,serial) tuple is unique for each syscall and is live from
- * syscall entry to syscall exit.
- *
- * Atomic values are only guaranteed to be 24-bit, so we count down.
- *
- * NOTE: Another possibility is to store the formatted records off the
- * audit context (for those records that have a context), and emit them
- * all at syscall exit.  However, this could delay the reporting of
- * significant errors until syscall exit (or never, if the system
- * halts). */
-static inline unsigned int audit_serial(void)
-{
-	static atomic_t serial = ATOMIC_INIT(0xffffff);
-	unsigned int a, b;
-
-	do {
-		a = atomic_read(&serial);
-		if (atomic_dec_and_test(&serial))
-			atomic_set(&serial, 0xffffff);
-		b = atomic_read(&serial);
-	} while (b != a - 1);
-
-	return 0xffffff - b;
-}
-
 /* Fill in audit context at syscall entry.  This only happens if the
  * audit context was created when the task was created and the state or
  * filters demand the audit context be built.  If the state from the
@@ -1042,17 +1012,13 @@
 	context->names[idx].rdev = inode->i_rdev;
 }
 
-int audit_get_stamp(struct audit_context *ctx,
-		     struct timespec *t, unsigned int *serial)
+void auditsc_get_stamp(struct audit_context *ctx,
+		       struct timespec *t, unsigned int *serial)
 {
-	if (ctx) {
-		t->tv_sec  = ctx->ctime.tv_sec;
-		t->tv_nsec = ctx->ctime.tv_nsec;
-		*serial    = ctx->serial;
-		ctx->auditable = 1;
-		return 1;
-	}
-	return 0;
+	t->tv_sec  = ctx->ctime.tv_sec;
+	t->tv_nsec = ctx->ctime.tv_nsec;
+	*serial    = ctx->serial;
+	ctx->auditable = 1;
 }
 
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)


-- 
dwmw2




More information about the Linux-audit mailing list