public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc()
@ 2024-07-02 16:04 Shigeru Yoshida
  2024-07-02 16:04 ` [PATCH net 2/2] selftest: af_unix: Add test case for backtrack after finalising SCC Shigeru Yoshida
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Shigeru Yoshida @ 2024-07-02 16:04 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni
  Cc: kuniyu, netdev, linux-kernel, Shigeru Yoshida, syzkaller

KMSAN reported uninit-value access in __unix_walk_scc() [1].

In the list_for_each_entry_reverse() loop, when the vertex's index
equals it's scc_index, the loop uses the variable vertex as a
temporary variable that points to a vertex in scc. And when the loop
is finished, the variable vertex points to the list head, in this case
scc, which is a local variable on the stack (more precisely, it's not
even scc and might underflow the call stack of __unix_walk_scc():
container_of(&scc, struct unix_vertex, scc_entry)).

However, the variable vertex is used under the label prev_vertex. So
if the edge_stack is not empty and the function jumps to the
prev_vertex label, the function will access invalid data on the
stack. This causes the uninit-value access issue.

Fix this by introducing a new temporary variable for the loop.

[1]
BUG: KMSAN: uninit-value in __unix_walk_scc net/unix/garbage.c:478 [inline]
BUG: KMSAN: uninit-value in unix_walk_scc net/unix/garbage.c:526 [inline]
BUG: KMSAN: uninit-value in __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
 __unix_walk_scc net/unix/garbage.c:478 [inline]
 unix_walk_scc net/unix/garbage.c:526 [inline]
 __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
 process_one_work kernel/workqueue.c:3231 [inline]
 process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
 worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
 kthread+0x3c4/0x530 kernel/kthread.c:389
 ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Uninit was stored to memory at:
 unix_walk_scc net/unix/garbage.c:526 [inline]
 __unix_gc+0x2adf/0x3c20 net/unix/garbage.c:584
 process_one_work kernel/workqueue.c:3231 [inline]
 process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
 worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
 kthread+0x3c4/0x530 kernel/kthread.c:389
 ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Local variable entries created at:
 ref_tracker_free+0x48/0xf30 lib/ref_tracker.c:222
 netdev_tracker_free include/linux/netdevice.h:4058 [inline]
 netdev_put include/linux/netdevice.h:4075 [inline]
 dev_put include/linux/netdevice.h:4101 [inline]
 update_gid_event_work_handler+0xaa/0x1b0 drivers/infiniband/core/roce_gid_mgmt.c:813

CPU: 1 PID: 12763 Comm: kworker/u8:31 Not tainted 6.10.0-rc4-00217-g35bb670d65fc #32
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
Workqueue: events_unbound __unix_gc

Fixes: 3484f063172d ("af_unix: Detect Strongly Connected Components.")
Reported-by: syzkaller <syzkaller@googlegroups.com>
Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>
---
v1->v2: https://lore.kernel.org/all/20240625152713.1147650-1-syoshida@redhat.com/
- A bit of elaboration on the commit message, as suggested by Iwashima-san.
- Bundle a selftest written by Iwashima-san.
---
 net/unix/garbage.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index dfe94a90ece4..23efb78fe9ef 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -476,6 +476,7 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde
 	}
 
 	if (vertex->index == vertex->scc_index) {
+		struct unix_vertex *v;
 		struct list_head scc;
 		bool scc_dead = true;
 
@@ -486,15 +487,15 @@ static void __unix_walk_scc(struct unix_vertex *vertex, unsigned long *last_inde
 		 */
 		__list_cut_position(&scc, &vertex_stack, &vertex->scc_entry);
 
-		list_for_each_entry_reverse(vertex, &scc, scc_entry) {
+		list_for_each_entry_reverse(v, &scc, scc_entry) {
 			/* Don't restart DFS from this vertex in unix_walk_scc(). */
-			list_move_tail(&vertex->entry, &unix_visited_vertices);
+			list_move_tail(&v->entry, &unix_visited_vertices);
 
 			/* Mark vertex as off-stack. */
-			vertex->index = unix_vertex_grouped_index;
+			v->index = unix_vertex_grouped_index;
 
 			if (scc_dead)
-				scc_dead = unix_vertex_dead(vertex);
+				scc_dead = unix_vertex_dead(v);
 		}
 
 		if (scc_dead)
-- 
2.45.2


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

* [PATCH net 2/2] selftest: af_unix: Add test case for backtrack after finalising SCC.
  2024-07-02 16:04 [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Shigeru Yoshida
@ 2024-07-02 16:04 ` Shigeru Yoshida
  2024-07-03  2:42 ` [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Kuniyuki Iwashima
  2024-07-04  2:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Shigeru Yoshida @ 2024-07-02 16:04 UTC (permalink / raw)
  To: davem, edumazet, kuba, pabeni
  Cc: kuniyu, netdev, linux-kernel, Shigeru Yoshida

From: Kuniyuki Iwashima <kuniyu@amazon.com>

syzkaller reported a KMSAN splat in __unix_walk_scc() while backtracking
edge_stack after finalising SCC.

Let's add a test case exercising the path.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>

diff --git a/tools/testing/selftests/net/af_unix/scm_rights.c b/tools/testing/selftests/net/af_unix/scm_rights.c
index 2bfed46e0b19..d66336256580 100644
--- a/tools/testing/selftests/net/af_unix/scm_rights.c
+++ b/tools/testing/selftests/net/af_unix/scm_rights.c
@@ -14,12 +14,12 @@
 
 FIXTURE(scm_rights)
 {
-	int fd[16];
+	int fd[32];
 };
 
 FIXTURE_VARIANT(scm_rights)
 {
-	char name[16];
+	char name[32];
 	int type;
 	int flags;
 	bool test_listener;
@@ -172,6 +172,8 @@ static void __create_sockets(struct __test_metadata *_metadata,
 			     const FIXTURE_VARIANT(scm_rights) *variant,
 			     int n)
 {
+	ASSERT_LE(n * 2, sizeof(self->fd) / sizeof(self->fd[0]));
+
 	if (variant->test_listener)
 		create_listeners(_metadata, self, n);
 	else
@@ -283,4 +285,23 @@ TEST_F(scm_rights, cross_edge)
 	close_sockets(8);
 }
 
+TEST_F(scm_rights, backtrack_from_scc)
+{
+	create_sockets(10);
+
+	send_fd(0, 1);
+	send_fd(0, 4);
+	send_fd(1, 2);
+	send_fd(2, 3);
+	send_fd(3, 1);
+
+	send_fd(5, 6);
+	send_fd(5, 9);
+	send_fd(6, 7);
+	send_fd(7, 8);
+	send_fd(8, 6);
+
+	close_sockets(10);
+}
+
 TEST_HARNESS_MAIN


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

* Re: [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc()
  2024-07-02 16:04 [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Shigeru Yoshida
  2024-07-02 16:04 ` [PATCH net 2/2] selftest: af_unix: Add test case for backtrack after finalising SCC Shigeru Yoshida
@ 2024-07-03  2:42 ` Kuniyuki Iwashima
  2024-07-04  2:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2024-07-03  2:42 UTC (permalink / raw)
  To: syoshida
  Cc: davem, edumazet, kuba, kuniyu, linux-kernel, netdev, pabeni,
	syzkaller

From: Shigeru Yoshida <syoshida@redhat.com>
Date: Wed,  3 Jul 2024 01:04:27 +0900
> KMSAN reported uninit-value access in __unix_walk_scc() [1].
> 
> In the list_for_each_entry_reverse() loop, when the vertex's index
> equals it's scc_index, the loop uses the variable vertex as a
> temporary variable that points to a vertex in scc. And when the loop
> is finished, the variable vertex points to the list head, in this case
> scc, which is a local variable on the stack (more precisely, it's not
> even scc and might underflow the call stack of __unix_walk_scc():
> container_of(&scc, struct unix_vertex, scc_entry)).
> 
> However, the variable vertex is used under the label prev_vertex. So
> if the edge_stack is not empty and the function jumps to the
> prev_vertex label, the function will access invalid data on the
> stack. This causes the uninit-value access issue.
> 
> Fix this by introducing a new temporary variable for the loop.
> 
> [1]
> BUG: KMSAN: uninit-value in __unix_walk_scc net/unix/garbage.c:478 [inline]
> BUG: KMSAN: uninit-value in unix_walk_scc net/unix/garbage.c:526 [inline]
> BUG: KMSAN: uninit-value in __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
>  __unix_walk_scc net/unix/garbage.c:478 [inline]
>  unix_walk_scc net/unix/garbage.c:526 [inline]
>  __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
>  process_one_work kernel/workqueue.c:3231 [inline]
>  process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
>  worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
>  kthread+0x3c4/0x530 kernel/kthread.c:389
>  ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Uninit was stored to memory at:
>  unix_walk_scc net/unix/garbage.c:526 [inline]
>  __unix_gc+0x2adf/0x3c20 net/unix/garbage.c:584
>  process_one_work kernel/workqueue.c:3231 [inline]
>  process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
>  worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
>  kthread+0x3c4/0x530 kernel/kthread.c:389
>  ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Local variable entries created at:
>  ref_tracker_free+0x48/0xf30 lib/ref_tracker.c:222
>  netdev_tracker_free include/linux/netdevice.h:4058 [inline]
>  netdev_put include/linux/netdevice.h:4075 [inline]
>  dev_put include/linux/netdevice.h:4101 [inline]
>  update_gid_event_work_handler+0xaa/0x1b0 drivers/infiniband/core/roce_gid_mgmt.c:813
> 
> CPU: 1 PID: 12763 Comm: kworker/u8:31 Not tainted 6.10.0-rc4-00217-g35bb670d65fc #32
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
> Workqueue: events_unbound __unix_gc
> 
> Fixes: 3484f063172d ("af_unix: Detect Strongly Connected Components.")
> Reported-by: syzkaller <syzkaller@googlegroups.com>
> Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>

Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>

Thanks!

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

* Re: [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc()
  2024-07-02 16:04 [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Shigeru Yoshida
  2024-07-02 16:04 ` [PATCH net 2/2] selftest: af_unix: Add test case for backtrack after finalising SCC Shigeru Yoshida
  2024-07-03  2:42 ` [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Kuniyuki Iwashima
@ 2024-07-04  2:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-07-04  2:50 UTC (permalink / raw)
  To: Shigeru Yoshida
  Cc: davem, edumazet, kuba, pabeni, kuniyu, netdev, linux-kernel,
	syzkaller

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Wed,  3 Jul 2024 01:04:27 +0900 you wrote:
> KMSAN reported uninit-value access in __unix_walk_scc() [1].
> 
> In the list_for_each_entry_reverse() loop, when the vertex's index
> equals it's scc_index, the loop uses the variable vertex as a
> temporary variable that points to a vertex in scc. And when the loop
> is finished, the variable vertex points to the list head, in this case
> scc, which is a local variable on the stack (more precisely, it's not
> even scc and might underflow the call stack of __unix_walk_scc():
> container_of(&scc, struct unix_vertex, scc_entry)).
> 
> [...]

Here is the summary with links:
  - [net,1/2] af_unix: Fix uninit-value in __unix_walk_scc()
    https://git.kernel.org/netdev/net/c/927fa5b3e4f5
  - [net,2/2] selftest: af_unix: Add test case for backtrack after finalising SCC.
    https://git.kernel.org/netdev/net/c/2a79651bf2fa

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2024-07-04  2:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-02 16:04 [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Shigeru Yoshida
2024-07-02 16:04 ` [PATCH net 2/2] selftest: af_unix: Add test case for backtrack after finalising SCC Shigeru Yoshida
2024-07-03  2:42 ` [PATCH net 1/2] af_unix: Fix uninit-value in __unix_walk_scc() Kuniyuki Iwashima
2024-07-04  2:50 ` patchwork-bot+netdevbpf

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