| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/07 15:20 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"VSOCKETS"
],
"FocusSymbols": [
"vsock_accept",
"vsock_pending_work"
],
"KMSANReasoning": "The patch modifies the lifecycle of vsock sockets during the `accept()` process. Specifically, it removes the `rejected` flag from `struct vsock_sock` and changes `vsock_accept()` to immediately clean up and drop references to a rejected child socket, rather than deferring the cleanup to `vsock_pending_work()`. This addresses a potential memory leak or lifecycle issue where rejected sockets might not be cleaned up by the pending worker.\n\nThese changes are related to object lifecycle, reference counting, and state management. Any bugs introduced or fixed by this patch would manifest as memory leaks, use-after-free (UAF), or double-free vulnerabilities. Such issues are effectively detected by KASAN (for UAF/double-free) and KMEMLEAK (for memory leaks).\n\nThe patch does not introduce new data structures, does not expose any kernel memory to user space, and does not involve complex initializations where uninitialized memory could be read or leaked. Therefore, there is no risk of uninitialized memory usage that would require KMSAN. Standard KASAN fuzzing is sufficient.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the core vsock logic for handling rejected connections in `vsock_accept` and `vsock_pending_work`. It fixes a leak of rejected child sockets by cleaning them up directly in `vsock_accept` instead of deferring to `vsock_pending_work`. This is a functional change in reachable core kernel logic that should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/07 15:20 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 7d8b984987ceb01122412cb630622583ebfb9a76\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Aug 7 15:20:36 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/include/net/af_vsock.h b/include/net/af_vsock.h\nindex 30046a3c20f73..b70cea7f754f5 100644\n--- a/include/net/af_vsock.h\n+++ b/include/net/af_vsock.h\n@@ -53,12 +53,10 @@ struct vsock_sock {\n \t * for connection requests are placed in the pending list until they\n \t * are connected, at which point they are put in the accept queue list\n \t * so they can be accepted in accept(). If accept() cannot accept the\n-\t * connection, it is marked as rejected so the cleanup function knows\n-\t * to clean up the socket.\n+\t * connection, the child is cleaned up directly in vsock_accept().\n \t */\n \tstruct list_head pending_links;\n \tstruct list_head accept_queue;\n-\tbool rejected;\n \tstruct delayed_work connect_work;\n \tstruct delayed_work pending_work;\n \tstruct delayed_work close_work;\ndiff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c\nindex 622dbd0467994..2084c88ac836f 100644\n--- a/net/vmw_vsock/af_vsock.c\n+++ b/net/vmw_vsock/af_vsock.c\n@@ -39,9 +39,9 @@\n * from the listener socket's pending list and enqueued in the listener\n * socket's accept queue. Callers of accept(2) will accept connected sockets\n * from the listener socket's accept queue. If the socket cannot be accepted\n- * for some reason then it is marked rejected. Once the connection is\n- * accepted, it is owned by the user process and the responsibility for cleanup\n- * falls with that user process.\n+ * for some reason then it is cleaned up directly in vsock_accept(). Once the\n+ * connection is accepted, it is owned by the user process and the\n+ * responsibility for cleanup falls with that user process.\n *\n * - It is possible that these pending sockets will never reach the connected\n * state; in fact, we may never receive another packet after the connection\n@@ -49,9 +49,7 @@\n * future, after some amount of time passes where a connection should have been\n * established. This function ensures that the socket is off all lists so it\n * cannot be retrieved, then drops all references to the socket so it is cleaned\n- * up (sock_put() -\u003e sk_free() -\u003e our sk_destruct implementation). Note this\n- * function will also cleanup rejected sockets, those that reach the connected\n- * state but leave it before they have been accepted.\n+ * up (sock_put() -\u003e sk_free() -\u003e our sk_destruct implementation).\n *\n * - Lock ordering for pending or accept queue sockets is:\n *\n@@ -774,11 +772,11 @@ static void vsock_pending_work(struct work_struct *work)\n \n \tif (vsock_is_pending(sk)) {\n \t\tvsock_remove_pending(listener, sk);\n-\t} else if (!vsk-\u003erejected) {\n-\t\t/* We are not on the pending list and accept() did not reject\n-\t\t * us, so we must have been accepted by our user process. We\n-\t\t * just need to drop our references to the sockets and be on\n-\t\t * our way.\n+\t} else {\n+\t\t/* We are not on the pending list, so we must have been accepted\n+\t\t * by our user process (rejected sockets are cleaned up directly\n+\t\t * in vsock_accept()). We just need to drop our references to\n+\t\t * the sockets and be on our way.\n \t\t */\n \t\tcleanup = false;\n \t\tgoto out;\n@@ -942,7 +940,6 @@ static struct sock *__vsock_create(struct net *net,\n \tvsk-\u003elistener = NULL;\n \tINIT_LIST_HEAD(\u0026vsk-\u003epending_links);\n \tINIT_LIST_HEAD(\u0026vsk-\u003eaccept_queue);\n-\tvsk-\u003erejected = false;\n \tvsk-\u003esent_request = false;\n \tvsk-\u003eignore_connecting_rst = false;\n \tWRITE_ONCE(vsk-\u003epeer_shutdown, 0);\n@@ -1919,14 +1916,19 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,\n \t\tvconnected = vsock_sk(connected);\n \n \t\t/* If the listener socket has received an error, then we should\n-\t\t * reject this socket and return. Note that we simply mark the\n-\t\t * socket rejected, drop our reference, and let the cleanup\n-\t\t * function handle the cleanup; the fact that we found it in\n-\t\t * the listener's accept queue guarantees that the cleanup\n-\t\t * function hasn't run yet.\n+\t\t * reject this socket and return. The child was found on the\n+\t\t * listener's accept queue, so it still holds the references\n+\t\t * taken by sk_alloc(), __vsock_insert_connected() and\n+\t\t * vsock_enqueue_accept(). Drop them here so the socket is\n+\t\t * destroyed. We cannot defer this to vsock_pending_work():\n+\t\t * rejected child sockets created through virtio_transport and\n+\t\t * vsock_loopback are not cleaned up by that worker, so the\n+\t\t * child would otherwise leak permanently.\n \t\t */\n \t\tif (err) {\n-\t\t\tvconnected-\u003erejected = true;\n+\t\t\tvsock_remove_connected(vconnected);\n+\t\t\tconnected-\u003esk_state = TCP_CLOSE;\n+\t\t\tsock_put(connected);\n \t\t} else {\n \t\t\tnewsock-\u003estate = SS_CONNECTED;\n \t\t\tsock_graft(connected, newsock);\n"
} |
| 2/1 | 2026/08/07 15:20 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"VSOCKETS"
],
"FocusSymbols": [
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core vsock logic for handling rejected connections in `vsock_accept` and `vsock_pending_work`. It fixes a leak of rejected child sockets by cleaning them up directly in `vsock_accept` instead of deferring to `vsock_pending_work`. This is a functional change in reachable core kernel logic that should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 7d8b984987ceb01122412cb630622583ebfb9a76
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Aug 7 15:20:36 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 30046a3c20f73..b70cea7f754f5 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -53,12 +53,10 @@ struct vsock_sock {
* for connection requests are placed in the pending list until they
* are connected, at which point they are put in the accept queue list
* so they can be accepted in accept(). If accept() cannot accept the
- * connection, it is marked as rejected so the cleanup function knows
- * to clean up the socket.
+ * connection, the child is cleaned up directly in vsock_accept().
*/
struct list_head pending_links;
struct list_head accept_queue;
- bool rejected;
struct delayed_work connect_work;
struct delayed_work pending_work;
struct delayed_work close_work;
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 622dbd0467994..2084c88ac836f 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -39,9 +39,9 @@
* from the listener socket's pending list and enqueued in the listener
* socket's accept queue. Callers of accept(2) will accept connected sockets
* from the listener socket's accept queue. If the socket cannot be accepted
- * for some reason then it is marked rejected. Once the connection is
- * accepted, it is owned by the user process and the responsibility for cleanup
- * falls with that user process.
+ * for some reason then it is cleaned up directly in vsock_accept(). Once the
+ * connection is accepted, it is owned by the user process and the
+ * responsibility for cleanup falls with that user process.
*
* - It is possible that these pending sockets will never reach the connected
* state; in fact, we may never receive another packet after the connection
@@ -49,9 +49,7 @@
* future, after some amount of time passes where a connection should have been
* established. This function ensures that the socket is off all lists so it
* cannot be retrieved, then drops all references to the socket so it is cleaned
- * up (sock_put() -> sk_free() -> our sk_destruct implementation). Note this
- * function will also cleanup rejected sockets, those that reach the connected
- * state but leave it before they have been accepted.
+ * up (sock_put() -> sk_free() -> our sk_destruct implementation).
*
* - Lock ordering for pending or accept queue sockets is:
*
@@ -774,11 +772,11 @@ static void vsock_pending_work(struct work_struct *work)
if (vsock_is_pending(sk)) {
vsock_remove_pending(listener, sk);
- } else if (!vsk->rejected) {
- /* We are not on the pending list and accept() did not reject
- * us, so we must have been accepted by our user process. We
- * just need to drop our references to the sockets and be on
- * our way.
+ } else {
+ /* We are not on the pending list, so we must have been accepted
+ * by our user process (rejected sockets are cleaned up directly
+ * in vsock_accept()). We just need to drop our references to
+ * the sockets and be on our way.
*/
cleanup = false;
goto out;
@@ -942,7 +940,6 @@ static struct sock *__vsock_create(struct net *net,
vsk->listener = NULL;
INIT_LIST_HEAD(&vsk->pending_links);
INIT_LIST_HEAD(&vsk->accept_queue);
- vsk->rejected = false;
vsk->sent_request = false;
vsk->ignore_connecting_rst = false;
WRITE_ONCE(vsk->peer_shutdown, 0);
@@ -1919,14 +1916,19 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
vconnected = vsock_sk(connected);
/* If the listener socket has received an error, then we should
- * reject this socket and return. Note that we simply mark the
- * socket rejected, drop our reference, and let the cleanup
- * function handle the cleanup; the fact that we found it in
- * the listener's accept queue guarantees that the cleanup
- * function hasn't run yet.
+ * reject this socket and return. The child was found on the
+ * listener's accept queue, so it still holds the references
+ * taken by sk_alloc(), __vsock_insert_connected() and
+ * vsock_enqueue_accept(). Drop them here so the socket is
+ * destroyed. We cannot defer this to vsock_pending_work():
+ * rejected child sockets created through virtio_transport and
+ * vsock_loopback are not cleaned up by that worker, so the
+ * child would otherwise leak permanently.
*/
if (err) {
- vconnected->rejected = true;
+ vsock_remove_connected(vconnected);
+ connected->sk_state = TCP_CLOSE;
+ sock_put(connected);
} else {
newsock->state = SS_CONNECTED;
sock_graft(connected, newsock);
|
| 3/2 | 2026/08/07 15:20 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3229 output: 34 thoughts: 220 Thoughts: **Analyzing the vsock Patch** Okay, so I'm looking at this patch that's been proposed for the vsock implementation, specifically in `net/vmw_vsock/af_vsock.c` and `include/net/af_vsock.h`. My immediate takeaway is that they're streamlining the socket rejection process. The patch eliminates the `rejected` field within `struct vsock_sock`. Essentially, rather than marking a socket and deferring the cleanup, it looks like they're handling the cleanup directly within `vsock_accept()`. Let's dive deeper and verify the changes in `vsock_accept` within `net/vmw_vsock/af_vsock.c`. Ah, yes, here we go. It looks like the patch replaces the setting of `vconnected->rejected = true` with a more direct approach. They're now calling `vsock_remove_connected(vconnected)`, setting `connected->sk_state = TCP_CLOSE`, and then doing a `sock_put(connected)`. This is a pretty significant functional modification to the core vsock handling, so I need to understand the implications for other modules and possible side-effects. Before I go any deeper, I'll need to confirm what config options are related to this. Alright, the core configuration option is, obviously, `CONFIG_VSOCKETS`. I'll have a look at `net/vmw_vsock/Kconfig` to be certain. |
| 4/2 | 2026/08/07 15:20 | tool | grepper |
0mArgs:{
"Expression": "config VSOCKETS",
"PathPrefix": "net/vmw_vsock/Kconfig"
}Results: {
"Output": "net/vmw_vsock/Kconfig-5-\nnet/vmw_vsock/Kconfig:6:config VSOCKETS\nnet/vmw_vsock/Kconfig-7-\ttristate \"Virtual Socket protocol\"\n--\nnet/vmw_vsock/Kconfig-18-\nnet/vmw_vsock/Kconfig:19:config VSOCKETS_DIAG\nnet/vmw_vsock/Kconfig-20-\ttristate \"Virtual Sockets monitoring interface\"\n--\nnet/vmw_vsock/Kconfig-28-\nnet/vmw_vsock/Kconfig:29:config VSOCKETS_LOOPBACK\nnet/vmw_vsock/Kconfig-30-\ttristate \"Virtual Sockets loopback transport\"\n"
} |
| 5/2 | 2026/08/07 15:20 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 4000 output: 38 thoughts: 48 Thoughts: Okay, here's my interpretation of these thoughts, tailored as if I, as an expert, were having them: **VSOCKETS Configuration Deep Dive** Alright, so we're dealing with `VSOCKETS` here. That means we're in the realm of virtual sockets, which is going to shape how we think about this. The critical aspect is to understand the configuration that's at play. Now, I'm thinking about where to start my investigation. My initial inclination is to look at these focus symbols: `vsock_accept` and `vsock_pending_work`. These feel like solid entry points, particularly `vsock_accept`. It represents the process of a connection, and the other relates to work that is waiting. `vsock_accept` looks like a key starting point to check. |
| 6/2 | 2026/08/07 15:21 | tool | grepper |
0mArgs:{
"Expression": "vsock_accept",
"PathPrefix": "net/vmw_vsock/af_vsock.c"
}Results: {
"Output": "net/vmw_vsock/af_vsock.c-41- * from the listener socket's accept queue. If the socket cannot be accepted\nnet/vmw_vsock/af_vsock.c:42: * for some reason then it is cleaned up directly in vsock_accept(). Once the\nnet/vmw_vsock/af_vsock.c-43- * connection is accepted, it is owned by the user process and the\n--\nnet/vmw_vsock/af_vsock.c=758=static void vsock_pending_work(struct work_struct *work)\n--\nnet/vmw_vsock/af_vsock.c-777-\t\t * by our user process (rejected sockets are cleaned up directly\nnet/vmw_vsock/af_vsock.c:778:\t\t * in vsock_accept()). We just need to drop our references to\nnet/vmw_vsock/af_vsock.c-779-\t\t * the sockets and be on our way.\n--\nnet/vmw_vsock/af_vsock.c=1674=static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,\n--\nnet/vmw_vsock/af_vsock.c-1861-\nnet/vmw_vsock/af_vsock.c:1862:static int vsock_accept(struct socket *sock, struct socket *newsock,\nnet/vmw_vsock/af_vsock.c-1863-\t\t\tstruct proto_accept_arg *arg)\n--\nnet/vmw_vsock/af_vsock.c=2646=static const struct proto_ops vsock_stream_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2652-\t.socketpair = sock_no_socketpair,\nnet/vmw_vsock/af_vsock.c:2653:\t.accept = vsock_accept,\nnet/vmw_vsock/af_vsock.c-2654-\t.getname = vsock_getname,\n--\nnet/vmw_vsock/af_vsock.c=2668=static const struct proto_ops vsock_seqpacket_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2674-\t.socketpair = sock_no_socketpair,\nnet/vmw_vsock/af_vsock.c:2675:\t.accept = vsock_accept,\nnet/vmw_vsock/af_vsock.c-2676-\t.getname = vsock_getname,\n"
} |
| 7/2 | 2026/08/07 15:21 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 4924 output: 129 thoughts: 76 Thoughts: Okay, here's my take on those thoughts, framed as my own mental processing: **VSOCK Socket Leak Fix and Fuzzing Consideration** Right, so we're looking at a patch that targets a pretty specific problem: a leak of rejected child sockets in the vsock stream and seqpacket operations. Specifically, the leak is originating from how we handle things with `virtio_transport` and `vsock_loopback`. `vsock_accept` handles the `accept` function for both, and `vsock_pending_work` is a workqueue function involved in the process. This fix is interesting. The fact that we have a memory leak related to *rejected* sockets is a good indicator that something's off in the error path or the cleanup routines. It suggests the normal close path is never getting called when a socket is rejected by a server. Given the potential complexity and the fact that we're dealing with socket management (always a good target), this is *definitely* worth a thorough fuzzing campaign. We need to hit this with all sorts of malformed data and edge cases to ensure we've really plugged the hole. It's a prime target for crashing and memory corruption, so fuzzing is almost a given. Let's start by setting that up immediately. |
| 8/2 | 2026/08/07 15:21 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"VSOCKETS"
],
"FocusSymbols": [
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core vsock logic for handling rejected connections in `vsock_accept` and `vsock_pending_work`. It fixes a leak of rejected child sockets by cleaning them up directly in `vsock_accept` instead of deferring to `vsock_pending_work`. This is a functional change in reachable core kernel logic that should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"VSOCKETS"
],
"FocusSymbols": [
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core vsock logic for handling rejected connections in `vsock_accept` and `vsock_pending_work`. It fixes a leak of rejected child sockets by cleaning them up directly in `vsock_accept` instead of deferring to `vsock_pending_work`. This is a functional change in reachable core kernel logic that should be fuzzed.",
"WorthFuzzing": true
} |
| 9/1 | 2026/08/07 15:21 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 10/2 | 2026/08/07 15:21 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch modifies the lifecycle of vsock sockets during the `accept()` process. Specifically, it removes the `rejected` flag from `struct vsock_sock` and changes `vsock_accept()` to immediately clean up and drop references to a rejected child socket, rather than deferring the cleanup to `vsock_pending_work()`. This addresses a potential memory leak or lifecycle issue where rejected sockets might not be cleaned up by the pending worker.\n\nThese changes are related to object lifecycle, reference counting, and state management. Any bugs introduced or fixed by this patch would manifest as memory leaks, use-after-free (UAF), or double-free vulnerabilities. Such issues are effectively detected by KASAN (for UAF/double-free) and KMEMLEAK (for memory leaks).\n\nThe patch does not introduce new data structures, does not expose any kernel memory to user space, and does not involve complex initializations where uninitialized memory could be read or leaked. Therefore, there is no risk of uninitialized memory usage that would require KMSAN. Standard KASAN fuzzing is sufficient.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: For your convenience, here is the diff of the changes:
commit 7d8b984987ceb01122412cb630622583ebfb9a76
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Aug 7 15:20:36 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 30046a3c20f73..b70cea7f754f5 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -53,12 +53,10 @@ struct vsock_sock {
* for connection requests are placed in the pending list until they
* are connected, at which point they are put in the accept queue list
* so they can be accepted in accept(). If accept() cannot accept the
- * connection, it is marked as rejected so the cleanup function knows
- * to clean up the socket.
+ * connection, the child is cleaned up directly in vsock_accept().
*/
struct list_head pending_links;
struct list_head accept_queue;
- bool rejected;
struct delayed_work connect_work;
struct delayed_work pending_work;
struct delayed_work close_work;
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 622dbd0467994..2084c88ac836f 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -39,9 +39,9 @@
* from the listener socket's pending list and enqueued in the listener
* socket's accept queue. Callers of accept(2) will accept connected sockets
* from the listener socket's accept queue. If the socket cannot be accepted
- * for some reason then it is marked rejected. Once the connection is
- * accepted, it is owned by the user process and the responsibility for cleanup
- * falls with that user process.
+ * for some reason then it is cleaned up directly in vsock_accept(). Once the
+ * connection is accepted, it is owned by the user process and the
+ * responsibility for cleanup falls with that user process.
*
* - It is possible that these pending sockets will never reach the connected
* state; in fact, we may never receive another packet after the connection
@@ -49,9 +49,7 @@
* future, after some amount of time passes where a connection should have been
* established. This function ensures that the socket is off all lists so it
* cannot be retrieved, then drops all references to the socket so it is cleaned
- * up (sock_put() -> sk_free() -> our sk_destruct implementation). Note this
- * function will also cleanup rejected sockets, those that reach the connected
- * state but leave it before they have been accepted.
+ * up (sock_put() -> sk_free() -> our sk_destruct implementation).
*
* - Lock ordering for pending or accept queue sockets is:
*
@@ -774,11 +772,11 @@ static void vsock_pending_work(struct work_struct *work)
if (vsock_is_pending(sk)) {
vsock_remove_pending(listener, sk);
- } else if (!vsk->rejected) {
- /* We are not on the pending list and accept() did not reject
- * us, so we must have been accepted by our user process. We
- * just need to drop our references to the sockets and be on
- * our way.
+ } else {
+ /* We are not on the pending list, so we must have been accepted
+ * by our user process (rejected sockets are cleaned up directly
+ * in vsock_accept()). We just need to drop our references to
+ * the sockets and be on our way.
*/
cleanup = false;
goto out;
@@ -942,7 +940,6 @@ static struct sock *__vsock_create(struct net *net,
vsk->listener = NULL;
INIT_LIST_HEAD(&vsk->pending_links);
INIT_LIST_HEAD(&vsk->accept_queue);
- vsk->rejected = false;
vsk->sent_request = false;
vsk->ignore_connecting_rst = false;
WRITE_ONCE(vsk->peer_shutdown, 0);
@@ -1919,14 +1916,19 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
vconnected = vsock_sk(connected);
/* If the listener socket has received an error, then we should
- * reject this socket and return. Note that we simply mark the
- * socket rejected, drop our reference, and let the cleanup
- * function handle the cleanup; the fact that we found it in
- * the listener's accept queue guarantees that the cleanup
- * function hasn't run yet.
+ * reject this socket and return. The child was found on the
+ * listener's accept queue, so it still holds the references
+ * taken by sk_alloc(), __vsock_insert_connected() and
+ * vsock_enqueue_accept(). Drop them here so the socket is
+ * destroyed. We cannot defer this to vsock_pending_work():
+ * rejected child sockets created through virtio_transport and
+ * vsock_loopback are not cleaned up by that worker, so the
+ * child would otherwise leak permanently.
*/
if (err) {
- vconnected->rejected = true;
+ vsock_remove_connected(vconnected);
+ connected->sk_state = TCP_CLOSE;
+ sock_put(connected);
} else {
newsock->state = SS_CONNECTED;
sock_graft(connected, newsock);
|
| 11/3 | 2026/08/07 15:21 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3226 output: 254 thoughts: 552 Thoughts: **Analyzing the vsock Socket Lifecycle Patch** Okay, let's break this down. This patch is targeted at `vsock_accept` in `net/vmw_vsock/af_vsock.c` and is focused on streamlining socket lifecycle management, specifically around rejected sockets. My initial thought is this is addressing a memory management issue – likely a leak or use-after-free, based on the context. Instead of marking a socket as rejected and deferring cleanup, the patch is now handling immediate cleanup directly within `vsock_accept`. My immediate next step is to make sure this doesn't expose any uninitialized memory. The changes involve removing the `rejected` field from `struct vsock_sock` entirely, which also removes the initialization `vsk->rejected = false;` in `__vsock_create`. `vsock_accept` is now going to call `vsock_remove_connected`, set `sk_state = TCP_CLOSE`, and `sock_put` directly on the rejected socket. `vsock_pending_work` is no longer checking `!vsk->rejected`. From what I can see, this is a pretty straightforward change in socket lifecycle and reference counting. It’s entirely about state transitions, not data structure changes or uninitialized data. Critically, nothing new is being passed up to user space here. I'm confident we don't have an uninitialized memory issue here, so KMSAN isn't needed. This is purely a lifecycle and state machine change. Any issues introduced here are more likely to manifest as leaks, use-after-free (UAF), or double-free, which KASAN and KMEMLEAK should readily catch. Therefore, NeedsKMSAN = false. To summarize, this patch optimizes the handling of rejected sockets during the `accept()` process. By removing the `rejected` flag and moving cleanup to `vsock_accept()`, the patch fixes an issue where rejected sockets might not be cleaned up properly. It's a lifecycle/reference-counting change, so the major bugs of concern are memory leaks, UAF, or double-free. Standard KASAN fuzzing is sufficient because this patch does not expose uninitialized memory. |
| 12/3 | 2026/08/07 15:21 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch modifies the lifecycle of vsock sockets during the `accept()` process. Specifically, it removes the `rejected` flag from `struct vsock_sock` and changes `vsock_accept()` to immediately clean up and drop references to a rejected child socket, rather than deferring the cleanup to `vsock_pending_work()`. This addresses a potential memory leak or lifecycle issue where rejected sockets might not be cleaned up by the pending worker.\n\nThese changes are related to object lifecycle, reference counting, and state management. Any bugs introduced or fixed by this patch would manifest as memory leaks, use-after-free (UAF), or double-free vulnerabilities. Such issues are effectively detected by KASAN (for UAF/double-free) and KMEMLEAK (for memory leaks).\n\nThe patch does not introduce new data structures, does not expose any kernel memory to user space, and does not involve complex initializations where uninitialized memory could be read or leaked. Therefore, there is no risk of uninitialized memory usage that would require KMSAN. Standard KASAN fuzzing is sufficient.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch modifies the lifecycle of vsock sockets during the `accept()` process. Specifically, it removes the `rejected` flag from `struct vsock_sock` and changes `vsock_accept()` to immediately clean up and drop references to a rejected child socket, rather than deferring the cleanup to `vsock_pending_work()`. This addresses a potential memory leak or lifecycle issue where rejected sockets might not be cleaned up by the pending worker.\n\nThese changes are related to object lifecycle, reference counting, and state management. Any bugs introduced or fixed by this patch would manifest as memory leaks, use-after-free (UAF), or double-free vulnerabilities. Such issues are effectively detected by KASAN (for UAF/double-free) and KMEMLEAK (for memory leaks).\n\nThe patch does not introduce new data structures, does not expose any kernel memory to user space, and does not involve complex initializations where uninitialized memory could be read or leaked. Therefore, there is no risk of uninitialized memory usage that would require KMSAN. Standard KASAN fuzzing is sufficient.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|