mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] audit: add CLONE3 auxiliary record to log process cloning
@ 2026-07-24 15:02 Ricardo Robaina
  2026-07-28 16:31 ` Richard Guy Briggs
  2026-07-29 22:02 ` Paul Moore
  0 siblings, 2 replies; 4+ messages in thread
From: Ricardo Robaina @ 2026-07-24 15:02 UTC (permalink / raw)
  To: audit, linux-mm, linux-kernel
  Cc: paul, eparis, sgrubb, kees, mingo, peterz, juri.lelli,
	vincent.guittot, akpm, david, brauner, Ricardo Robaina

The clone3(2) syscall moves most parameters to struct clone_args.
For this reason, the generic SYSCALL audit record does not capture
the structured arguments.

Add a CLONE3 auxiliary record that logs: flags, exit_signal, cgroup,
and pidfd fields from struct clone_args. When CLONE_PIDFD is set and
the syscall succeeds, the resolved pidfd is logged; otherwise
pidfd=(null).

 ----
 type=SYSCALL : syscall=clone3 a0=0x7ffe7f1ec640 a1=0x58 a2=0x0 ...
 type=CLONE3 : cl3_flags=0x1000 exit_signal=17 cgroup=0 pidfd=3

Link: https://github.com/linux-audit/audit-kernel/issues/151
Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
---
 include/linux/audit.h      | 10 ++++++++++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c           | 20 ++++++++++++++++++++
 kernel/fork.c              |  4 +++-
 4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 45abb3722d30..833f349bf415 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -449,6 +449,7 @@ extern void __audit_tk_injoffset(struct timespec64 offset);
 extern void __audit_ntp_log(const struct audit_ntp_data *ad);
 extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
 			      enum audit_nfcfgop op, gfp_t gfp);
+extern void __audit_log_clone3(struct kernel_clone_args *kargs, int ret);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -598,6 +599,12 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
 		__audit_log_nfcfg(name, af, nentries, op, gfp);
 }
 
+static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
+{
+	if (!audit_dummy_context())
+		__audit_log_clone3(kargs, ret);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -730,6 +737,9 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
 				   enum audit_nfcfgop op, gfp_t gfp)
 { }
 
+static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
+{ }
+
 #define audit_n_rules 0
 #define audit_signals 0
 #endif /* CONFIG_AUDITSYSCALL */
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index e8f5ce677df7..37357e17adbf 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -122,6 +122,7 @@
 #define AUDIT_OPENAT2		1337	/* Record showing openat2 how args */
 #define AUDIT_DM_CTRL		1338	/* Device Mapper target control */
 #define AUDIT_DM_EVENT		1339	/* Device Mapper events */
+#define AUDIT_CLONE3		1343	/* Record showing clone3 args */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 6610e667c728..c0106bb71c19 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2882,6 +2882,26 @@ void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
 }
 EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
 
+void __audit_log_clone3(struct kernel_clone_args *kargs, int ret)
+{
+	struct audit_buffer *ab;
+	int pidfd;
+
+	ab = audit_log_start(audit_context(), GFP_KERNEL,
+			     AUDIT_CLONE3);
+	if (!ab)
+		return;
+
+	audit_log_format(ab, "cl3_flags=0x%llx exit_signal=%d cgroup=%d",
+			 kargs->flags, kargs->exit_signal, kargs->cgroup);
+	if ((kargs->flags & CLONE_PIDFD) && ret >= 0 &&
+	    !get_user(pidfd, kargs->pidfd))
+		audit_log_format(ab, " pidfd=%d", pidfd);
+	else
+		audit_log_format(ab, " pidfd=(null)");
+	audit_log_end(ab);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
 	kuid_t auid, uid;
diff --git a/kernel/fork.c b/kernel/fork.c
index f0e2e131a9a5..0f52e8c0e900 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -3047,7 +3047,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size)
 	if (!clone3_args_valid(&kargs))
 		return -EINVAL;
 
-	return kernel_clone(&kargs);
+	err = kernel_clone(&kargs);
+	audit_log_clone3(&kargs, err);
+	return err;
 }
 
 void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data)
-- 
2.53.0


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

* Re: [PATCH] audit: add CLONE3 auxiliary record to log process cloning
  2026-07-24 15:02 [PATCH] audit: add CLONE3 auxiliary record to log process cloning Ricardo Robaina
@ 2026-07-28 16:31 ` Richard Guy Briggs
  2026-07-28 21:01   ` Steve Grubb
  2026-07-29 22:02 ` Paul Moore
  1 sibling, 1 reply; 4+ messages in thread
From: Richard Guy Briggs @ 2026-07-28 16:31 UTC (permalink / raw)
  To: Ricardo Robaina
  Cc: audit, linux-mm, linux-kernel, paul, eparis, sgrubb, kees, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, david, brauner

On 2026-07-24 12:02, Ricardo Robaina wrote:
> The clone3(2) syscall moves most parameters to struct clone_args.
> For this reason, the generic SYSCALL audit record does not capture
> the structured arguments.
> 
> Add a CLONE3 auxiliary record that logs: flags, exit_signal, cgroup,
> and pidfd fields from struct clone_args. When CLONE_PIDFD is set and
> the syscall succeeds, the resolved pidfd is logged; otherwise
> pidfd=(null).
> 
>  ----
>  type=SYSCALL : syscall=clone3 a0=0x7ffe7f1ec640 a1=0x58 a2=0x0 ...
>  type=CLONE3 : cl3_flags=0x1000 exit_signal=17 cgroup=0 pidfd=3
> 
> Link: https://github.com/linux-audit/audit-kernel/issues/151
> Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
> ---
>  include/linux/audit.h      | 10 ++++++++++
>  include/uapi/linux/audit.h |  1 +
>  kernel/auditsc.c           | 20 ++++++++++++++++++++
>  kernel/fork.c              |  4 +++-
>  4 files changed, 34 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 45abb3722d30..833f349bf415 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -449,6 +449,7 @@ extern void __audit_tk_injoffset(struct timespec64 offset);
>  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
>  extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
>  			      enum audit_nfcfgop op, gfp_t gfp);
> +extern void __audit_log_clone3(struct kernel_clone_args *kargs, int ret);
>  
>  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
>  {
> @@ -598,6 +599,12 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
>  		__audit_log_nfcfg(name, af, nentries, op, gfp);
>  }
>  
> +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{
> +	if (!audit_dummy_context())
> +		__audit_log_clone3(kargs, ret);
> +}
> +
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> @@ -730,6 +737,9 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
>  				   enum audit_nfcfgop op, gfp_t gfp)
>  { }
>  
> +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{ }
> +
>  #define audit_n_rules 0
>  #define audit_signals 0
>  #endif /* CONFIG_AUDITSYSCALL */
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index e8f5ce677df7..37357e17adbf 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -122,6 +122,7 @@
>  #define AUDIT_OPENAT2		1337	/* Record showing openat2 how args */
>  #define AUDIT_DM_CTRL		1338	/* Device Mapper target control */
>  #define AUDIT_DM_EVENT		1339	/* Device Mapper events */
> +#define AUDIT_CLONE3		1343	/* Record showing clone3 args */
>  
>  #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
>  #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 6610e667c728..c0106bb71c19 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -2882,6 +2882,26 @@ void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
>  }
>  EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
>  
> +void __audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{
> +	struct audit_buffer *ab;
> +	int pidfd;
> +
> +	ab = audit_log_start(audit_context(), GFP_KERNEL,
> +			     AUDIT_CLONE3);
> +	if (!ab)
> +		return;
> +
> +	audit_log_format(ab, "cl3_flags=0x%llx exit_signal=%d cgroup=%d",
> +			 kargs->flags, kargs->exit_signal, kargs->cgroup);

Would there be any confusion if this were simply "flags=..." since it is
already a record type AUDIT_CLONE3?

> +	if ((kargs->flags & CLONE_PIDFD) && ret >= 0 &&
> +	    !get_user(pidfd, kargs->pidfd))
> +		audit_log_format(ab, " pidfd=%d", pidfd);
> +	else
> +		audit_log_format(ab, " pidfd=(null)");

Is there any interest in:
	child_tid (was captured by generic audit syscall arg 4)
	parent_tid (was captured by generic audit syscall arg 3 or 4)
	tls (was captured by generic audit syscall arg 4)
	set_tid

Is there a situation where a valid pid is returned without CLONE_PIDFD set?

Otherwise, looks reasonable to me.

> +	audit_log_end(ab);
> +}
> +
>  static void audit_log_task(struct audit_buffer *ab)
>  {
>  	kuid_t auid, uid;
> diff --git a/kernel/fork.c b/kernel/fork.c
> index f0e2e131a9a5..0f52e8c0e900 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -3047,7 +3047,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size)
>  	if (!clone3_args_valid(&kargs))
>  		return -EINVAL;
>  
> -	return kernel_clone(&kargs);
> +	err = kernel_clone(&kargs);
> +	audit_log_clone3(&kargs, err);
> +	return err;
>  }
>  
>  void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data)
> -- 
> 2.53.0

- RGB

--
Richard Guy Briggs <rgb@redhat.com>
Sr. S/W Engineer, Kernel Security, Base Operating Systems
Remote, Ottawa, Red Hat Canada
Upstream IRC: SunRaycer
Voice: +1.613.860 2354 SMS: +1.613.518.6570


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

* Re: [PATCH] audit: add CLONE3 auxiliary record to log process cloning
  2026-07-28 16:31 ` Richard Guy Briggs
@ 2026-07-28 21:01   ` Steve Grubb
  0 siblings, 0 replies; 4+ messages in thread
From: Steve Grubb @ 2026-07-28 21:01 UTC (permalink / raw)
  To: Ricardo Robaina, Richard Guy Briggs
  Cc: audit, linux-mm, linux-kernel, paul, eparis, kees, mingo, peterz,
	juri.lelli, vincent.guittot, akpm, david, brauner

On Tuesday, July 28, 2026 12:31:02 PM Eastern Daylight Time Richard Guy 
Briggs wrote:
> On 2026-07-24 12:02, Ricardo Robaina wrote:
> > The clone3(2) syscall moves most parameters to struct clone_args.
> > For this reason, the generic SYSCALL audit record does not capture
> > the structured arguments.
> > 
> > Add a CLONE3 auxiliary record that logs: flags, exit_signal, cgroup,
> > and pidfd fields from struct clone_args. When CLONE_PIDFD is set and
> > the syscall succeeds, the resolved pidfd is logged; otherwise
> > pidfd=(null).
> > 
> >  ----
> >  type=SYSCALL : syscall=clone3 a0=0x7ffe7f1ec640 a1=0x58 a2=0x0 ...
> >  type=CLONE3 : cl3_flags=0x1000 exit_signal=17 cgroup=0 pidfd=3
> > 
> > Link: https://github.com/linux-audit/audit-kernel/issues/151
> > Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
> > ---
> > 
> >  include/linux/audit.h      | 10 ++++++++++
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/auditsc.c           | 20 ++++++++++++++++++++
> >  kernel/fork.c              |  4 +++-
> >  4 files changed, 34 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 45abb3722d30..833f349bf415 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -449,6 +449,7 @@ extern void __audit_tk_injoffset(struct timespec64
> > offset);> 
> >  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
> >  extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int
> >  nentries,>  
> >  			      enum audit_nfcfgop op, gfp_t gfp);
> > 
> > +extern void __audit_log_clone3(struct kernel_clone_args *kargs, int
> > ret);
> > 
> >  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> >  {
> > 
> > @@ -598,6 +599,12 @@ static inline void audit_log_nfcfg(const char *name,
> > u8 af,> 
> >  		__audit_log_nfcfg(name, af, nentries, op, gfp);
> >  
> >  }
> > 
> > +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int
> > ret) +{
> > +	if (!audit_dummy_context())
> > +		__audit_log_clone3(kargs, ret);
> > +}
> > +
> > 
> >  extern int audit_n_rules;
> >  extern int audit_signals;
> >  #else /* CONFIG_AUDITSYSCALL */
> > 
> > @@ -730,6 +737,9 @@ static inline void audit_log_nfcfg(const char *name,
> > u8 af,> 
> >  				   enum audit_nfcfgop op, gfp_t gfp)
> >  
> >  { }
> > 
> > +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int
> > ret) +{ }
> > +
> > 
> >  #define audit_n_rules 0
> >  #define audit_signals 0
> >  #endif /* CONFIG_AUDITSYSCALL */
> > 
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index e8f5ce677df7..37357e17adbf 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -122,6 +122,7 @@
> > 
> >  #define AUDIT_OPENAT2		1337	/* Record showing openat2 how args 
*/
> >  #define AUDIT_DM_CTRL		1338	/* Device Mapper target control */
> >  #define AUDIT_DM_EVENT		1339	/* Device Mapper events */
> > 
> > +#define AUDIT_CLONE3		1343	/* Record showing clone3 args */
> > 
> >  #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
> >  #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
> > 
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 6610e667c728..c0106bb71c19 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -2882,6 +2882,26 @@ void __audit_log_nfcfg(const char *name, u8 af,
> > unsigned int nentries,> 
> >  }
> >  EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
> > 
> > +void __audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> > +{
> > +	struct audit_buffer *ab;
> > +	int pidfd;
> > +
> > +	ab = audit_log_start(audit_context(), GFP_KERNEL,
> > +			     AUDIT_CLONE3);
> > +	if (!ab)
> > +		return;
> > +
> > +	audit_log_format(ab, "cl3_flags=0x%llx exit_signal=%d cgroup=%d",
> > +			 kargs->flags, kargs->exit_signal, kargs->cgroup);
> 
> Would there be any confusion if this were simply "flags=..." since it is
> already a record type AUDIT_CLONE3?

flags is already used in mmap records and will require workarounds to have 
the same field name here. Separating them by name is better.

> > +	if ((kargs->flags & CLONE_PIDFD) && ret >= 0 &&
> > +	    !get_user(pidfd, kargs->pidfd))
> > +		audit_log_format(ab, " pidfd=%d", pidfd);
> > +	else
> > +		audit_log_format(ab, " pidfd=(null)");
> 
> Is there any interest in:
> 	child_tid (was captured by generic audit syscall arg 4)
> 	parent_tid (was captured by generic audit syscall arg 3 or 4)
> 	tls (was captured by generic audit syscall arg 4)
> 	set_tid

Nope. Those are more resource related and not security focused. Even if you 
wanted it, these are pointers to the answer and not the answer. The patch has 
everything needed from a security PoV.

Ack.

> Is there a situation where a valid pid is returned without CLONE_PIDFD set?

No idea. The man page makes it sound like it is only valid when CLONE_PIDFD. 
Besides, its a pointer to an int from what the man page said.

-Steve

> Otherwise, looks reasonable to me.
> 
> > +	audit_log_end(ab);
> > +}
> > +
> > 
> >  static void audit_log_task(struct audit_buffer *ab)
> >  {
> >  
> >  	kuid_t auid, uid;
> > 
> > diff --git a/kernel/fork.c b/kernel/fork.c
> > index f0e2e131a9a5..0f52e8c0e900 100644
> > --- a/kernel/fork.c
> > +++ b/kernel/fork.c
> > @@ -3047,7 +3047,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *,
> > uargs, size_t, size)> 
> >  	if (!clone3_args_valid(&kargs))
> >  	
> >  		return -EINVAL;
> > 
> > -	return kernel_clone(&kargs);
> > +	err = kernel_clone(&kargs);
> > +	audit_log_clone3(&kargs, err);
> > +	return err;
> > 
> >  }
> >  
> >  void walk_process_tree(struct task_struct *top, proc_visitor visitor,
> >  void *data)
> - RGB
> 
> --
> Richard Guy Briggs <rgb@redhat.com>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> Upstream IRC: SunRaycer
> Voice: +1.613.860 2354 SMS: +1.613.518.6570





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

* Re: [PATCH] audit: add CLONE3 auxiliary record to log process cloning
  2026-07-24 15:02 [PATCH] audit: add CLONE3 auxiliary record to log process cloning Ricardo Robaina
  2026-07-28 16:31 ` Richard Guy Briggs
@ 2026-07-29 22:02 ` Paul Moore
  1 sibling, 0 replies; 4+ messages in thread
From: Paul Moore @ 2026-07-29 22:02 UTC (permalink / raw)
  To: Ricardo Robaina
  Cc: audit, linux-mm, linux-kernel, eparis, sgrubb, kees, mingo,
	peterz, juri.lelli, vincent.guittot, akpm, david, brauner

On Fri, Jul 24, 2026 at 11:03 AM Ricardo Robaina <rrobaina@redhat.com> wrote:
>
> The clone3(2) syscall moves most parameters to struct clone_args.
> For this reason, the generic SYSCALL audit record does not capture
> the structured arguments.
>
> Add a CLONE3 auxiliary record that logs: flags, exit_signal, cgroup,
> and pidfd fields from struct clone_args. When CLONE_PIDFD is set and
> the syscall succeeds, the resolved pidfd is logged; otherwise
> pidfd=(null).
>
>  ----
>  type=SYSCALL : syscall=clone3 a0=0x7ffe7f1ec640 a1=0x58 a2=0x0 ...
>  type=CLONE3 : cl3_flags=0x1000 exit_signal=17 cgroup=0 pidfd=3
>
> Link: https://github.com/linux-audit/audit-kernel/issues/151
> Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
> ---
>  include/linux/audit.h      | 10 ++++++++++
>  include/uapi/linux/audit.h |  1 +
>  kernel/auditsc.c           | 20 ++++++++++++++++++++
>  kernel/fork.c              |  4 +++-
>  4 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 45abb3722d30..833f349bf415 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -449,6 +449,7 @@ extern void __audit_tk_injoffset(struct timespec64 offset);
>  extern void __audit_ntp_log(const struct audit_ntp_data *ad);
>  extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
>                               enum audit_nfcfgop op, gfp_t gfp);
> +extern void __audit_log_clone3(struct kernel_clone_args *kargs, int ret);
>
>  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
>  {
> @@ -598,6 +599,12 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
>                 __audit_log_nfcfg(name, af, nentries, op, gfp);
>  }
>
> +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{
> +       if (!audit_dummy_context())
> +               __audit_log_clone3(kargs, ret);
> +}
> +
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> @@ -730,6 +737,9 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
>                                    enum audit_nfcfgop op, gfp_t gfp)
>  { }
>
> +static inline void audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{ }
> +
>  #define audit_n_rules 0
>  #define audit_signals 0
>  #endif /* CONFIG_AUDITSYSCALL */
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index e8f5ce677df7..37357e17adbf 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -122,6 +122,7 @@
>  #define AUDIT_OPENAT2          1337    /* Record showing openat2 how args */
>  #define AUDIT_DM_CTRL          1338    /* Device Mapper target control */
>  #define AUDIT_DM_EVENT         1339    /* Device Mapper events */
> +#define AUDIT_CLONE3           1343    /* Record showing clone3 args */
>
>  #define AUDIT_AVC              1400    /* SE Linux avc denial or grant */
>  #define AUDIT_SELINUX_ERR      1401    /* Internal SE Linux Errors */
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 6610e667c728..c0106bb71c19 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -2882,6 +2882,26 @@ void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
>  }
>  EXPORT_SYMBOL_GPL(__audit_log_nfcfg);
>
> +void __audit_log_clone3(struct kernel_clone_args *kargs, int ret)
> +{
> +       struct audit_buffer *ab;
> +       int pidfd;
> +
> +       ab = audit_log_start(audit_context(), GFP_KERNEL,
> +                            AUDIT_CLONE3);
> +       if (!ab)
> +               return;
> +
> +       audit_log_format(ab, "cl3_flags=0x%llx exit_signal=%d cgroup=%d",
> +                        kargs->flags, kargs->exit_signal, kargs->cgroup);
> +       if ((kargs->flags & CLONE_PIDFD) && ret >= 0 &&
> +           !get_user(pidfd, kargs->pidfd))
> +               audit_log_format(ab, " pidfd=%d", pidfd);

Do we care about distinguishing between the combination of CLONE_PIDFD
and CLONE_THREAD vs CLONE_PIDFD alone?  In other words, do we care if
the "pidfd" field sometimes represents a pidfd of the child process vs
a thread in the current process?

> +       else
> +               audit_log_format(ab, " pidfd=(null)");
> +       audit_log_end(ab);
> +}
> +
>  static void audit_log_task(struct audit_buffer *ab)
>  {
>         kuid_t auid, uid;
> diff --git a/kernel/fork.c b/kernel/fork.c
> index f0e2e131a9a5..0f52e8c0e900 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -3047,7 +3047,9 @@ SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size)
>         if (!clone3_args_valid(&kargs))
>                 return -EINVAL;
>
> -       return kernel_clone(&kargs);
> +       err = kernel_clone(&kargs);
> +       audit_log_clone3(&kargs, err);
> +       return err;
>  }
>
>  void walk_process_tree(struct task_struct *top, proc_visitor visitor, void *data)
> --
> 2.53.0

-- 
paul-moore.com

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

end of thread, other threads:[~2026-07-29 22:03 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-24 15:02 [PATCH] audit: add CLONE3 auxiliary record to log process cloning Ricardo Robaina
2026-07-28 16:31 ` Richard Guy Briggs
2026-07-28 21:01   ` Steve Grubb
2026-07-29 22:02 ` Paul Moore

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

all inboxes | Powered by JetHome®