[PATCH] rseq: fix using an uninitialized stack variable in rseq_exit_user_update

Qing Wang posted 1 patch 1 week ago
There is a newer version of this series
include/linux/rseq_entry.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Qing Wang 1 week ago
There is an bug which is an uninitialized stack variable use in
`rseq_exit_user_update()` reported by syzbot:

BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]

The local variable:
```c
	struct rseq_ids ids = {
		.cpu_id	 = task_cpu(t),
		.mm_cid	 = task_mm_cid(t),
		.node_id = cpu_to_node(ids.cpu_id),
	};
```
According to the C standard, the evaluation order of expressions in an
initializer list is indeterminately sequenced. The compiler (Clang, in this
KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before* `ids.cpu_id` is
initialized with `task_cpu(t)`.

This is fixed by moving the assignment of ids.node_id outside the structure
initialization.

Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
Signed-off-by: Qing Wang <wangqing7171@gmail.com>
---
 include/linux/rseq_entry.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 63bc72086e75..e05f4c18f39e 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -638,8 +638,8 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
 	struct rseq_ids ids = {
 		.cpu_id	 = task_cpu(t),
 		.mm_cid	 = task_mm_cid(t),
-		.node_id = cpu_to_node(ids.cpu_id),
 	};
+	ids.node_id = cpu_to_node(ids.cpu_id);
 
 	return rseq_update_usr(t, regs, &ids);
 efault:
-- 
2.34.1
Re: [PATCH] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Mathieu Desnoyers 6 days, 16 hours ago
On 2026-05-31 22:13, Qing Wang wrote:
> There is an bug which is an uninitialized stack variable use in
> `rseq_exit_user_update()` reported by syzbot:
> 
> BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]
> 
> The local variable:
> ```c
> 	struct rseq_ids ids = {
> 		.cpu_id	 = task_cpu(t),
> 		.mm_cid	 = task_mm_cid(t),
> 		.node_id = cpu_to_node(ids.cpu_id),
> 	};
> ```
> According to the C standard, the evaluation order of expressions in an
> initializer list is indeterminately sequenced. The compiler (Clang, in this
> KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before* `ids.cpu_id` is
> initialized with `task_cpu(t)`.
> 
> This is fixed by moving the assignment of ids.node_id outside the structure
> initialization.
> 
> Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
> Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
> Signed-off-by: Qing Wang <wangqing7171@gmail.com>
> ---
>   include/linux/rseq_entry.h | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
> index 63bc72086e75..e05f4c18f39e 100644
> --- a/include/linux/rseq_entry.h
> +++ b/include/linux/rseq_entry.h
> @@ -638,8 +638,8 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
>   	struct rseq_ids ids = {
>   		.cpu_id	 = task_cpu(t),
>   		.mm_cid	 = task_mm_cid(t),
> -		.node_id = cpu_to_node(ids.cpu_id),
>   	};
> +	ids.node_id = cpu_to_node(ids.cpu_id);

I find the fix odd. How about:

int cpu = task_cpu(t);
struct rseq_ids ids = {
	.cpu_id = cpu,
	.mm_cid = task_mm_cid(t),
	.node_id = cpu_to_node(cpu),
};

instead ?

Thanks,

Mathieu

>   
>   	return rseq_update_usr(t, regs, &ids);
>   efault:


-- 
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
Re: [PATCH] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Peter Zijlstra 6 days, 15 hours ago
On Mon, Jun 01, 2026 at 09:59:35AM -0400, Mathieu Desnoyers wrote:
> On 2026-05-31 22:13, Qing Wang wrote:
> > There is an bug which is an uninitialized stack variable use in
> > `rseq_exit_user_update()` reported by syzbot:
> > 
> > BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]
> > 
> > The local variable:
> > ```c
> > 	struct rseq_ids ids = {
> > 		.cpu_id	 = task_cpu(t),
> > 		.mm_cid	 = task_mm_cid(t),
> > 		.node_id = cpu_to_node(ids.cpu_id),
> > 	};
> > ```
> > According to the C standard, the evaluation order of expressions in an
> > initializer list is indeterminately sequenced. The compiler (Clang, in this
> > KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before* `ids.cpu_id` is
> > initialized with `task_cpu(t)`.

W.T.F. would they (C committee) do that :-(, and since this is
apparently a known thing, why aren't the compilers issuing WARNs about
this pattern?

Clearly any non address-of self reference in a struct initializer is
buggered.

And ideally it would actually observe the data-dependency and respect
it, irrespective of the lunacy of the C standard.

> > This is fixed by moving the assignment of ids.node_id outside the structure
> > initialization.
> > 
> > Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
> > Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
> > Signed-off-by: Qing Wang <wangqing7171@gmail.com>
> > ---
> >   include/linux/rseq_entry.h | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
> > index 63bc72086e75..e05f4c18f39e 100644
> > --- a/include/linux/rseq_entry.h
> > +++ b/include/linux/rseq_entry.h
> > @@ -638,8 +638,8 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
> >   	struct rseq_ids ids = {
> >   		.cpu_id	 = task_cpu(t),
> >   		.mm_cid	 = task_mm_cid(t),
> > -		.node_id = cpu_to_node(ids.cpu_id),
> >   	};
> > +	ids.node_id = cpu_to_node(ids.cpu_id);
> 
> I find the fix odd. How about:
> 
> int cpu = task_cpu(t);
> struct rseq_ids ids = {
> 	.cpu_id = cpu,
> 	.mm_cid = task_mm_cid(t),
> 	.node_id = cpu_to_node(cpu),
> };
> 
> instead ?

Yes, much saner.
[PATCH v2] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Qing Wang 6 days, 3 hours ago
There is an bug which is an uninitialized stack variable use in
`rseq_exit_user_update()` reported by syzbot:

BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]

The local variable:
```c
	struct rseq_ids ids = {
		.cpu_id	 = task_cpu(t),
		.mm_cid	 = task_mm_cid(t),
		.node_id = cpu_to_node(ids.cpu_id),
	};
```
According to the C standard, the evaluation order of expressions in an
initializer list is indeterminately sequenced. The compiler (Clang, in this
KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before* `ids.cpu_id` is
initialized with `task_cpu(t)`.

This is fixed by moving the assignment of ids.node_id outside the structure
initialization.

Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
Signed-off-by: Qing Wang <wangqing7171@gmail.com>
---
 include/linux/rseq_entry.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 63bc72086e75..ed9da6e41a2a 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -635,10 +635,11 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
 		return true;
 	}
 
+	int cpu = task_cpu(t);
 	struct rseq_ids ids = {
-		.cpu_id	 = task_cpu(t),
+		.cpu_id	 = cpu,
 		.mm_cid	 = task_mm_cid(t),
-		.node_id = cpu_to_node(ids.cpu_id),
+		.node_id = cpu_to_node(cpu),
 	};
 
 	return rseq_update_usr(t, regs, &ids);
-- 
2.34.1
Re: [PATCH v2] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Peter Zijlstra 5 days, 19 hours ago
On Tue, Jun 02, 2026 at 11:08:54AM +0800, Qing Wang wrote:
> There is an bug which is an uninitialized stack variable use in
> `rseq_exit_user_update()` reported by syzbot:
> 
> BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]
> 
> The local variable:
> ```c
> 	struct rseq_ids ids = {
> 		.cpu_id	 = task_cpu(t),
> 		.mm_cid	 = task_mm_cid(t),
> 		.node_id = cpu_to_node(ids.cpu_id),
> 	};
> ```

FWIW, I've no idea what that ``` nonsense is, but it does not belong in
Changelogs. I've removed it.
Re: [PATCH v2] rseq: fix using an uninitialized stack variable in rseq_exit_user_update
Posted by Mark Rutland 5 days, 20 hours ago
On Tue, Jun 02, 2026 at 11:08:54AM +0800, Qing Wang wrote:
> There is an bug which is an uninitialized stack variable use in
> `rseq_exit_user_update()` reported by syzbot:
> 
> BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]
> 
> The local variable:
> ```c
> 	struct rseq_ids ids = {
> 		.cpu_id	 = task_cpu(t),
> 		.mm_cid	 = task_mm_cid(t),
> 		.node_id = cpu_to_node(ids.cpu_id),
> 	};
> ```
> According to the C standard, the evaluation order of expressions in an
> initializer list is indeterminately sequenced. The compiler (Clang, in this
> KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before* `ids.cpu_id` is
> initialized with `task_cpu(t)`.
> 
> This is fixed by moving the assignment of ids.node_id outside the structure
> initialization.
> 
> Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
> Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
> Signed-off-by: Qing Wang <wangqing7171@gmail.com>

FWIW, this looks sane to me, so:

Acked-by: Mark Rutland <mark.rutland@arm.com>

Mark.

> ---
>  include/linux/rseq_entry.h | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
> index 63bc72086e75..ed9da6e41a2a 100644
> --- a/include/linux/rseq_entry.h
> +++ b/include/linux/rseq_entry.h
> @@ -635,10 +635,11 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
>  		return true;
>  	}
>  
> +	int cpu = task_cpu(t);
>  	struct rseq_ids ids = {
> -		.cpu_id	 = task_cpu(t),
> +		.cpu_id	 = cpu,
>  		.mm_cid	 = task_mm_cid(t),
> -		.node_id = cpu_to_node(ids.cpu_id),
> +		.node_id = cpu_to_node(cpu),
>  	};
>  
>  	return rseq_update_usr(t, regs, &ids);
> -- 
> 2.34.1
>
[tip: sched/urgent] rseq: Fix using an uninitialized stack variable in rseq_exit_user_update()
Posted by tip-bot2 for Qing Wang 5 days, 19 hours ago
The following commit has been merged into the sched/urgent branch of tip:

Commit-ID:     6d99479799c69c3cb588fcda19c81d8f61d64ecd
Gitweb:        https://git.kernel.org/tip/6d99479799c69c3cb588fcda19c81d8f61d64ecd
Author:        Qing Wang <wangqing7171@gmail.com>
AuthorDate:    Tue, 02 Jun 2026 11:08:54 +08:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Tue, 02 Jun 2026 12:41:15 +02:00

rseq: Fix using an uninitialized stack variable in rseq_exit_user_update()

There is an bug in which an uninitialized stack variable is used in
rseq_exit_user_update() as reported by syzbot:

BUG: KMSAN: kernel-infoleak in rseq_set_ids_get_csaddr include/linux/rseq_entry.h:502 [inline]

The local variable:

	struct rseq_ids ids = {
		.cpu_id	 = task_cpu(t),
		.mm_cid	 = task_mm_cid(t),
		.node_id = cpu_to_node(ids.cpu_id),
	};

According to the C standard, the evaluation order of expressions in an
initializer list is indeterminately sequenced. The compiler (Clang, in
this KMSAN build) evaluates `cpu_to_node(ids.cpu_id)` *before*
`ids.cpu_id` is initialized with `task_cpu(t)`.

This is fixed by moving the assignment of ids.node_id outside the
structure initialization.

Fixes: 82f572449cfe ("rseq: Implement read only ABI enforcement for optimized RSEQ V2 mode")
Closes: https://syzkaller.appspot.com/bug?extid=185a631927096f9da2fc
Reported-by: syzbot+185a631927096f9da2fc@syzkaller.appspotmail.com
Signed-off-by: Qing Wang <wangqing7171@gmail.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Link: https://patch.msgid.link/20260602030854.574038-1-wangqing7171@gmail.com
---
 include/linux/rseq_entry.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 63bc720..ed9da6e 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -635,10 +635,11 @@ static __always_inline bool rseq_exit_user_update(struct pt_regs *regs, struct t
 		return true;
 	}
 
+	int cpu = task_cpu(t);
 	struct rseq_ids ids = {
-		.cpu_id	 = task_cpu(t),
+		.cpu_id	 = cpu,
 		.mm_cid	 = task_mm_cid(t),
-		.node_id = cpu_to_node(ids.cpu_id),
+		.node_id = cpu_to_node(cpu),
 	};
 
 	return rseq_update_usr(t, regs, &ids);