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