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