* [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