Audit system development
 help / color / mirror / Atom feed
* [PATCH v2 1/3] audit: compact name entries and context fields
@ 2026-11-06 15:03 Christian Göttsche
  2026-11-06 15:03 ` [PATCH v2 2/3] audit: return the collected entry from __audit_inode() Christian Göttsche
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Christian Göttsche @ 2026-11-06 15:03 UTC (permalink / raw)
  To: audit; +Cc: Paul Moore, Eric Paris, Christian Göttsche

From: Christian Göttsche <cgzones@googlemail.com>

Group the inode metadata and the small scalar fields of audit_names to
remove padding, while keeping the pathname next to its length and the
file capability revision next to the file capabilities. Store the
per-name file capability revision in s16: it must represent both the
eight-bit on-disk revision and the -1 AUDIT_INODE_NOEVAL sentinel. Keep
the existing formatter and its unknown-capability output unchanged.

Move name_count ahead of the embedded name slots to remove two alignment
holes, and place personality before the task credential scalars.
Preserve the first int dummy member required by audit_dummy_context(),
all five embedded name slots, and the existing allocation and reference
lifetimes.

On x86_64 with SELinux this reduces audit_context from 928 to 880 bytes,
leaving room for descriptor paths while staying below 1 KiB. On the tested
arm64 configuration without property-bearing LSMs it falls to 872 bytes.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v2:
- keep name next to name_len and fcap_ver next to fcap
- move name_count below the names_list comment
---
 kernel/audit.h | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/kernel/audit.h b/kernel/audit.h
index 7640d2c0fba4..614afa1cfa14 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -77,17 +77,14 @@ struct audit_names {
 
 	struct filename		*name;
 	int			name_len;	/* number of chars to log */
-	bool			hidden;		/* don't log this record */
-
-	u64			ino;
 	dev_t			dev;
-	umode_t			mode;
+	u64			ino;
 	kuid_t			uid;
 	kgid_t			gid;
 	dev_t			rdev;
 	struct lsm_prop		oprop;
-	struct audit_file_caps	fcap;
-	unsigned int		fcap_ver;
+	umode_t			mode;
+	bool			hidden;		/* don't log this record */
 	unsigned char		type;		/* record type */
 	/*
 	 * This was an allocated audit_names and not from the array of
@@ -95,6 +92,8 @@ struct audit_names {
 	 * should be freed on syscall exit.
 	 */
 	bool			should_free;
+	s16			fcap_ver;	/* 8-bit revision, or -1 for NOEVAL */
+	struct audit_file_caps	fcap;
 };
 
 struct audit_proctitle {
@@ -132,8 +131,8 @@ struct audit_context {
 	 * through the preallocated_names array and should only be found/used
 	 * by running the names_list.
 	 */
-	struct audit_names  preallocated_names[AUDIT_NAMES];
 	int		    name_count; /* total records in names_list */
+	struct audit_names  preallocated_names[AUDIT_NAMES];
 	struct list_head    names_list;	/* struct audit_names->list anchor */
 	char		    *filterkey;	/* key for rule that triggered record */
 	struct path	    pwd;
@@ -142,10 +141,10 @@ struct audit_context {
 	struct sockaddr_storage *sockaddr;
 	size_t sockaddr_len;
 	/* Save things to print about task_struct */
+	unsigned long	    personality;
 	pid_t		    ppid;
 	kuid_t		    uid, euid, suid, fsuid;
 	kgid_t		    gid, egid, sgid, fsgid;
-	unsigned long	    personality;
 	int		    arch;
 
 	pid_t		    target_pid;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/3] audit: return the collected entry from __audit_inode()
  2026-11-06 15:03 [PATCH v2 1/3] audit: compact name entries and context fields Christian Göttsche
@ 2026-11-06 15:03 ` Christian Göttsche
  2026-11-06 15:07   ` sashiko-bot
  2026-11-06 15:03 ` [PATCH v2 3/3] audit: retain file paths for descriptor PATH records Christian Göttsche
  2026-11-06 15:09 ` [PATCH v2 1/3] audit: compact name entries and context fields sashiko-bot
  2 siblings, 1 reply; 6+ messages in thread
From: Christian Göttsche @ 2026-11-06 15:03 UTC (permalink / raw)
  To: audit; +Cc: Paul Moore, Eric Paris, Christian Göttsche

From: Christian Göttsche <cgzones@googlemail.com>

Return the selected audit_names entry, or NULL when collection is
skipped or fails, so audit_file() can attach descriptor-specific
information reliably. The existing audit_inode() and
audit_inode_parent_hidden() wrappers ignore the result, and collection
behavior is unchanged.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v2: return the entry from __audit_inode() instead of adding a private
    helper
---
 include/linux/audit.h |  6 ++++--
 kernel/auditsc.c      | 14 +++++++++-----
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 767e349d4834..1f456f954c2e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -35,6 +35,7 @@ struct audit_sig_info {
 
 struct audit_buffer;
 struct audit_context;
+struct audit_names;
 struct inode;
 struct netlink_skb_parms;
 struct path;
@@ -327,8 +328,9 @@ extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
 				  unsigned long a2, unsigned long a3);
 extern void __audit_syscall_exit(int ret_success, long ret_value);
 extern void __audit_getname(struct filename *name);
-extern void __audit_inode(struct filename *name, const struct dentry *dentry,
-				unsigned int flags);
+extern struct audit_names *__audit_inode(struct filename *name,
+					 const struct dentry *dentry,
+					 unsigned int flags);
 extern void __audit_file(const struct file *);
 extern void __audit_inode_child(struct inode *parent,
 				const struct dentry *dentry,
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 552ba9f4fb0a..b740e056cd80 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2242,9 +2242,12 @@ static void audit_copy_inode(struct audit_names *name,
  * @name: name being audited
  * @dentry: dentry being audited
  * @flags: attributes for this particular entry
+ *
+ * Return: the collected entry, or NULL if collection was skipped or failed.
  */
-void __audit_inode(struct filename *name, const struct dentry *dentry,
-		   unsigned int flags)
+struct audit_names *__audit_inode(struct filename *name,
+				  const struct dentry *dentry,
+				  unsigned int flags)
 {
 	struct audit_context *context = audit_context();
 	struct inode *inode = d_backing_inode(dentry);
@@ -2255,7 +2258,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
 	int i;
 
 	if (context->context == AUDIT_CTX_UNUSED)
-		return;
+		return NULL;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(e, list, list) {
@@ -2267,7 +2270,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
 						f->op, f->val)
 			    && e->rule.action == AUDIT_NEVER) {
 				rcu_read_unlock();
-				return;
+				return NULL;
 			}
 		}
 	}
@@ -2321,7 +2324,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
 	/* unable to find an entry with both a matching name and type */
 	n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
 	if (!n)
-		return;
+		return NULL;
 	if (name) {
 		n->name = name;
 		name->refcnt++;
@@ -2339,6 +2342,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
 	}
 	handle_path(dentry);
 	audit_copy_inode(n, dentry, inode, flags & AUDIT_INODE_NOEVAL);
+	return n;
 }
 
 void __audit_file(const struct file *file)
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/3] audit: retain file paths for descriptor PATH records
  2026-11-06 15:03 [PATCH v2 1/3] audit: compact name entries and context fields Christian Göttsche
  2026-11-06 15:03 ` [PATCH v2 2/3] audit: return the collected entry from __audit_inode() Christian Göttsche
@ 2026-11-06 15:03 ` Christian Göttsche
  2026-11-06 15:12   ` sashiko-bot
  2026-11-06 15:09 ` [PATCH v2 1/3] audit: compact name entries and context fields sashiko-bot
  2 siblings, 1 reply; 6+ messages in thread
From: Christian Göttsche @ 2026-11-06 15:03 UTC (permalink / raw)
  To: audit; +Cc: Paul Moore, Eric Paris, Christian Göttsche

From: Christian Göttsche <cgzones@googlemail.com>

fchown() and the other audit_file() callers collect inode metadata but
emit name=(null), even though file->f_path is available.

Retain the path with balanced dentry and mount references, and use the
existing audit_log_d_path() formatter when no filename was collected.
Release the references on context cleanup. Descriptor entries carry no
filename, so they can only be reused by a later lookup that matches the
same inode; keep the retained path then instead of falling back to
name=(null). Filesystem exclusions continue to skip entry creation.

The name reflects d_path() at event emission: concurrent renames and
unlinks can affect it. Original lookup names retain precedence.

This adds sizeof(struct path) to each audit_names. With the preceding
capability and layout changes, audit_context grows from 880 to 960 bytes
on the tested x86_64 SELinux configuration and remains in the 1 KiB
kmalloc class. Other LSM configurations can have different object sizes.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
v2:
- reset fd_path after path_put() in audit_free_names()
- keep fd_path when a later lookup reuses the entry for the same inode,
  instead of dropping it in audit_copy_inode()
- place fd_path ahead of name
- use the entry returned by __audit_inode()
---
 kernel/audit.h   |  1 +
 kernel/auditsc.c | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/kernel/audit.h b/kernel/audit.h
index 614afa1cfa14..476821dbed64 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -75,6 +75,7 @@ struct audit_cap_data {
 struct audit_names {
 	struct list_head	list;		/* audit_context->names_list */
 
+	struct path		fd_path;	/* owned audit_file() fallback */
 	struct filename		*name;
 	int			name_len;	/* number of chars to log */
 	dev_t			dev;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b740e056cd80..31c45f681b13 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -936,6 +936,8 @@ static inline void audit_free_names(struct audit_context *context)
 		list_del(&n->list);
 		if (n->name)
 			putname(n->name);
+		path_put(&n->fd_path);
+		n->fd_path = (struct path) { };
 		if (n->should_free)
 			kfree(n);
 	}
@@ -1531,7 +1533,9 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
 			audit_log_n_untrustedstring(ab, n->name->name,
 						    n->name_len);
 		}
-	} else
+	} else if (n->fd_path.dentry)
+		audit_log_d_path(ab, " name=", &n->fd_path);
+	else
 		audit_log_format(ab, " name=(null)");
 
 	if (n->ino != AUDIT_INO_UNSET)
@@ -2347,7 +2351,15 @@ struct audit_names *__audit_inode(struct filename *name,
 
 void __audit_file(const struct file *file)
 {
-	__audit_inode(NULL, file->f_path.dentry, 0);
+	struct audit_names *n;
+
+	n = __audit_inode(NULL, file->f_path.dentry, 0);
+	if (!n)
+		return;
+
+	/* Resolve at event emission, so renames and unlinks can affect the name. */
+	n->fd_path = file->f_path;
+	path_get(&n->fd_path);
 }
 
 /**
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] audit: return the collected entry from __audit_inode()
  2026-11-06 15:03 ` [PATCH v2 2/3] audit: return the collected entry from __audit_inode() Christian Göttsche
@ 2026-11-06 15:07   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-11-06 15:07 UTC (permalink / raw)
  To: audit

> From: Christian Göttsche <cgzones@googlemail.com>
> 
> Return the selected audit_names entry, or NULL when collection is
> skipped or fails, so audit_file() can attach descriptor-specific
> information reliably. The existing audit_inode() and
> audit_inode_parent_hidden() wrappers ignore the result, and collection
> behavior is unchanged.
> 
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106150342.670199-1-cgoettsche@seltendoof.de?part=2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/3] audit: compact name entries and context fields
  2026-11-06 15:03 [PATCH v2 1/3] audit: compact name entries and context fields Christian Göttsche
  2026-11-06 15:03 ` [PATCH v2 2/3] audit: return the collected entry from __audit_inode() Christian Göttsche
  2026-11-06 15:03 ` [PATCH v2 3/3] audit: retain file paths for descriptor PATH records Christian Göttsche
@ 2026-11-06 15:09 ` sashiko-bot
  2 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-11-06 15:09 UTC (permalink / raw)
  To: audit

> From: Christian Göttsche <cgzones@googlemail.com>
> 
> Group the inode metadata and the small scalar fields of audit_names to
> remove padding, while keeping the pathname next to its length and the
> file capability revision next to the file capabilities. Store the
> per-name file capability revision in s16: it must represent both the
> eight-bit on-disk revision and the -1 AUDIT_INODE_NOEVAL sentinel. Keep
> the existing formatter and its unknown-capability output unchanged.
> 
> Move name_count ahead of the embedded name slots to remove two alignment
> holes, and place personality before the task credential scalars.
> Preserve the first int dummy member required by audit_dummy_context(),
> all five embedded name slots, and the existing allocation and reference
> lifetimes.
> 
> On x86_64 with SELinux this reduces audit_context from 928 to 880 bytes,
> leaving room for descriptor paths while staying below 1 KiB. On the tested
> arm64 configuration without property-bearing LSMs it falls to 872 bytes.
> 
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106150342.670199-1-cgoettsche@seltendoof.de?part=1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 3/3] audit: retain file paths for descriptor PATH records
  2026-11-06 15:03 ` [PATCH v2 3/3] audit: retain file paths for descriptor PATH records Christian Göttsche
@ 2026-11-06 15:12   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-11-06 15:12 UTC (permalink / raw)
  To: audit

> From: Christian Göttsche <cgzones@googlemail.com>
> 
> fchown() and the other audit_file() callers collect inode metadata but
> emit name=(null), even though file->f_path is available.
> 
> Retain the path with balanced dentry and mount references, and use the
> existing audit_log_d_path() formatter when no filename was collected.
> Release the references on context cleanup. Descriptor entries carry no
> filename, so they can only be reused by a later lookup that matches the
> same inode; keep the retained path then instead of falling back to
> name=(null). Filesystem exclusions continue to skip entry creation.
> 
> The name reflects d_path() at event emission: concurrent renames and
> unlinks can affect it. Original lookup names retain precedence.
> 
> This adds sizeof(struct path) to each audit_names. With the preceding
> capability and layout changes, audit_context grows from 880 to 960 bytes
> on the tested x86_64 SELinux configuration and remains in the 1 KiB
> kmalloc class. Other LSM configurations can have different object sizes.
> 
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106150342.670199-1-cgoettsche@seltendoof.de?part=3


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-06 15:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-06 15:03 [PATCH v2 1/3] audit: compact name entries and context fields Christian Göttsche
2026-11-06 15:03 ` [PATCH v2 2/3] audit: return the collected entry from __audit_inode() Christian Göttsche
2026-11-06 15:07   ` sashiko-bot
2026-11-06 15:03 ` [PATCH v2 3/3] audit: retain file paths for descriptor PATH records Christian Göttsche
2026-11-06 15:12   ` sashiko-bot
2026-11-06 15:09 ` [PATCH v2 1/3] audit: compact name entries and context fields sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox