| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/13 19:01 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"VSOCKETS",
"VSOCKETS_LOOPBACK"
],
"FocusSymbols": [
"vsock_connect",
"vsock_accept",
"vsock_pending_work"
],
"KMSANReasoning": "The patch removes the `rejected` field from `struct vsock_sock` and simplifies error handling logic in `vsock_accept` and `vsock_connect`. It does not introduce any new structures sent to user space, nor does it add any new allocations or complex data structures. The changes do not expose any uninitialized memory risks. Any potential bugs introduced by this patch (such as use-after-free, memory leaks, or logic errors) would be effectively caught by KASAN and other standard bug detectors. Therefore, a dedicated KMSAN fuzzing session is not necessary.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies the core connection establishment and error handling logic for AF_VSOCK sockets. It removes the `rejected` state from pending sockets and changes how `vsock_accept` and `vsock_connect` handle socket errors. These are functional changes in reachable core networking code that should be fuzzed to ensure no regressions or memory leaks occur during connection failures.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/13 19:01 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit dba546b60de08b0fe1a73ac464ef56dacfbe2121\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Aug 13 19:01:16 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..3357ee62d10bf 100644\n--- a/include/net/af_vsock.h\n+++ b/include/net/af_vsock.h\n@@ -52,13 +52,10 @@ struct vsock_sock {\n \t * The listening socket is the head for both lists. Sockets created\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 * so they can be accepted in 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..e89cb84b8d737 100644\n--- a/net/vmw_vsock/af_vsock.c\n+++ b/net/vmw_vsock/af_vsock.c\n@@ -38,10 +38,9 @@\n * pending socket. When that socket reaches the connected state, it is removed\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+ * from the listener socket's accept queue. Once the connection is accepted,\n+ * it is owned by the user process and the responsibility for cleanup falls\n+ * 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 +48,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 +771,10 @@ 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. 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 +938,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@@ -1847,12 +1842,10 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,\n \t\tprepare_to_wait(sk_sleep(sk), \u0026wait, TASK_INTERRUPTIBLE);\n \t}\n \n-\tif (sk-\u003esk_err) {\n-\t\terr = -sk-\u003esk_err;\n+\terr = sock_error(sk);\n+\tif (err) {\n \t\tsk-\u003esk_state = TCP_CLOSE;\n \t\tsock-\u003estate = SS_UNCONNECTED;\n-\t} else {\n-\t\terr = 0;\n \t}\n \n out_wait:\n@@ -1893,7 +1886,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,\n \ttimeout = sock_rcvtimeo(listener, arg-\u003eflags \u0026 O_NONBLOCK);\n \n \twhile ((connected = vsock_dequeue_accept(listener)) == NULL \u0026\u0026\n-\t listener-\u003esk_err == 0 \u0026\u0026 timeout != 0) {\n+\t\ttimeout != 0) {\n \t\tprepare_to_wait(sk_sleep(listener), \u0026wait, TASK_INTERRUPTIBLE);\n \t\trelease_sock(listener);\n \t\ttimeout = schedule_timeout(timeout);\n@@ -1906,38 +1899,23 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,\n \t\t}\n \t}\n \n-\tif (listener-\u003esk_err) {\n-\t\terr = -listener-\u003esk_err;\n-\t} else if (!connected) {\n+\tif (!connected) {\n \t\terr = -EAGAIN;\n-\t}\n-\n-\tif (connected) {\n+\t} else {\n \t\tsk_acceptq_removed(listener);\n \n \t\tlock_sock_nested(connected, SINGLE_DEPTH_NESTING);\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 */\n-\t\tif (err) {\n-\t\t\tvconnected-\u003erejected = true;\n-\t\t} else {\n-\t\t\tnewsock-\u003estate = SS_CONNECTED;\n-\t\t\tsock_graft(connected, newsock);\n+\t\tnewsock-\u003estate = SS_CONNECTED;\n+\t\tsock_graft(connected, newsock);\n \n-\t\t\tset_bit(SOCK_CUSTOM_SOCKOPT,\n-\t\t\t\t\u0026connected-\u003esk_socket-\u003eflags);\n+\t\tset_bit(SOCK_CUSTOM_SOCKOPT,\n+\t\t\t\u0026connected-\u003esk_socket-\u003eflags);\n \n-\t\t\tif (vsock_msgzerocopy_allow(vconnected-\u003etransport))\n-\t\t\t\tset_bit(SOCK_SUPPORT_ZC,\n-\t\t\t\t\t\u0026connected-\u003esk_socket-\u003eflags);\n-\t\t}\n+\t\tif (vsock_msgzerocopy_allow(vconnected-\u003etransport))\n+\t\t\tset_bit(SOCK_SUPPORT_ZC,\n+\t\t\t\t\u0026connected-\u003esk_socket-\u003eflags);\n \n \t\trelease_sock(connected);\n \t\tsock_put(connected);\n"
} |
| 2/1 | 2026/08/13 19:01 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"VSOCKETS",
"VSOCKETS_LOOPBACK"
],
"FocusSymbols": [
"vsock_connect",
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core connection establishment and error handling logic for AF_VSOCK sockets. It removes the `rejected` state from pending sockets and changes how `vsock_accept` and `vsock_connect` handle socket errors. These are functional changes in reachable core networking code that should be fuzzed to ensure no regressions or memory leaks occur during connection failures.",
"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 dba546b60de08b0fe1a73ac464ef56dacfbe2121
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Aug 13 19:01:16 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 30046a3c20f73..3357ee62d10bf 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -52,13 +52,10 @@ struct vsock_sock {
* The listening socket is the head for both lists. Sockets created
* 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.
+ * so they can be accepted in 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..e89cb84b8d737 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -38,10 +38,9 @@
* pending socket. When that socket reaches the connected state, it is removed
* 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.
+ * from the listener socket's accept queue. 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 +48,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 +771,10 @@ 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. We just need to drop our references to
+ * the sockets and be on our way.
*/
cleanup = false;
goto out;
@@ -942,7 +938,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);
@@ -1847,12 +1842,10 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
}
- if (sk->sk_err) {
- err = -sk->sk_err;
+ err = sock_error(sk);
+ if (err) {
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
- } else {
- err = 0;
}
out_wait:
@@ -1893,7 +1886,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
- listener->sk_err == 0 && timeout != 0) {
+ timeout != 0) {
prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
release_sock(listener);
timeout = schedule_timeout(timeout);
@@ -1906,38 +1899,23 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
}
}
- if (listener->sk_err) {
- err = -listener->sk_err;
- } else if (!connected) {
+ if (!connected) {
err = -EAGAIN;
- }
-
- if (connected) {
+ } else {
sk_acceptq_removed(listener);
lock_sock_nested(connected, SINGLE_DEPTH_NESTING);
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.
- */
- if (err) {
- vconnected->rejected = true;
- } else {
- newsock->state = SS_CONNECTED;
- sock_graft(connected, newsock);
+ newsock->state = SS_CONNECTED;
+ sock_graft(connected, newsock);
- set_bit(SOCK_CUSTOM_SOCKOPT,
- &connected->sk_socket->flags);
+ set_bit(SOCK_CUSTOM_SOCKOPT,
+ &connected->sk_socket->flags);
- if (vsock_msgzerocopy_allow(vconnected->transport))
- set_bit(SOCK_SUPPORT_ZC,
- &connected->sk_socket->flags);
- }
+ if (vsock_msgzerocopy_allow(vconnected->transport))
+ set_bit(SOCK_SUPPORT_ZC,
+ &connected->sk_socket->flags);
release_sock(connected);
sock_put(connected);
|
| 3/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3686 output: 38 thoughts: 522 Thoughts: **Analyzing a vsock Patch** Okay, so I've got this patch affecting the vsock implementation, specifically messing with `net/vmw_vsock/af_vsock.c` and `include/net/af_vsock.h`. My immediate thought is, "intriguing, let's see what's changed and what this means for the network subsystem." It looks like they're removing the `rejected` field from `struct vsock_sock`, and that instantly flags my attention. That boolean likely had a very specific purpose in the error handling or connection lifecycle. The changes focus on a few key functions: `vsock_pending_work`, `vsock_connect`, and `vsock_accept`. Let's break it down: * **`vsock_sock` struct**: Gone is the `rejected` boolean. That implies a shift in how connections are managed. * **`vsock_pending_work`**: The patch eliminates a check for `!vsk->rejected`. This is coupled to the first point; the "rejection" concept is getting altered or removed. * **`vsock_connect`**: The patch is going from `if (sk->sk_err)` to `err = sock_error(sk); if (err)`. This appears to be a cleaner way to get the socket error. * **`vsock_accept`**: This is where things get interesting. The patch removes the check for `listener->sk_err == 0` in the `while` loop, removes handling for `listener->sk_err`, and the code path handling `vconnected->rejected = true`. This points to a change in how the accept queue is handled, maybe more lenient error handling. This is a fundamental change to vsock core logic, which is definitely worth a closer look, especially for the effects on error handling in `accept()` and `connect()`. My gut tells me this needs some solid fuzzing. My next step is to nail down the focus symbols. The functions being touched are: `vsock_pending_work`, `vsock_connect`, and `vsock_accept`. They're *static*, but assigned to `struct proto_ops`. Alright, so `vsock_connect` and `vsock_accept` are the actual, direct functions. I need to confirm if there are any non-static wrappers, like the usual `sys_connect` -> `__sys_connect` -> `sock->ops->connect` pattern. Yes, `vsock_connect` and `vsock_accept` are static within `net/vmw_vsock/af_vsock.c`, so those are the entry points. Given this understanding, I can now begin to map out the potential attack surface. |
| 4/2 | 2026/08/13 19:01 | tool | grepper |
0mArgs:{
"Expression": "vsock_connect",
"PathPrefix": "net/vmw_vsock/af_vsock.c"
}Results: {
"Output": "net/vmw_vsock/af_vsock.c=209=static DEFINE_MUTEX(vsock_register_mutex);\n--\nnet/vmw_vsock/af_vsock.c-235-\t(((src)-\u003esvm_cid ^ (dst)-\u003esvm_port) % VSOCK_HASH_SIZE)\nnet/vmw_vsock/af_vsock.c:236:#define vsock_connected_sockets(src, dst)\t\t\\\nnet/vmw_vsock/af_vsock.c:237:\t(\u0026vsock_connected_table[VSOCK_CONN_HASH(src, dst)])\nnet/vmw_vsock/af_vsock.c:238:#define vsock_connected_sockets_vsk(vsk)\t\t\t\t\\\nnet/vmw_vsock/af_vsock.c:239:\tvsock_connected_sockets(\u0026(vsk)-\u003eremote_addr, \u0026(vsk)-\u003elocal_addr)\nnet/vmw_vsock/af_vsock.c-240-\n--\nnet/vmw_vsock/af_vsock.c=242=EXPORT_SYMBOL_GPL(vsock_bind_table);\nnet/vmw_vsock/af_vsock.c:243:struct list_head vsock_connected_table[VSOCK_HASH_SIZE];\nnet/vmw_vsock/af_vsock.c:244:EXPORT_SYMBOL_GPL(vsock_connected_table);\nnet/vmw_vsock/af_vsock.c-245-DEFINE_SPINLOCK(vsock_table_lock);\n--\nnet/vmw_vsock/af_vsock.c=260=static void vsock_init_tables(void)\n--\nnet/vmw_vsock/af_vsock.c-266-\nnet/vmw_vsock/af_vsock.c:267:\tfor (i = 0; i \u003c ARRAY_SIZE(vsock_connected_table); i++)\nnet/vmw_vsock/af_vsock.c:268:\t\tINIT_LIST_HEAD(\u0026vsock_connected_table[i]);\nnet/vmw_vsock/af_vsock.c-269-}\n--\nnet/vmw_vsock/af_vsock.c=320=__vsock_find_connected_socket_net(struct sockaddr_vm *src,\n--\nnet/vmw_vsock/af_vsock.c-324-\nnet/vmw_vsock/af_vsock.c:325:\tlist_for_each_entry(vsk, vsock_connected_sockets(src, dst),\nnet/vmw_vsock/af_vsock.c-326-\t\t\t connected_table) {\n--\nnet/vmw_vsock/af_vsock.c=346=void vsock_insert_connected(struct vsock_sock *vsk)\nnet/vmw_vsock/af_vsock.c-347-{\nnet/vmw_vsock/af_vsock.c:348:\tstruct list_head *list = vsock_connected_sockets(\nnet/vmw_vsock/af_vsock.c-349-\t\t\u0026vsk-\u003eremote_addr, \u0026vsk-\u003elocal_addr);\n--\nnet/vmw_vsock/af_vsock.c=451=void vsock_for_each_connected_socket(struct vsock_transport *transport,\n--\nnet/vmw_vsock/af_vsock.c-457-\nnet/vmw_vsock/af_vsock.c:458:\tfor (i = 0; i \u003c ARRAY_SIZE(vsock_connected_table); i++) {\nnet/vmw_vsock/af_vsock.c-459-\t\tstruct vsock_sock *vsk;\nnet/vmw_vsock/af_vsock.c:460:\t\tlist_for_each_entry(vsk, \u0026vsock_connected_table[i],\nnet/vmw_vsock/af_vsock.c-461-\t\t\t\t connected_table) {\n--\nnet/vmw_vsock/af_vsock.c=567=int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)\n--\nnet/vmw_vsock/af_vsock.c-640-\t\t/* transport-\u003erelease() must be called with sock lock acquired.\nnet/vmw_vsock/af_vsock.c:641:\t\t * This path can only be taken during vsock_connect(), where we\nnet/vmw_vsock/af_vsock.c-642-\t\t * have already held the sock lock. In the other cases, this\n--\nnet/vmw_vsock/af_vsock.c-650-\t\t * state, since we are reassigning the socket to a new transport\nnet/vmw_vsock/af_vsock.c:651:\t\t * during vsock_connect(), let's reset these fields to have a\nnet/vmw_vsock/af_vsock.c-652-\t\t * clean state.\n--\nnet/vmw_vsock/af_vsock.c=865=static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr)\n--\nnet/vmw_vsock/af_vsock.c-901-\nnet/vmw_vsock/af_vsock.c:902:static void vsock_connect_timeout(struct work_struct *work);\nnet/vmw_vsock/af_vsock.c-903-\nnet/vmw_vsock/af_vsock.c=904=static struct sock *__vsock_create(struct net *net,\n--\nnet/vmw_vsock/af_vsock.c-943-\tWRITE_ONCE(vsk-\u003epeer_shutdown, 0);\nnet/vmw_vsock/af_vsock.c:944:\tINIT_DELAYED_WORK(\u0026vsk-\u003econnect_work, vsock_connect_timeout);\nnet/vmw_vsock/af_vsock.c-945-\tINIT_DELAYED_WORK(\u0026vsk-\u003epending_work, vsock_pending_work);\n--\nnet/vmw_vsock/af_vsock.c=1058=EXPORT_SYMBOL_GPL(vsock_stream_has_data);\nnet/vmw_vsock/af_vsock.c-1059-\nnet/vmw_vsock/af_vsock.c:1060:s64 vsock_connectible_has_data(struct vsock_sock *vsk)\nnet/vmw_vsock/af_vsock.c-1061-{\n--\nnet/vmw_vsock/af_vsock.c-1071-}\nnet/vmw_vsock/af_vsock.c:1072:EXPORT_SYMBOL_GPL(vsock_connectible_has_data);\nnet/vmw_vsock/af_vsock.c-1073-\n--\nnet/vmw_vsock/af_vsock.c=1640=static int vsock_transport_cancel_pkt(struct vsock_sock *vsk)\n--\nnet/vmw_vsock/af_vsock.c-1649-\nnet/vmw_vsock/af_vsock.c:1650:static void vsock_connect_timeout(struct work_struct *work)\nnet/vmw_vsock/af_vsock.c-1651-{\n--\nnet/vmw_vsock/af_vsock.c-1671-\nnet/vmw_vsock/af_vsock.c:1672:static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,\nnet/vmw_vsock/af_vsock.c-1673-\t\t\t int addr_len, int flags)\n--\nnet/vmw_vsock/af_vsock.c-1819-\t\t * sk_state != TCP_ESTABLISHED implies that socket is not on\nnet/vmw_vsock/af_vsock.c:1820:\t\t * vsock_connected_table. We keep the binding and the transport\nnet/vmw_vsock/af_vsock.c-1821-\t\t * assigned.\n--\nnet/vmw_vsock/af_vsock.c=1966=static void vsock_update_buffer_size(struct vsock_sock *vsk,\n--\nnet/vmw_vsock/af_vsock.c-1982-\nnet/vmw_vsock/af_vsock.c:1983:static int vsock_connectible_setsockopt(struct socket *sock,\nnet/vmw_vsock/af_vsock.c-1984-\t\t\t\t\tint level,\n--\nnet/vmw_vsock/af_vsock.c-2096-\nnet/vmw_vsock/af_vsock.c:2097:static int vsock_connectible_getsockopt(struct socket *sock,\nnet/vmw_vsock/af_vsock.c-2098-\t\t\t\t\tint level, int optname,\n--\nnet/vmw_vsock/af_vsock.c-2155-\nnet/vmw_vsock/af_vsock.c:2156:static int vsock_connectible_sendmsg(struct socket *sock, struct msghdr *msg,\nnet/vmw_vsock/af_vsock.c-2157-\t\t\t\t size_t len)\n--\nnet/vmw_vsock/af_vsock.c-2317-\nnet/vmw_vsock/af_vsock.c:2318:static int vsock_connectible_wait_data(struct sock *sk,\nnet/vmw_vsock/af_vsock.c-2319-\t\t\t\t struct wait_queue_entry *wait,\n--\nnet/vmw_vsock/af_vsock.c-2334-\t\tprepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE);\nnet/vmw_vsock/af_vsock.c:2335:\t\tdata = vsock_connectible_has_data(vsk);\nnet/vmw_vsock/af_vsock.c-2336-\t\tif (data != 0)\n--\nnet/vmw_vsock/af_vsock.c=2385=static int __vsock_stream_recvmsg(struct sock *sk, struct msghdr *msg,\n--\nnet/vmw_vsock/af_vsock.c-2422-\nnet/vmw_vsock/af_vsock.c:2423:\t\terr = vsock_connectible_wait_data(sk, \u0026wait, timeout,\nnet/vmw_vsock/af_vsock.c-2424-\t\t\t\t\t\t \u0026recv_data, target);\n--\nnet/vmw_vsock/af_vsock.c=2464=static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg,\n--\nnet/vmw_vsock/af_vsock.c-2478-\nnet/vmw_vsock/af_vsock.c:2479:\terr = vsock_connectible_wait_data(sk, \u0026wait, timeout, NULL, 0);\nnet/vmw_vsock/af_vsock.c-2480-\tif (err \u003c= 0)\n--\nnet/vmw_vsock/af_vsock.c=2514=int\nnet/vmw_vsock/af_vsock.c:2515:__vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,\nnet/vmw_vsock/af_vsock.c-2516-\t\t\t int flags)\n--\nnet/vmw_vsock/af_vsock.c=2581=int\nnet/vmw_vsock/af_vsock.c:2582:vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,\nnet/vmw_vsock/af_vsock.c-2583-\t\t\t int flags)\n--\nnet/vmw_vsock/af_vsock.c-2593-\nnet/vmw_vsock/af_vsock.c:2594:\treturn __vsock_connectible_recvmsg(sock, msg, len, flags);\nnet/vmw_vsock/af_vsock.c-2595-}\nnet/vmw_vsock/af_vsock.c:2596:EXPORT_SYMBOL_GPL(vsock_connectible_recvmsg);\nnet/vmw_vsock/af_vsock.c-2597-\n--\nnet/vmw_vsock/af_vsock.c=2622=static const struct proto_ops vsock_stream_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2626-\t.bind = vsock_bind,\nnet/vmw_vsock/af_vsock.c:2627:\t.connect = vsock_connect,\nnet/vmw_vsock/af_vsock.c-2628-\t.socketpair = sock_no_socketpair,\n--\nnet/vmw_vsock/af_vsock.c-2634-\t.shutdown = vsock_shutdown,\nnet/vmw_vsock/af_vsock.c:2635:\t.setsockopt = vsock_connectible_setsockopt,\nnet/vmw_vsock/af_vsock.c:2636:\t.getsockopt_iter = vsock_connectible_getsockopt,\nnet/vmw_vsock/af_vsock.c:2637:\t.sendmsg = vsock_connectible_sendmsg,\nnet/vmw_vsock/af_vsock.c:2638:\t.recvmsg = vsock_connectible_recvmsg,\nnet/vmw_vsock/af_vsock.c-2639-\t.mmap = sock_no_mmap,\n--\nnet/vmw_vsock/af_vsock.c=2644=static const struct proto_ops vsock_seqpacket_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2648-\t.bind = vsock_bind,\nnet/vmw_vsock/af_vsock.c:2649:\t.connect = vsock_connect,\nnet/vmw_vsock/af_vsock.c-2650-\t.socketpair = sock_no_socketpair,\n--\nnet/vmw_vsock/af_vsock.c-2656-\t.shutdown = vsock_shutdown,\nnet/vmw_vsock/af_vsock.c:2657:\t.setsockopt = vsock_connectible_setsockopt,\nnet/vmw_vsock/af_vsock.c:2658:\t.getsockopt_iter = vsock_connectible_getsockopt,\nnet/vmw_vsock/af_vsock.c:2659:\t.sendmsg = vsock_connectible_sendmsg,\nnet/vmw_vsock/af_vsock.c:2660:\t.recvmsg = vsock_connectible_recvmsg,\nnet/vmw_vsock/af_vsock.c-2661-\t.mmap = sock_no_mmap,\n"
} |
| 5/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8756 output: 38 thoughts: 66 Thoughts: **Examining the vsock Connection Functions** Okay, so `vsock_connect`... right, it's a static function. That's as expected. Now, I need to confirm that's also true for the `vsock_accept` function, both of which are residing in `net/vmw_vsock/af_vsock.c`. The real question is, are there any non-static wrappers for these functions? That's what I really need to drill down on to understand the calling contexts. Let me start by digging into the details of `vsock_accept` and see if there are any obvious non-static call points. |
| 6/2 | 2026/08/13 19:01 | tool | grepper |
0mArgs:{
"Expression": "vsock_accept",
"PathPrefix": "net/vmw_vsock/af_vsock.c"
}Results: {
"Output": "net/vmw_vsock/af_vsock.c=1672=static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,\n--\nnet/vmw_vsock/af_vsock.c-1857-\nnet/vmw_vsock/af_vsock.c:1858:static int vsock_accept(struct socket *sock, struct socket *newsock,\nnet/vmw_vsock/af_vsock.c-1859-\t\t\tstruct proto_accept_arg *arg)\n--\nnet/vmw_vsock/af_vsock.c=2622=static const struct proto_ops vsock_stream_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2628-\t.socketpair = sock_no_socketpair,\nnet/vmw_vsock/af_vsock.c:2629:\t.accept = vsock_accept,\nnet/vmw_vsock/af_vsock.c-2630-\t.getname = vsock_getname,\n--\nnet/vmw_vsock/af_vsock.c=2644=static const struct proto_ops vsock_seqpacket_ops = {\n--\nnet/vmw_vsock/af_vsock.c-2650-\t.socketpair = sock_no_socketpair,\nnet/vmw_vsock/af_vsock.c:2651:\t.accept = vsock_accept,\nnet/vmw_vsock/af_vsock.c-2652-\t.getname = vsock_getname,\n"
} |
| 7/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9415 output: 34 thoughts: 391 Thoughts: **My Assessment of vsock API Entrypoints for Syzkaller** Okay, so I'm thinking about how to expose the `vsock` functionality for fuzzing with syzkaller. The initial thought was that since `vsock_connect` and `vsock_accept` are declared as static functions, syzkaller wouldn't be able to directly call them as separate symbols. However, I realize syzkaller will fuzz `connect()` and `accept()` on `AF_VSOCK` sockets. But does it then fuzz `connect$vsock` and `accept$vsock`? My mental model is that it maps to `sys_connect` and `sys_accept`, which eventually *call* these functions. Then I recalled the guideline: prioritize non-static, non-inlined API entrypoints over static helper functions. This is key. The good news is that `vsock_connect` and `vsock_accept` are assigned to the `proto_ops` structs (`vsock_stream_ops` and `vsock_seqpacket_ops`). Since they're function pointers within structs, the compiler *shouldn't* inline them. Their addresses are definitely taken, so they should have distinct symbol addresses. But, if I need to provide non-static functions, are there any? There aren't any explicit non-static wrappers for `vsock_connect` and `vsock_accept`; they are directly assigned within the `proto_ops`. So it looks like I can just list `vsock_connect` and `vsock_accept`. Wait a minute, what about `vsock_pending_work`? This is a workqueue callback. It's *also* static, but its address is taken within `INIT_DELAYED_WORK`. So, it won't be inlined either! So, I think I can safely include `vsock_connect`, `vsock_accept`, and `vsock_pending_work` as suitable candidates. Finally, I should confirm the configuration requirements. The `AF_VSOCK` support requires `CONFIG_VSOCKETS`. That's the baseline, but I'll make sure it's enabled to be absolutely sure. |
| 8/2 | 2026/08/13 19:01 | 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"
} |
| 9/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10508 output: 36 thoughts: 26 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Investigating VSOCKETS Dependencies** Okay, so I need to understand the dependencies of the `VSOCKETS` subsystem. The first logical step is to dive into the Kconfig file for the relevant module. Let's see, that would be `net/vmw_vsock/Kconfig`. This file should lay out everything I need to know in terms of what other kernel features, options, or hardware configurations need to be present or enabled for `VSOCKETS` to function correctly. I'm expecting to find conditional dependencies, perhaps things like hypervisor specific settings or certain networking configurations. Understanding these dependencies is crucial for any sort of debugging or porting effort I'll need to do. Time to see what's in that file. |
| 10/2 | 2026/08/13 19:01 | tool | read-file |
0mArgs:{
"File": "net/vmw_vsock/Kconfig",
"FirstLine": 1,
"LineCount": 20
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\t#\n 3:\t# Vsock protocol\n 4:\t#\n 5:\t\n 6:\tconfig VSOCKETS\n 7:\t\ttristate \"Virtual Socket protocol\"\n 8:\t\thelp\n 9:\t\t Virtual Socket Protocol is a socket protocol similar to TCP/IP\n 10:\t\t allowing communication between Virtual Machines and hypervisor\n 11:\t\t or host.\n 12:\t\n 13:\t\t You should also select one or more hypervisor-specific transports\n 14:\t\t below.\n 15:\t\n 16:\t\t To compile this driver as a module, choose M here: the module\n 17:\t\t will be called vsock. If unsure, say N.\n 18:\t\n 19:\tconfig VSOCKETS_DIAG\n 20:\t\ttristate \"Virtual Sockets monitoring interface\"\n"
} |
| 11/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10988 output: 37 thoughts: 46 Thoughts: Okay, here's my take on those thoughts, framed as my own: **Considering `VSOCKETS` Testing Options** Right, so `VSOCKETS`, inherently, is stand-alone. No other libraries are required. That's a definite plus for keeping things clean. Now, I need to think about how to actually *test* this. To actually exercise the `VSOCKETS` API, I'm going to need a transport layer, of course. For my purposes, particularly for fuzzing, `VSOCKETS_LOOPBACK` is actually an excellent choice. No hypervisor dependencies means less overhead and complexity, which is ideal when I'm aiming for speed and simplicity in my fuzzing setup. This should allow for efficient and focused testing of the core functionality. |
| 12/2 | 2026/08/13 19:01 | tool | read-file |
0mArgs:{
"File": "net/vmw_vsock/Kconfig",
"FirstLine": 21,
"LineCount": 20
}Results: {
"Contents": " 21:\t\tdepends on VSOCKETS\n 22:\t\tdefault y\n 23:\t\thelp\n 24:\t\t Support for PF_VSOCK sockets monitoring interface used by the ss tool.\n 25:\t\t If unsure, say Y.\n 26:\t\n 27:\t\t Enable this module so userspace applications can query open sockets.\n 28:\t\n 29:\tconfig VSOCKETS_LOOPBACK\n 30:\t\ttristate \"Virtual Sockets loopback transport\"\n 31:\t\tdepends on VSOCKETS\n 32:\t\tdefault y\n 33:\t\tselect VIRTIO_VSOCKETS_COMMON\n 34:\t\thelp\n 35:\t\t This module implements a loopback transport for Virtual Sockets,\n 36:\t\t using vmw_vsock_virtio_transport_common.\n 37:\t\n 38:\t\t To compile this driver as a module, choose M here: the module\n 39:\t\t will be called vsock_loopback. If unsure, say N.\n 40:\t\n"
} |
| 13/2 | 2026/08/13 19:01 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11507 output: 142 thoughts: 295 Thoughts: **My Assessment of the VSOCK Patch** Okay, so I've looked through the proposed changes to the VSOCK subsystem. It seems like enabling `VSOCKETS` and `VSOCKETS_LOOPBACK` is a good starting point for testing. I quickly confirmed that `VIRTIO_VSOCKETS_COMMON` is automatically selected by `VSOCKETS_LOOPBACK`, so those two are all I need to focus on. The core of the patch involves streamlining connection establishment and error handling. Specifically, it seems like they're removing the `rejected` field from `struct vsock_sock`, which makes sense to me—it feels like a somewhat redundant piece of state. The code now handles the rejection logic in `vsock_accept` and `vsock_connect` more concisely. In `vsock_accept`, instead of setting `vconnected->rejected = true`, it now simply returns `-EAGAIN` if the connection isn't ready. And, it looks like they've switched to using `sock_error(sk)` in `vsock_connect` instead of directly accessing `sk->sk_err`. The patch also simplifies `vsock_pending_work`, removing the check that involved the `rejected` field. This is a functional change, definitely touching on critical aspects of the connection process. Given the changes to the error handling and connection establishment, I think we should definitely prioritize fuzzing the `vsock_connect`, `vsock_accept`, and `vsock_pending_work` functions, especially around error conditions and concurrent connection attempts. It's time to generate some test cases. Let's call `set-results`. |
| 14/2 | 2026/08/13 19:01 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"VSOCKETS",
"VSOCKETS_LOOPBACK"
],
"FocusSymbols": [
"vsock_connect",
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core connection establishment and error handling logic for AF_VSOCK sockets. It removes the `rejected` state from pending sockets and changes how `vsock_accept` and `vsock_connect` handle socket errors. These are functional changes in reachable core networking code that should be fuzzed to ensure no regressions or memory leaks occur during connection failures.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"VSOCKETS",
"VSOCKETS_LOOPBACK"
],
"FocusSymbols": [
"vsock_connect",
"vsock_accept",
"vsock_pending_work"
],
"Reasoning": "The patch modifies the core connection establishment and error handling logic for AF_VSOCK sockets. It removes the `rejected` state from pending sockets and changes how `vsock_accept` and `vsock_connect` handle socket errors. These are functional changes in reachable core networking code that should be fuzzed to ensure no regressions or memory leaks occur during connection failures.",
"WorthFuzzing": true
} |
| 15/1 | 2026/08/13 19:01 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 16/2 | 2026/08/13 19:01 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch removes the `rejected` field from `struct vsock_sock` and simplifies error handling logic in `vsock_accept` and `vsock_connect`. It does not introduce any new structures sent to user space, nor does it add any new allocations or complex data structures. The changes do not expose any uninitialized memory risks. Any potential bugs introduced by this patch (such as use-after-free, memory leaks, or logic errors) would be effectively caught by KASAN and other standard bug detectors. Therefore, a dedicated KMSAN fuzzing session is not necessary.",
"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 dba546b60de08b0fe1a73ac464ef56dacfbe2121
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Aug 13 19:01:16 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 30046a3c20f73..3357ee62d10bf 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -52,13 +52,10 @@ struct vsock_sock {
* The listening socket is the head for both lists. Sockets created
* 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.
+ * so they can be accepted in 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..e89cb84b8d737 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -38,10 +38,9 @@
* pending socket. When that socket reaches the connected state, it is removed
* 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.
+ * from the listener socket's accept queue. 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 +48,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 +771,10 @@ 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. We just need to drop our references to
+ * the sockets and be on our way.
*/
cleanup = false;
goto out;
@@ -942,7 +938,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);
@@ -1847,12 +1842,10 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
}
- if (sk->sk_err) {
- err = -sk->sk_err;
+ err = sock_error(sk);
+ if (err) {
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
- } else {
- err = 0;
}
out_wait:
@@ -1893,7 +1886,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
- listener->sk_err == 0 && timeout != 0) {
+ timeout != 0) {
prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
release_sock(listener);
timeout = schedule_timeout(timeout);
@@ -1906,38 +1899,23 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
}
}
- if (listener->sk_err) {
- err = -listener->sk_err;
- } else if (!connected) {
+ if (!connected) {
err = -EAGAIN;
- }
-
- if (connected) {
+ } else {
sk_acceptq_removed(listener);
lock_sock_nested(connected, SINGLE_DEPTH_NESTING);
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.
- */
- if (err) {
- vconnected->rejected = true;
- } else {
- newsock->state = SS_CONNECTED;
- sock_graft(connected, newsock);
+ newsock->state = SS_CONNECTED;
+ sock_graft(connected, newsock);
- set_bit(SOCK_CUSTOM_SOCKOPT,
- &connected->sk_socket->flags);
+ set_bit(SOCK_CUSTOM_SOCKOPT,
+ &connected->sk_socket->flags);
- if (vsock_msgzerocopy_allow(vconnected->transport))
- set_bit(SOCK_SUPPORT_ZC,
- &connected->sk_socket->flags);
- }
+ if (vsock_msgzerocopy_allow(vconnected->transport))
+ set_bit(SOCK_SUPPORT_ZC,
+ &connected->sk_socket->flags);
release_sock(connected);
sock_put(connected);
|
| 17/3 | 2026/08/13 19:01 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3683 output: 146 thoughts: 583 Thoughts: **My Assessment of the vsock Patch** Okay, let's break this down. This patch is touching `af_vsock.c` and `af_vsock.h`, specifically removing the `rejected` field from `struct vsock_sock`. My initial thought is to immediately check for uninitialized memory risks. I always go through this checklist. The code changes are mostly focused on error handling within `vsock_pending_work`, `vsock_connect`, and `vsock_accept`. It looks like it's replacing direct checks of `sk->sk_err` and `listener->sk_err` with `sock_error(sk)`. At first glance, no new structures are exposed to userspace, no new memory allocations are involved, and it doesn't seem like any uninitialized fields are *being* exposed. The changes appear to be purely logic-driven, primarily related to how socket errors and connection rejections are handled. I don't see any immediate red flags. This doesn't seem like the sort of change that would expose uninitialized memory. Any bugs would likely manifest as use-after-free, memory leaks, or logic errors, which should be caught by KASAN or standard testing. However, let's zoom in on `vsock_accept` – there's a definite logic shift. The original code had a `while` loop condition that checked for both a connected socket and `listener->sk_err`, and then checked `listener->sk_err` *again* after the loop. Now, it seems that if `listener->sk_err` isn't zero, it will either return `-EAGAIN` or continue to execute. This is definitely a logic change and needs careful review, but it still seems that the change does not expose uninitialized memory. To be absolutely sure, I'll go through the KMSAN rules: Essentially, I'm checking for *my* areas of expertise -- cases where uninitialized memory might sneak through. 1. Kernel structures sent to user space where fields might not be fully initialized? No. 2. Conditional logic or branching dependent on uninitialized variables? Nope. 3. Allocation or initialization of complex data structures with uninitialized fields? Negative. 4. Bounds checks or lengths which could expose uninitialized data? Doesn't look like it. Given all of this, I'm comfortable setting `NeedsKMSAN=false` for this patch. It's a logic change, likely simplifying error handling, but not introducing any apparent memory safety concerns in the process. |
| 18/3 | 2026/08/13 19:02 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch removes the `rejected` field from `struct vsock_sock` and simplifies error handling logic in `vsock_accept` and `vsock_connect`. It does not introduce any new structures sent to user space, nor does it add any new allocations or complex data structures. The changes do not expose any uninitialized memory risks. Any potential bugs introduced by this patch (such as use-after-free, memory leaks, or logic errors) would be effectively caught by KASAN and other standard bug detectors. Therefore, a dedicated KMSAN fuzzing session is not necessary.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch removes the `rejected` field from `struct vsock_sock` and simplifies error handling logic in `vsock_accept` and `vsock_connect`. It does not introduce any new structures sent to user space, nor does it add any new allocations or complex data structures. The changes do not expose any uninitialized memory risks. Any potential bugs introduced by this patch (such as use-after-free, memory leaks, or logic errors) would be effectively caught by KASAN and other standard bug detectors. Therefore, a dedicated KMSAN fuzzing session is not necessary.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|