| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/27 19:05 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"BLK_DEV_NBD"
],
"FocusSymbols": [
"nbd_add_socket",
"nbd_genl_connect",
"nbd_genl_reconfigure",
"__nbd_ioctl",
"nbd_set_size",
"find_fallback",
"nbd_genl_foreach_sock"
],
"Reasoning": "The patch modifies the Network Block Device (NBD) driver to fix socket handling, add a module parameter for hardware queues, and refactor netlink socket parsing. These changes affect core NBD functionality reachable via ioctl and netlink, making them functional and worth fuzzing.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/27 19:05 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 0da5cf613c7e7a7b2c85ae79fc43469e101fc850\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 27 19:05:17 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/block/nbd.c b/drivers/block/nbd.c\nindex 8f10762e90ef74..1d8cdc5713eba3 100644\n--- a/drivers/block/nbd.c\n+++ b/drivers/block/nbd.c\n@@ -166,6 +166,7 @@ static struct dentry *nbd_dbg_dir;\n \n static unsigned int nbds_max = 16;\n static int max_part = 16;\n+static int nr_hw_queues = 1;\n static int part_shift;\n \n static int nbd_dev_dbg_init(struct nbd_device *nbd);\n@@ -331,7 +332,8 @@ static void nbd_mark_nsock_dead(struct nbd_device *nbd, struct nbd_sock *nsock,\n \tnsock-\u003esent = 0;\n }\n \n-static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)\n+static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize,\n+\t\t\tbool freeze)\n {\n \tstruct queue_limits lim;\n \tint error;\n@@ -371,7 +373,13 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)\n \n \tlim.logical_block_size = blksize;\n \tlim.physical_block_size = blksize;\n-\terror = queue_limits_commit_update_frozen(nbd-\u003edisk-\u003equeue, \u0026lim);\n+\n+\tif (freeze)\n+\t\terror = queue_limits_commit_update_frozen(nbd-\u003edisk-\u003equeue,\n+\t\t\t\t\u0026lim);\n+\telse\n+\t\terror = queue_limits_commit_update(nbd-\u003edisk-\u003equeue, \u0026lim);\n+\n \tif (error)\n \t\treturn error;\n \n@@ -1061,40 +1069,31 @@ static int find_fallback(struct nbd_device *nbd, int index)\n \tint new_index = -1;\n \tstruct nbd_sock *nsock = config-\u003esocks[index];\n \tint fallback = nsock-\u003efallback_index;\n+\tint i;\n \n \tif (test_bit(NBD_RT_DISCONNECTED, \u0026config-\u003eruntime_flags))\n \t\treturn new_index;\n \n-\tif (config-\u003enum_connections \u003c= 1) {\n-\t\tdev_err_ratelimited(disk_to_dev(nbd-\u003edisk),\n-\t\t\t\t \"Dead connection, failed to find a fallback\\n\");\n-\t\treturn new_index;\n-\t}\n+\tif (config-\u003enum_connections \u003c= 1)\n+\t\tgoto no_fallback;\n \n \tif (fallback \u003e= 0 \u0026\u0026 fallback \u003c config-\u003enum_connections \u0026\u0026\n \t !config-\u003esocks[fallback]-\u003edead)\n \t\treturn fallback;\n \n-\tif (nsock-\u003efallback_index \u003c 0 ||\n-\t nsock-\u003efallback_index \u003e= config-\u003enum_connections ||\n-\t config-\u003esocks[nsock-\u003efallback_index]-\u003edead) {\n-\t\tint i;\n-\t\tfor (i = 0; i \u003c config-\u003enum_connections; i++) {\n-\t\t\tif (i == index)\n-\t\t\t\tcontinue;\n-\t\t\tif (!config-\u003esocks[i]-\u003edead) {\n-\t\t\t\tnew_index = i;\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t\tnsock-\u003efallback_index = new_index;\n-\t\tif (new_index \u003c 0) {\n-\t\t\tdev_err_ratelimited(disk_to_dev(nbd-\u003edisk),\n-\t\t\t\t\t \"Dead connection, failed to find a fallback\\n\");\n-\t\t\treturn new_index;\n+\tfor (i = 0; i \u003c config-\u003enum_connections; i++) {\n+\t\tif (i != index \u0026\u0026 !config-\u003esocks[i]-\u003edead) {\n+\t\t\tnew_index = i;\n+\t\t\tbreak;\n \t\t}\n \t}\n-\tnew_index = nsock-\u003efallback_index;\n+\tnsock-\u003efallback_index = new_index;\n+\tif (new_index \u003e= 0)\n+\t\treturn new_index;\n+\n+no_fallback:\n+\tdev_err_ratelimited(disk_to_dev(nbd-\u003edisk),\n+\t\t\t \"Dead connection, failed to find a fallback\\n\");\n \treturn new_index;\n }\n \n@@ -1281,23 +1280,23 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,\n \tstruct socket *sock;\n \tstruct nbd_sock **socks;\n \tstruct nbd_sock *nsock;\n-\tunsigned int memflags;\n \tint err;\n \n \t/* Arg will be cast to int, check it to avoid overflow */\n \tif (arg \u003e INT_MAX)\n \t\treturn -EINVAL;\n+\n+\tif (nbd-\u003epid) {\n+\t\tdev_err(disk_to_dev(nbd-\u003edisk),\n+\t\t\t\"Cannot add socket to a running device\\n\");\n+\t\treturn -EBUSY;\n+\t}\n+\n \tsock = nbd_get_socket(nbd, arg, \u0026err);\n \tif (!sock)\n \t\treturn err;\n \tnbd_reclassify_socket(sock);\n \n-\t/*\n-\t * We need to make sure we don't get any errant requests while we're\n-\t * reallocating the -\u003esocks array.\n-\t */\n-\tmemflags = blk_mq_freeze_queue(nbd-\u003edisk-\u003equeue);\n-\n \tif (!netlink \u0026\u0026 !nbd-\u003etask_setup \u0026\u0026\n \t !test_bit(NBD_RT_BOUND, \u0026config-\u003eruntime_flags))\n \t\tnbd-\u003etask_setup = current;\n@@ -1337,12 +1336,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,\n \tINIT_WORK(\u0026nsock-\u003ework, nbd_pending_cmd_work);\n \tsocks[config-\u003enum_connections++] = nsock;\n \tatomic_inc(\u0026config-\u003elive_connections);\n-\tblk_mq_unfreeze_queue(nbd-\u003edisk-\u003equeue, memflags);\n \n \treturn 0;\n \n put_socket:\n-\tblk_mq_unfreeze_queue(nbd-\u003edisk-\u003equeue, memflags);\n \tsockfd_put(sock);\n \treturn err;\n }\n@@ -1574,7 +1571,7 @@ static int nbd_start_device(struct nbd_device *nbd)\n \t\targs-\u003eindex = i;\n \t\tqueue_work(nbd-\u003erecv_workq, \u0026args-\u003ework);\n \t}\n-\treturn nbd_set_size(nbd, config-\u003ebytesize, nbd_blksize(config));\n+\treturn nbd_set_size(nbd, config-\u003ebytesize, nbd_blksize(config), false);\n }\n \n static int nbd_start_device_ioctl(struct nbd_device *nbd)\n@@ -1642,13 +1639,13 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,\n \tcase NBD_SET_SOCK:\n \t\treturn nbd_add_socket(nbd, arg, false);\n \tcase NBD_SET_BLKSIZE:\n-\t\treturn nbd_set_size(nbd, config-\u003ebytesize, arg);\n+\t\treturn nbd_set_size(nbd, config-\u003ebytesize, arg, true);\n \tcase NBD_SET_SIZE:\n-\t\treturn nbd_set_size(nbd, arg, nbd_blksize(config));\n+\t\treturn nbd_set_size(nbd, arg, nbd_blksize(config), true);\n \tcase NBD_SET_SIZE_BLOCKS:\n \t\tif (check_shl_overflow(arg, config-\u003eblksize_bits, \u0026bytesize))\n \t\t\treturn -EINVAL;\n-\t\treturn nbd_set_size(nbd, bytesize, nbd_blksize(config));\n+\t\treturn nbd_set_size(nbd, bytesize, nbd_blksize(config), true);\n \tcase NBD_SET_TIMEOUT:\n \t\tnbd_set_cmd_timeout(nbd, arg);\n \t\treturn 0;\n@@ -1941,7 +1938,8 @@ static const struct blk_mq_ops nbd_mq_ops = {\n \t.timeout\t= nbd_xmit_timeout,\n };\n \n-static struct nbd_device *nbd_dev_add(int index, unsigned int refs)\n+static struct nbd_device *nbd_dev_add(int index, unsigned int refs,\n+\t\t\t\t int nr_hw_queues)\n {\n \tstruct queue_limits lim = {\n \t\t.max_hw_sectors\t\t= 65536,\n@@ -1958,7 +1956,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)\n \t\tgoto out;\n \n \tnbd-\u003etag_set.ops = \u0026nbd_mq_ops;\n-\tnbd-\u003etag_set.nr_hw_queues = 1;\n+\tnbd-\u003etag_set.nr_hw_queues = nr_hw_queues;\n \tnbd-\u003etag_set.queue_depth = 128;\n \tnbd-\u003etag_set.numa_node = NUMA_NO_NODE;\n \tnbd-\u003etag_set.cmd_size = sizeof(struct nbd_cmd);\n@@ -2103,10 +2101,63 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd)\n \t\tbsize = nla_get_u64(info-\u003eattrs[NBD_ATTR_BLOCK_SIZE_BYTES]);\n \n \tif (bytes != config-\u003ebytesize || bsize != nbd_blksize(config))\n-\t\treturn nbd_set_size(nbd, bytes, bsize);\n+\t\treturn nbd_set_size(nbd, bytes, bsize, true);\n \treturn 0;\n }\n \n+/*\n+ * Walk the NBD_ATTR_SOCKETS nested list can call @cb for each socket fd.\n+ *\n+ * Return the number of fds walked, or a negative errno.\n+ */\n+static int nbd_genl_foreach_sock(struct genl_info *info,\n+\t\tint (*cb)(struct nbd_device *nbd, int fd),\n+\t\tstruct nbd_device *nbd)\n+{\n+\tstruct nlattr *attr;\n+\tint rem, count = 0;\n+\n+\tif (!info-\u003eattrs[NBD_ATTR_SOCKETS])\n+\t\treturn 0;\n+\n+\tnla_for_each_nested(attr, info-\u003eattrs[NBD_ATTR_SOCKETS], rem) {\n+\t\tstruct nlattr *socks[NBD_SOCK_MAX + 1];\n+\t\tint ret;\n+\n+\t\tif (nla_type(attr) != NBD_SOCK_ITEM) {\n+\t\t\tpr_err(\"socks must be embedded in a SOCK_ITEM attr\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,\n+\t\t\t\t\t\tattr,\n+\t\t\t\t\t\tnbd_sock_policy,\n+\t\t\t\t\t\tinfo-\u003eextack)) {\n+\t\t\tpr_err(\"error processing sock list\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tif (!socks[NBD_SOCK_FD])\n+\t\t\tcontinue;\n+\n+\t\tcount++;\n+\t\tif (cb) {\n+\t\t\tret = cb(nbd, (int)nla_get_u32(socks[NBD_SOCK_FD]));\n+\t\t\tif (ret \u003e 0)\n+\t\t\t\treturn count;\n+\t\t\tif (ret \u003c 0)\n+\t\t\t\treturn ret;\n+\n+\t\t}\n+\t}\n+\treturn count;\n+}\n+\n+static int nbd_genl_connect_sock_cb(struct nbd_device *nbd, int fd)\n+{\n+\treturn nbd_add_socket(nbd, fd, true);\n+}\n+\n static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)\n {\n \tstruct nbd_device *nbd;\n@@ -2159,7 +2210,11 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)\n \tmutex_unlock(\u0026nbd_index_mutex);\n \n \tif (!nbd) {\n-\t\tnbd = nbd_dev_add(index, 2);\n+\t\tret = nbd_genl_foreach_sock(info, NULL, NULL);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tnbd = nbd_dev_add(index, 2, ret \u003e 0 ? ret : 1);\n \t\tif (IS_ERR(nbd)) {\n \t\t\tpr_err(\"failed to add new device\\n\");\n \t\t\treturn PTR_ERR(nbd);\n@@ -2226,36 +2281,9 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)\n \t\t}\n \t}\n \n-\tif (info-\u003eattrs[NBD_ATTR_SOCKETS]) {\n-\t\tstruct nlattr *attr;\n-\t\tint rem, fd;\n-\n-\t\tnla_for_each_nested(attr, info-\u003eattrs[NBD_ATTR_SOCKETS],\n-\t\t\t\t rem) {\n-\t\t\tstruct nlattr *socks[NBD_SOCK_MAX+1];\n-\n-\t\t\tif (nla_type(attr) != NBD_SOCK_ITEM) {\n-\t\t\t\tpr_err(\"socks must be embedded in a SOCK_ITEM attr\\n\");\n-\t\t\t\tret = -EINVAL;\n-\t\t\t\tgoto out;\n-\t\t\t}\n-\t\t\tret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,\n-\t\t\t\t\t\t\t attr,\n-\t\t\t\t\t\t\t nbd_sock_policy,\n-\t\t\t\t\t\t\t info-\u003eextack);\n-\t\t\tif (ret != 0) {\n-\t\t\t\tpr_err(\"error processing sock list\\n\");\n-\t\t\t\tret = -EINVAL;\n-\t\t\t\tgoto out;\n-\t\t\t}\n-\t\t\tif (!socks[NBD_SOCK_FD])\n-\t\t\t\tcontinue;\n-\t\t\tfd = (int)nla_get_u32(socks[NBD_SOCK_FD]);\n-\t\t\tret = nbd_add_socket(nbd, fd, true);\n-\t\t\tif (ret)\n-\t\t\t\tgoto out;\n-\t\t}\n-\t}\n+\tret = nbd_genl_foreach_sock(info, nbd_genl_connect_sock_cb, nbd);\n+\tif (ret \u003c 0)\n+\t\tgoto out;\n \n \tif (info-\u003eattrs[NBD_ATTR_BACKEND_IDENTIFIER]) {\n \t\tnbd-\u003ebackend = nla_strdup(info-\u003eattrs[NBD_ATTR_BACKEND_IDENTIFIER],\n@@ -2344,6 +2372,20 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)\n \treturn 0;\n }\n \n+static int nbd_genl_reconnect_sock_cb(struct nbd_device *nbd, int fd)\n+{\n+\tint ret = nbd_reconnect_socket(nbd, fd);\n+\n+\tif (!ret) {\n+\t\tdev_info(nbd_to_dev(nbd), \"reconnected socket\\n\");\n+\t\treturn 0;\n+\t}\n+\n+\tif (ret == -ENOSPC)\n+\t\treturn 1;\n+\treturn ret;\n+}\n+\n static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)\n {\n \tstruct nbd_device *nbd = NULL;\n@@ -2440,40 +2482,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)\n \t\t}\n \t}\n \n-\tif (info-\u003eattrs[NBD_ATTR_SOCKETS]) {\n-\t\tstruct nlattr *attr;\n-\t\tint rem, fd;\n-\n-\t\tnla_for_each_nested(attr, info-\u003eattrs[NBD_ATTR_SOCKETS],\n-\t\t\t\t rem) {\n-\t\t\tstruct nlattr *socks[NBD_SOCK_MAX+1];\n-\n-\t\t\tif (nla_type(attr) != NBD_SOCK_ITEM) {\n-\t\t\t\tpr_err(\"socks must be embedded in a SOCK_ITEM attr\\n\");\n-\t\t\t\tret = -EINVAL;\n-\t\t\t\tgoto out;\n-\t\t\t}\n-\t\t\tret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,\n-\t\t\t\t\t\t\t attr,\n-\t\t\t\t\t\t\t nbd_sock_policy,\n-\t\t\t\t\t\t\t info-\u003eextack);\n-\t\t\tif (ret != 0) {\n-\t\t\t\tpr_err(\"error processing sock list\\n\");\n-\t\t\t\tret = -EINVAL;\n-\t\t\t\tgoto out;\n-\t\t\t}\n-\t\t\tif (!socks[NBD_SOCK_FD])\n-\t\t\t\tcontinue;\n-\t\t\tfd = (int)nla_get_u32(socks[NBD_SOCK_FD]);\n-\t\t\tret = nbd_reconnect_socket(nbd, fd);\n-\t\t\tif (ret) {\n-\t\t\t\tif (ret == -ENOSPC)\n-\t\t\t\t\tret = 0;\n-\t\t\t\tgoto out;\n-\t\t\t}\n-\t\t\tdev_info(nbd_to_dev(nbd), \"reconnected socket\\n\");\n-\t\t}\n-\t}\n+\tret = nbd_genl_foreach_sock(info, nbd_genl_reconnect_sock_cb, nbd);\n out:\n \tmutex_unlock(\u0026nbd-\u003econfig_lock);\n \tnbd_config_put(nbd);\n@@ -2725,8 +2734,10 @@ static int __init nbd_init(void)\n \t}\n \tnbd_dbg_init();\n \n+\tif (nr_hw_queues \u003c 1)\n+\t\tnr_hw_queues = 1;\n \tfor (i = 0; i \u003c nbds_max; i++)\n-\t\tnbd_dev_add(i, 1);\n+\t\tnbd_dev_add(i, 1, nr_hw_queues);\n \treturn 0;\n }\n \n@@ -2787,3 +2798,6 @@ module_param(nbds_max, int, 0444);\n MODULE_PARM_DESC(nbds_max, \"number of network block devices to initialize (default: 16)\");\n module_param(max_part, int, 0444);\n MODULE_PARM_DESC(max_part, \"number of partitions per device (default: 16)\");\n+module_param(nr_hw_queues, int, 0444);\n+MODULE_PARM_DESC(nr_hw_queues,\n+\"number of hardware queues for devices pre-created at module load (default: 1). \");\n"
} |
| 2/1 | 2026/07/27 19:05 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"BLK_DEV_NBD"
],
"FocusSymbols": [
"nbd_add_socket",
"nbd_genl_connect",
"nbd_genl_reconfigure",
"__nbd_ioctl",
"nbd_set_size",
"find_fallback",
"nbd_genl_foreach_sock"
],
"Reasoning": "The patch modifies the Network Block Device (NBD) driver to fix socket handling, add a module parameter for hardware queues, and refactor netlink socket parsing. These changes affect core NBD functionality reachable via ioctl and netlink, making them functional and worth fuzzing.",
"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 0da5cf613c7e7a7b2c85ae79fc43469e101fc850
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 27 19:05:17 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 8f10762e90ef74..1d8cdc5713eba3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -166,6 +166,7 @@ static struct dentry *nbd_dbg_dir;
static unsigned int nbds_max = 16;
static int max_part = 16;
+static int nr_hw_queues = 1;
static int part_shift;
static int nbd_dev_dbg_init(struct nbd_device *nbd);
@@ -331,7 +332,8 @@ static void nbd_mark_nsock_dead(struct nbd_device *nbd, struct nbd_sock *nsock,
nsock->sent = 0;
}
-static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)
+static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize,
+ bool freeze)
{
struct queue_limits lim;
int error;
@@ -371,7 +373,13 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)
lim.logical_block_size = blksize;
lim.physical_block_size = blksize;
- error = queue_limits_commit_update_frozen(nbd->disk->queue, &lim);
+
+ if (freeze)
+ error = queue_limits_commit_update_frozen(nbd->disk->queue,
+ &lim);
+ else
+ error = queue_limits_commit_update(nbd->disk->queue, &lim);
+
if (error)
return error;
@@ -1061,40 +1069,31 @@ static int find_fallback(struct nbd_device *nbd, int index)
int new_index = -1;
struct nbd_sock *nsock = config->socks[index];
int fallback = nsock->fallback_index;
+ int i;
if (test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags))
return new_index;
- if (config->num_connections <= 1) {
- dev_err_ratelimited(disk_to_dev(nbd->disk),
- "Dead connection, failed to find a fallback\n");
- return new_index;
- }
+ if (config->num_connections <= 1)
+ goto no_fallback;
if (fallback >= 0 && fallback < config->num_connections &&
!config->socks[fallback]->dead)
return fallback;
- if (nsock->fallback_index < 0 ||
- nsock->fallback_index >= config->num_connections ||
- config->socks[nsock->fallback_index]->dead) {
- int i;
- for (i = 0; i < config->num_connections; i++) {
- if (i == index)
- continue;
- if (!config->socks[i]->dead) {
- new_index = i;
- break;
- }
- }
- nsock->fallback_index = new_index;
- if (new_index < 0) {
- dev_err_ratelimited(disk_to_dev(nbd->disk),
- "Dead connection, failed to find a fallback\n");
- return new_index;
+ for (i = 0; i < config->num_connections; i++) {
+ if (i != index && !config->socks[i]->dead) {
+ new_index = i;
+ break;
}
}
- new_index = nsock->fallback_index;
+ nsock->fallback_index = new_index;
+ if (new_index >= 0)
+ return new_index;
+
+no_fallback:
+ dev_err_ratelimited(disk_to_dev(nbd->disk),
+ "Dead connection, failed to find a fallback\n");
return new_index;
}
@@ -1281,23 +1280,23 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
struct socket *sock;
struct nbd_sock **socks;
struct nbd_sock *nsock;
- unsigned int memflags;
int err;
/* Arg will be cast to int, check it to avoid overflow */
if (arg > INT_MAX)
return -EINVAL;
+
+ if (nbd->pid) {
+ dev_err(disk_to_dev(nbd->disk),
+ "Cannot add socket to a running device\n");
+ return -EBUSY;
+ }
+
sock = nbd_get_socket(nbd, arg, &err);
if (!sock)
return err;
nbd_reclassify_socket(sock);
- /*
- * We need to make sure we don't get any errant requests while we're
- * reallocating the ->socks array.
- */
- memflags = blk_mq_freeze_queue(nbd->disk->queue);
-
if (!netlink && !nbd->task_setup &&
!test_bit(NBD_RT_BOUND, &config->runtime_flags))
nbd->task_setup = current;
@@ -1337,12 +1336,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
INIT_WORK(&nsock->work, nbd_pending_cmd_work);
socks[config->num_connections++] = nsock;
atomic_inc(&config->live_connections);
- blk_mq_unfreeze_queue(nbd->disk->queue, memflags);
return 0;
put_socket:
- blk_mq_unfreeze_queue(nbd->disk->queue, memflags);
sockfd_put(sock);
return err;
}
@@ -1574,7 +1571,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
- return nbd_set_size(nbd, config->bytesize, nbd_blksize(config));
+ return nbd_set_size(nbd, config->bytesize, nbd_blksize(config), false);
}
static int nbd_start_device_ioctl(struct nbd_device *nbd)
@@ -1642,13 +1639,13 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
case NBD_SET_SOCK:
return nbd_add_socket(nbd, arg, false);
case NBD_SET_BLKSIZE:
- return nbd_set_size(nbd, config->bytesize, arg);
+ return nbd_set_size(nbd, config->bytesize, arg, true);
case NBD_SET_SIZE:
- return nbd_set_size(nbd, arg, nbd_blksize(config));
+ return nbd_set_size(nbd, arg, nbd_blksize(config), true);
case NBD_SET_SIZE_BLOCKS:
if (check_shl_overflow(arg, config->blksize_bits, &bytesize))
return -EINVAL;
- return nbd_set_size(nbd, bytesize, nbd_blksize(config));
+ return nbd_set_size(nbd, bytesize, nbd_blksize(config), true);
case NBD_SET_TIMEOUT:
nbd_set_cmd_timeout(nbd, arg);
return 0;
@@ -1941,7 +1938,8 @@ static const struct blk_mq_ops nbd_mq_ops = {
.timeout = nbd_xmit_timeout,
};
-static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
+static struct nbd_device *nbd_dev_add(int index, unsigned int refs,
+ int nr_hw_queues)
{
struct queue_limits lim = {
.max_hw_sectors = 65536,
@@ -1958,7 +1956,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
goto out;
nbd->tag_set.ops = &nbd_mq_ops;
- nbd->tag_set.nr_hw_queues = 1;
+ nbd->tag_set.nr_hw_queues = nr_hw_queues;
nbd->tag_set.queue_depth = 128;
nbd->tag_set.numa_node = NUMA_NO_NODE;
nbd->tag_set.cmd_size = sizeof(struct nbd_cmd);
@@ -2103,10 +2101,63 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd)
bsize = nla_get_u64(info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]);
if (bytes != config->bytesize || bsize != nbd_blksize(config))
- return nbd_set_size(nbd, bytes, bsize);
+ return nbd_set_size(nbd, bytes, bsize, true);
return 0;
}
+/*
+ * Walk the NBD_ATTR_SOCKETS nested list can call @cb for each socket fd.
+ *
+ * Return the number of fds walked, or a negative errno.
+ */
+static int nbd_genl_foreach_sock(struct genl_info *info,
+ int (*cb)(struct nbd_device *nbd, int fd),
+ struct nbd_device *nbd)
+{
+ struct nlattr *attr;
+ int rem, count = 0;
+
+ if (!info->attrs[NBD_ATTR_SOCKETS])
+ return 0;
+
+ nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS], rem) {
+ struct nlattr *socks[NBD_SOCK_MAX + 1];
+ int ret;
+
+ if (nla_type(attr) != NBD_SOCK_ITEM) {
+ pr_err("socks must be embedded in a SOCK_ITEM attr\n");
+ return -EINVAL;
+ }
+
+ if (nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,
+ attr,
+ nbd_sock_policy,
+ info->extack)) {
+ pr_err("error processing sock list\n");
+ return -EINVAL;
+ }
+
+ if (!socks[NBD_SOCK_FD])
+ continue;
+
+ count++;
+ if (cb) {
+ ret = cb(nbd, (int)nla_get_u32(socks[NBD_SOCK_FD]));
+ if (ret > 0)
+ return count;
+ if (ret < 0)
+ return ret;
+
+ }
+ }
+ return count;
+}
+
+static int nbd_genl_connect_sock_cb(struct nbd_device *nbd, int fd)
+{
+ return nbd_add_socket(nbd, fd, true);
+}
+
static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd;
@@ -2159,7 +2210,11 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
mutex_unlock(&nbd_index_mutex);
if (!nbd) {
- nbd = nbd_dev_add(index, 2);
+ ret = nbd_genl_foreach_sock(info, NULL, NULL);
+ if (ret < 0)
+ return ret;
+
+ nbd = nbd_dev_add(index, 2, ret > 0 ? ret : 1);
if (IS_ERR(nbd)) {
pr_err("failed to add new device\n");
return PTR_ERR(nbd);
@@ -2226,36 +2281,9 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
}
}
- if (info->attrs[NBD_ATTR_SOCKETS]) {
- struct nlattr *attr;
- int rem, fd;
-
- nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS],
- rem) {
- struct nlattr *socks[NBD_SOCK_MAX+1];
-
- if (nla_type(attr) != NBD_SOCK_ITEM) {
- pr_err("socks must be embedded in a SOCK_ITEM attr\n");
- ret = -EINVAL;
- goto out;
- }
- ret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,
- attr,
- nbd_sock_policy,
- info->extack);
- if (ret != 0) {
- pr_err("error processing sock list\n");
- ret = -EINVAL;
- goto out;
- }
- if (!socks[NBD_SOCK_FD])
- continue;
- fd = (int)nla_get_u32(socks[NBD_SOCK_FD]);
- ret = nbd_add_socket(nbd, fd, true);
- if (ret)
- goto out;
- }
- }
+ ret = nbd_genl_foreach_sock(info, nbd_genl_connect_sock_cb, nbd);
+ if (ret < 0)
+ goto out;
if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) {
nbd->backend = nla_strdup(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER],
@@ -2344,6 +2372,20 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
return 0;
}
+static int nbd_genl_reconnect_sock_cb(struct nbd_device *nbd, int fd)
+{
+ int ret = nbd_reconnect_socket(nbd, fd);
+
+ if (!ret) {
+ dev_info(nbd_to_dev(nbd), "reconnected socket\n");
+ return 0;
+ }
+
+ if (ret == -ENOSPC)
+ return 1;
+ return ret;
+}
+
static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd = NULL;
@@ -2440,40 +2482,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
}
- if (info->attrs[NBD_ATTR_SOCKETS]) {
- struct nlattr *attr;
- int rem, fd;
-
- nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS],
- rem) {
- struct nlattr *socks[NBD_SOCK_MAX+1];
-
- if (nla_type(attr) != NBD_SOCK_ITEM) {
- pr_err("socks must be embedded in a SOCK_ITEM attr\n");
- ret = -EINVAL;
- goto out;
- }
- ret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX,
- attr,
- nbd_sock_policy,
- info->extack);
- if (ret != 0) {
- pr_err("error processing sock list\n");
- ret = -EINVAL;
- goto out;
- }
- if (!socks[NBD_SOCK_FD])
- continue;
- fd = (int)nla_get_u32(socks[NBD_SOCK_FD]);
- ret = nbd_reconnect_socket(nbd, fd);
- if (ret) {
- if (ret == -ENOSPC)
- ret = 0;
- goto out;
- }
- dev_info(nbd_to_dev(nbd), "reconnected socket\n");
- }
- }
+ ret = nbd_genl_foreach_sock(info, nbd_genl_reconnect_sock_cb, nbd);
out:
mutex_unlock(&nbd->config_lock);
nbd_config_put(nbd);
@@ -2725,8 +2734,10 @@ static int __init nbd_init(void)
}
nbd_dbg_init();
+ if (nr_hw_queues < 1)
+ nr_hw_queues = 1;
for (i = 0; i < nbds_max; i++)
- nbd_dev_add(i, 1);
+ nbd_dev_add(i, 1, nr_hw_queues);
return 0;
}
@@ -2787,3 +2798,6 @@ module_param(nbds_max, int, 0444);
MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
module_param(max_part, int, 0444);
MODULE_PARM_DESC(max_part, "number of partitions per device (default: 16)");
+module_param(nr_hw_queues, int, 0444);
+MODULE_PARM_DESC(nr_hw_queues,
+"number of hardware queues for devices pre-created at module load (default: 1). ");
|
| 3/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6674 output: 27 thoughts: 150 Thoughts: **Analyzing the NBD Driver Patch** Okay, so I'm looking at this patch for `drivers/block/nbd.c`. Immediately, I see it's a functional modification, and not just a bug fix. It's adding a module parameter, `nr_hw_queues`, which suggests some performance or resource tuning is being introduced at module load time. The `nbd_set_size` change with a `freeze` parameter raises my eyebrows a bit – sounds like there's some deeper interaction with the block layer's freezing mechanisms happening, likely to ensure data consistency during size adjustments. The refactoring of `find_fallback` is interesting. I'll need to dig into the context of *why* it needed to be changed, and if this relates to any underlying changes in error handling. Preventing the addition of sockets to a *running* device in `nbd_add_socket` is a good practice to prevent unintended race conditions, especially if there's no suitable locking in place. Removing `blk_mq_freeze_queue` from `nbd_add_socket` is curious. Perhaps the freezing is handled elsewhere, or perhaps it's deemed unnecessary now. That requires an examination of the added logic that takes its place. Finally, the refactoring of socket parsing in netlink operations, `nbd_genl_foreach_sock`, indicates changes to the control plane, which means there may be additions to ioctl commands as well. NBD is reachable via ioctl and netlink, which are common access points. I should probably focus on finding the right configuration file for NBD. I know NBD is often configured with kernel parameters, and possibly via sysfs. This is going to require some deeper investigation of the associated kernel documentation and source code to fully grasp the ramifications of these changes. |
| 4/2 | 2026/07/27 19:05 | tool | grepper |
0mError:no matches Args: {
"Expression": "config NBD",
"PathPrefix": "drivers/block/"
}Results: {
"error": "no matches"
} |
| 5/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7248 output: 32 thoughts: 12 Thoughts: Okay, here's my summary, presented as a stream of thought: **Diving into the Block Driver Configuration** Right, let's get down to brass tacks. I need to understand the configuration options for the block drivers. Where else to start but the source? Specifically, the `drivers/block` directory. I'm going to navigate over there and dive into those Kconfig files. This is where the real meat of the build-time configuration lies for block devices. I want to see how features are enabled and disabled, dependencies, and any subtleties in the configuration logic. This will give me a solid foundation for understanding the system's block device behavior. Time to get my hands dirty. |
| 6/2 | 2026/07/27 19:05 | tool | grepper |
0mArgs:{
"Expression": "config BLK_DEV_NBD",
"PathPrefix": "drivers/block/"
}Results: {
"Output": "drivers/block/Kconfig=194=source \"drivers/block/drbd/Kconfig\"\ndrivers/block/Kconfig-195-\ndrivers/block/Kconfig:196:config BLK_DEV_NBD\ndrivers/block/Kconfig-197-\ttristate \"Network block device support\"\n"
} |
| 7/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7529 output: 34 thoughts: 289 Thoughts: **Fuzzing Target Prioritization for NBD Driver** Alright, the configuration specifically enables `BLK_DEV_NBD`. Good. Now I need to quickly assess the modified functions to identify promising targets for fuzzing within the NBD driver. Let's see... the diff includes: `nbd_set_size`, `find_fallback`, `nbd_add_socket`, `nbd_start_device` and a `_ioctl` version, and of course all the genl (netlink) functions. Specifically, it looks like `nbd_genl_foreach_sock`, `nbd_genl_connect_sock_cb`, and `nbd_genl_reconnect_sock_cb` are all new, which warrants some extra attention. Given the changes and the potential attack surface, my instinct is to prioritize the following functions for fuzzing efforts: `nbd_add_socket`, `nbd_genl_connect`, `nbd_genl_reconfigure`, `__nbd_ioctl`, `nbd_set_size`, and `find_fallback`. These seem like the most likely entry points for triggering interesting behavior, and they all touch the core operations of the NBD driver. I'll start with a closer look at `nbd_add_socket` and `nbd_genl_connect` to get a better handle on their inputs and potential vulnerabilities. These are logical starting points. |
| 8/2 | 2026/07/27 19:05 | tool | grepper |
0mArgs:{
"Expression": "nbd_add_socket",
"PathPrefix": "drivers/block/nbd.c"
}Results: {
"Output": "drivers/block/nbd.c=1273=static inline void nbd_reclassify_socket(struct socket *sock) {}\n--\ndrivers/block/nbd.c-1275-\ndrivers/block/nbd.c:1276:static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,\ndrivers/block/nbd.c-1277-\t\t\t bool netlink)\n--\ndrivers/block/nbd.c=1627=static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,\n--\ndrivers/block/nbd.c-1639-\tcase NBD_SET_SOCK:\ndrivers/block/nbd.c:1640:\t\treturn nbd_add_socket(nbd, arg, false);\ndrivers/block/nbd.c-1641-\tcase NBD_SET_BLKSIZE:\n--\ndrivers/block/nbd.c=2156=static int nbd_genl_connect_sock_cb(struct nbd_device *nbd, int fd)\ndrivers/block/nbd.c-2157-{\ndrivers/block/nbd.c:2158:\treturn nbd_add_socket(nbd, fd, true);\ndrivers/block/nbd.c-2159-}\n"
} |
| 9/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8508 output: 62 thoughts: 231 Thoughts: **Analyzing the NBD Configuration and API** Okay, so I'm looking at these NBD changes. They seem to be functional and definitely reachable through `ioctl` and `netlink`, which is good. The relevant configuration setting is `BLK_DEV_NBD`, got it. Now, let's zero in on the key symbols, as I see them. I'm focusing on `nbd_add_socket`, `nbd_genl_connect`, `nbd_genl_reconfigure`, `__nbd_ioctl`, `nbd_set_size`, and the mysterious `find_fallback`. Right, time to check if `find_fallback` is static. Yes, it's static. Fine. And `nbd_set_size` is static. `nbd_add_socket` is static. And `nbd_genl_connect` and `nbd_genl_reconfigure`, also static. Finally, `__nbd_ioctl` is static as well. Hmm, but wait. The instructions are telling me something: "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)." Okay, so, all these functions I checked are static... that's a clue. I need to now go hunting for the non-static functions in `nbd.c`. I have a feeling I'm going to find the real API entry points there. |
| 10/2 | 2026/07/27 19:05 | tool | grepper |
0mArgs:{
"Expression": "^(static )?(int|void|struct [a-zA-Z0-9_]+ \\*) [a-zA-Z0-9_]+\\(",
"PathPrefix": "drivers/block/nbd.c"
}Results: {
"Output": "drivers/block/nbd.c=170=static int part_shift;\ndrivers/block/nbd.c-171-\ndrivers/block/nbd.c:172:static int nbd_dev_dbg_init(struct nbd_device *nbd);\ndrivers/block/nbd.c:173:static void nbd_dev_dbg_close(struct nbd_device *nbd);\ndrivers/block/nbd.c:174:static void nbd_config_put(struct nbd_device *nbd);\ndrivers/block/nbd.c:175:static void nbd_connect_reply(struct genl_info *info, int index);\ndrivers/block/nbd.c:176:static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);\ndrivers/block/nbd.c:177:static void nbd_dead_link_work(struct work_struct *work);\ndrivers/block/nbd.c:178:static void nbd_disconnect_and_put(struct nbd_device *nbd);\ndrivers/block/nbd.c-179-\ndrivers/block/nbd.c=180=static inline struct device *nbd_to_dev(struct nbd_device *nbd)\n--\ndrivers/block/nbd.c-184-\ndrivers/block/nbd.c:185:static void nbd_requeue_cmd(struct nbd_cmd *cmd)\ndrivers/block/nbd.c-186-{\n--\ndrivers/block/nbd.c=260=static const struct device_attribute backend_attr = {\n--\ndrivers/block/nbd.c-264-\ndrivers/block/nbd.c:265:static void nbd_dev_remove(struct nbd_device *nbd)\ndrivers/block/nbd.c-266-{\n--\ndrivers/block/nbd.c-282-\ndrivers/block/nbd.c:283:static void nbd_dev_remove_work(struct work_struct *work)\ndrivers/block/nbd.c-284-{\n--\ndrivers/block/nbd.c-287-\ndrivers/block/nbd.c:288:static void nbd_put(struct nbd_device *nbd)\ndrivers/block/nbd.c-289-{\n--\ndrivers/block/nbd.c-299-\ndrivers/block/nbd.c:300:static int nbd_disconnected(struct nbd_config *config)\ndrivers/block/nbd.c-301-{\n--\ndrivers/block/nbd.c-305-\ndrivers/block/nbd.c:306:static void nbd_mark_nsock_dead(struct nbd_device *nbd, struct nbd_sock *nsock,\ndrivers/block/nbd.c-307-\t\t\t\tint notify)\n--\ndrivers/block/nbd.c-334-\ndrivers/block/nbd.c:335:static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize,\ndrivers/block/nbd.c-336-\t\t\tbool freeze)\n--\ndrivers/block/nbd.c-392-\ndrivers/block/nbd.c:393:static void nbd_complete_rq(struct request *req)\ndrivers/block/nbd.c-394-{\n--\ndrivers/block/nbd.c-405- */\ndrivers/block/nbd.c:406:static void sock_shutdown(struct nbd_device *nbd)\ndrivers/block/nbd.c-407-{\n--\ndrivers/block/nbd.c=459=static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req)\n--\ndrivers/block/nbd.c-558-\ndrivers/block/nbd.c:559:static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send,\ndrivers/block/nbd.c-560-\t\t struct iov_iter *iter, int msg_flags, int *sent)\n--\ndrivers/block/nbd.c-606- */\ndrivers/block/nbd.c:607:static int sock_xmit(struct nbd_device *nbd, int index, int send,\ndrivers/block/nbd.c-608-\t\t struct iov_iter *iter, int msg_flags, int *sent)\n--\ndrivers/block/nbd.c=620=static inline int was_interrupted(int result)\n--\ndrivers/block/nbd.c-632- */\ndrivers/block/nbd.c:633:static void nbd_sched_pending_work(struct nbd_device *nbd,\ndrivers/block/nbd.c-634-\t\t\t\t struct nbd_sock *nsock,\n--\ndrivers/block/nbd.c=653=static blk_status_t nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd,\n--\ndrivers/block/nbd.c-815-/* handle partial sending */\ndrivers/block/nbd.c:816:static void nbd_pending_cmd_work(struct work_struct *work)\ndrivers/block/nbd.c-817-{\n--\ndrivers/block/nbd.c-852-\ndrivers/block/nbd.c:853:static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock,\ndrivers/block/nbd.c-854-\t\t\t struct nbd_reply *reply)\n--\ndrivers/block/nbd.c=880=static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,\n--\ndrivers/block/nbd.c-977-\ndrivers/block/nbd.c:978:static void recv_work(struct work_struct *work)\ndrivers/block/nbd.c-979-{\n--\ndrivers/block/nbd.c=1038=static bool nbd_clear_req(struct request *req, void *data)\n--\ndrivers/block/nbd.c-1057-\ndrivers/block/nbd.c:1058:static void nbd_clear_que(struct nbd_device *nbd)\ndrivers/block/nbd.c-1059-{\n--\ndrivers/block/nbd.c-1065-\ndrivers/block/nbd.c:1066:static int find_fallback(struct nbd_device *nbd, int index)\ndrivers/block/nbd.c-1067-{\n--\ndrivers/block/nbd.c-1099-\ndrivers/block/nbd.c:1100:static int wait_for_reconnect(struct nbd_device *nbd)\ndrivers/block/nbd.c-1101-{\n--\ndrivers/block/nbd.c=1242=static struct lock_class_key nbd_slock_key[3];\ndrivers/block/nbd.c-1243-\ndrivers/block/nbd.c:1244:static void nbd_reclassify_socket(struct socket *sock)\ndrivers/block/nbd.c-1245-{\n--\ndrivers/block/nbd.c=1273=static inline void nbd_reclassify_socket(struct socket *sock) {}\n--\ndrivers/block/nbd.c-1275-\ndrivers/block/nbd.c:1276:static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,\ndrivers/block/nbd.c-1277-\t\t\t bool netlink)\n--\ndrivers/block/nbd.c-1346-\ndrivers/block/nbd.c:1347:static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)\ndrivers/block/nbd.c-1348-{\n--\ndrivers/block/nbd.c-1408-\ndrivers/block/nbd.c:1409:static void nbd_bdev_reset(struct nbd_device *nbd)\ndrivers/block/nbd.c-1410-{\n--\ndrivers/block/nbd.c-1415-\ndrivers/block/nbd.c:1416:static void nbd_parse_flags(struct nbd_device *nbd)\ndrivers/block/nbd.c-1417-{\n--\ndrivers/block/nbd.c-1423-\ndrivers/block/nbd.c:1424:static void send_disconnects(struct nbd_device *nbd)\ndrivers/block/nbd.c-1425-{\n--\ndrivers/block/nbd.c-1447-\ndrivers/block/nbd.c:1448:static int nbd_disconnect(struct nbd_device *nbd)\ndrivers/block/nbd.c-1449-{\n--\ndrivers/block/nbd.c-1458-\ndrivers/block/nbd.c:1459:static void nbd_clear_sock(struct nbd_device *nbd)\ndrivers/block/nbd.c-1460-{\n--\ndrivers/block/nbd.c-1465-\ndrivers/block/nbd.c:1466:static void nbd_config_put(struct nbd_device *nbd)\ndrivers/block/nbd.c-1467-{\n--\ndrivers/block/nbd.c-1504-\ndrivers/block/nbd.c:1505:static int nbd_start_device(struct nbd_device *nbd)\ndrivers/block/nbd.c-1506-{\n--\ndrivers/block/nbd.c-1576-\ndrivers/block/nbd.c:1577:static int nbd_start_device_ioctl(struct nbd_device *nbd)\ndrivers/block/nbd.c-1578-{\n--\ndrivers/block/nbd.c-1606-\ndrivers/block/nbd.c:1607:static void nbd_clear_sock_ioctl(struct nbd_device *nbd)\ndrivers/block/nbd.c-1608-{\n--\ndrivers/block/nbd.c-1616-\ndrivers/block/nbd.c:1617:static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)\ndrivers/block/nbd.c-1618-{\n--\ndrivers/block/nbd.c-1626-/* Must be called with config_lock held */\ndrivers/block/nbd.c:1627:static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,\ndrivers/block/nbd.c-1628-\t\t unsigned int cmd, unsigned long arg)\n--\ndrivers/block/nbd.c-1673-\ndrivers/block/nbd.c:1674:static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode,\ndrivers/block/nbd.c-1675-\t\t unsigned int cmd, unsigned long arg)\n--\ndrivers/block/nbd.c-1703-\ndrivers/block/nbd.c:1704:static int nbd_alloc_and_init_config(struct nbd_device *nbd)\ndrivers/block/nbd.c-1705-{\n--\ndrivers/block/nbd.c-1738-\ndrivers/block/nbd.c:1739:static int nbd_open(struct gendisk *disk, blk_mode_t mode)\ndrivers/block/nbd.c-1740-{\n--\ndrivers/block/nbd.c-1781-\ndrivers/block/nbd.c:1782:static void nbd_release(struct gendisk *disk)\ndrivers/block/nbd.c-1783-{\n--\ndrivers/block/nbd.c-1793-\ndrivers/block/nbd.c:1794:static void nbd_free_disk(struct gendisk *disk)\ndrivers/block/nbd.c-1795-{\n--\ndrivers/block/nbd.c=1801=static const struct block_device_operations nbd_fops =\n--\ndrivers/block/nbd.c-1812-\ndrivers/block/nbd.c:1813:static int nbd_dbg_tasks_show(struct seq_file *s, void *unused)\ndrivers/block/nbd.c-1814-{\n--\ndrivers/block/nbd.c=1823=DEFINE_SHOW_ATTRIBUTE(nbd_dbg_tasks);\ndrivers/block/nbd.c-1824-\ndrivers/block/nbd.c:1825:static int nbd_dbg_flags_show(struct seq_file *s, void *unused)\ndrivers/block/nbd.c-1826-{\n--\ndrivers/block/nbd.c=1852=DEFINE_SHOW_ATTRIBUTE(nbd_dbg_flags);\ndrivers/block/nbd.c-1853-\ndrivers/block/nbd.c:1854:static int nbd_dev_dbg_init(struct nbd_device *nbd)\ndrivers/block/nbd.c-1855-{\n--\ndrivers/block/nbd.c-1878-\ndrivers/block/nbd.c:1879:static void nbd_dev_dbg_close(struct nbd_device *nbd)\ndrivers/block/nbd.c-1880-{\n--\ndrivers/block/nbd.c-1883-\ndrivers/block/nbd.c:1884:static int nbd_dbg_init(void)\ndrivers/block/nbd.c-1885-{\n--\ndrivers/block/nbd.c-1896-\ndrivers/block/nbd.c:1897:static void nbd_dbg_close(void)\ndrivers/block/nbd.c-1898-{\n--\ndrivers/block/nbd.c-1903-\ndrivers/block/nbd.c:1904:static int nbd_dev_dbg_init(struct nbd_device *nbd)\ndrivers/block/nbd.c-1905-{\n--\ndrivers/block/nbd.c-1908-\ndrivers/block/nbd.c:1909:static void nbd_dev_dbg_close(struct nbd_device *nbd)\ndrivers/block/nbd.c-1910-{\n--\ndrivers/block/nbd.c-1912-\ndrivers/block/nbd.c:1913:static int nbd_dbg_init(void)\ndrivers/block/nbd.c-1914-{\n--\ndrivers/block/nbd.c-1917-\ndrivers/block/nbd.c:1918:static void nbd_dbg_close(void)\ndrivers/block/nbd.c-1919-{\n--\ndrivers/block/nbd.c-1923-\ndrivers/block/nbd.c:1924:static int nbd_init_request(struct blk_mq_tag_set *set, struct request *rq,\ndrivers/block/nbd.c-1925-\t\t\t unsigned int hctx_idx, int numa_node)\n--\ndrivers/block/nbd.c=2086=nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] = {\n--\ndrivers/block/nbd.c-2090-\ndrivers/block/nbd.c:2091:static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd)\ndrivers/block/nbd.c-2092-{\n--\ndrivers/block/nbd.c-2112- */\ndrivers/block/nbd.c:2113:static int nbd_genl_foreach_sock(struct genl_info *info,\ndrivers/block/nbd.c-2114-\t\tint (*cb)(struct nbd_device *nbd, int fd),\n--\ndrivers/block/nbd.c-2155-\ndrivers/block/nbd.c:2156:static int nbd_genl_connect_sock_cb(struct nbd_device *nbd, int fd)\ndrivers/block/nbd.c-2157-{\n--\ndrivers/block/nbd.c-2160-\ndrivers/block/nbd.c:2161:static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)\ndrivers/block/nbd.c-2162-{\n--\ndrivers/block/nbd.c-2318-\ndrivers/block/nbd.c:2319:static void nbd_disconnect_and_put(struct nbd_device *nbd)\ndrivers/block/nbd.c-2320-{\n--\ndrivers/block/nbd.c-2339-\ndrivers/block/nbd.c:2340:static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)\ndrivers/block/nbd.c-2341-{\n--\ndrivers/block/nbd.c-2374-\ndrivers/block/nbd.c:2375:static int nbd_genl_reconnect_sock_cb(struct nbd_device *nbd, int fd)\ndrivers/block/nbd.c-2376-{\n--\ndrivers/block/nbd.c-2388-\ndrivers/block/nbd.c:2389:static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)\ndrivers/block/nbd.c-2390-{\n--\ndrivers/block/nbd.c=2536=MODULE_ALIAS_GENL_FAMILY(NBD_GENL_FAMILY_NAME);\ndrivers/block/nbd.c-2537-\ndrivers/block/nbd.c:2538:static int populate_nbd_status(struct nbd_device *nbd, struct sk_buff *reply)\ndrivers/block/nbd.c-2539-{\n--\ndrivers/block/nbd.c-2566-\ndrivers/block/nbd.c:2567:static int status_cb(int id, void *ptr, void *data)\ndrivers/block/nbd.c-2568-{\n--\ndrivers/block/nbd.c-2572-\ndrivers/block/nbd.c:2573:static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info)\ndrivers/block/nbd.c-2574-{\n--\ndrivers/block/nbd.c-2632-\ndrivers/block/nbd.c:2633:static void nbd_connect_reply(struct genl_info *info, int index)\ndrivers/block/nbd.c-2634-{\n--\ndrivers/block/nbd.c-2656-\ndrivers/block/nbd.c:2657:static void nbd_mcast_index(int index)\ndrivers/block/nbd.c-2658-{\n--\ndrivers/block/nbd.c-2680-\ndrivers/block/nbd.c:2681:static void nbd_dead_link_work(struct work_struct *work)\ndrivers/block/nbd.c-2682-{\n--\ndrivers/block/nbd.c=2689=static int __init nbd_init(void)\n--\ndrivers/block/nbd.c-2743-\ndrivers/block/nbd.c:2744:static int nbd_exit_cb(int id, void *ptr, void *data)\ndrivers/block/nbd.c-2745-{\n"
} |
| 11/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14238 output: 32 thoughts: 263 Thoughts: **Analyzing the `nbd.c` Module for API Entrypoints** Okay, so I'm looking at `nbd.c` and immediately noticing something: apart from the module init and exit functions (`nbd_init` and `nbd_cleanup`), everything else seems to be static. Hmm, that's not quite what the guidelines were suggesting, is it? We're supposed to prefer non-static, non-inlined API entrypoints over static helper functions. But, since everything *is* static here, it looks like we just need to list the static ones that we want to expose. Let's see... based on the code, here's what I'm listing as candidate API entrypoints: * `nbd_add_socket` * `nbd_genl_connect` * `nbd_genl_reconfigure` * `__nbd_ioctl` * `nbd_set_size` * `find_fallback` * `nbd_genl_foreach_sock` Alright, first thing's first, I need to confirm that `nbd_add_socket` isn't magically being inlined. Nope, no `inline` keyword there. Good, that's one off the list. Now, let's consider what each of these functions *does*. `nbd_genl_connect` is an obvious one - that's our entry point for the netlink connection. Same deal with `nbd_genl_reconfigure`. And `__nbd_ioctl`... that's our ioctl entry point, making it another crucial one. Now I need to investigate the dependencies for `BLK_DEV_NBD`. That's where I need to look next. |
| 12/2 | 2026/07/27 19:05 | tool | grepper |
0mArgs:{
"Expression": "config BLK_DEV_NBD",
"PathPrefix": "drivers/block/"
}Results: {
"Output": "drivers/block/Kconfig=194=source \"drivers/block/drbd/Kconfig\"\ndrivers/block/Kconfig-195-\ndrivers/block/Kconfig:196:config BLK_DEV_NBD\ndrivers/block/Kconfig-197-\ttristate \"Network block device support\"\n"
} |
| 13/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15010 output: 34 thoughts: 16 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into the `BLK_DEV_NBD` Definition** Alright, let's get down to brass tacks. I need to make absolutely sure I'm crystal clear on the full scope and implications of `BLK_DEV_NBD`. No assumptions, no shortcuts. My mental model needs to be rock solid. I'm going to revisit the authoritative definition, the *complete* definition, not just a snippet. I want to scrutinize every detail, every nuance, every potential edge case associated with this. I know the basic concept, sure, network block device, got it. But, I'm aiming for a deep understanding, which demands a thorough review of the formal specification. I'm going to look for hidden assumptions or limitations that I may not have considered before, that could bite me later. I need to refresh my understanding and ensure that I am not missing anything that could potentially affect any of my current or planned projects. The devil is always in the details, so let's get into those details. |
| 14/2 | 2026/07/27 19:05 | tool | read-file |
0mArgs:{
"File": "drivers/block/Kconfig",
"FirstLine": 196,
"LineCount": 20
}Results: {
"Contents": " 196:\tconfig BLK_DEV_NBD\n 197:\t\ttristate \"Network block device support\"\n 198:\t\tdepends on NET\n 199:\t\thelp\n 200:\t\t Saying Y here will allow your computer to be a client for network\n 201:\t\t block devices, i.e. it will be able to use block devices exported by\n 202:\t\t servers (mount file systems on them etc.). Communication between\n 203:\t\t client and server works over TCP/IP networking, but to the client\n 204:\t\t program this is hidden: it looks like a regular local file access to\n 205:\t\t a block device special file such as /dev/nd0.\n 206:\t\n 207:\t\t Network block devices also allows you to run a block-device in\n 208:\t\t userland (making server and client physically the same computer,\n 209:\t\t communicating using the loopback network device).\n 210:\t\n 211:\t\t Read \u003cfile:Documentation/admin-guide/blockdev/nbd.rst\u003e for more information,\n 212:\t\t especially about where to find the server code, which runs in user\n 213:\t\t space and does not need special kernel support.\n 214:\t\n 215:\t\t Note that this has nothing to do with the network file systems NFS\n"
} |
| 15/2 | 2026/07/27 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15653 output: 159 thoughts: 330 Thoughts: **Analyzing the NBD Driver's Attack Surface** Okay, so the scope here seems pretty straightforward: it hinges on `NET`. Looks like `BLK_DEV_NBD` is the *only* configuration option we'll need to account for. Good, keeps things simple. Just doing a quick sanity check to be sure... yep, `NET` is standard. No surprises there. Alright, let's nail down the critical symbols. My initial target list looks like: * `nbd_add_socket` * `nbd_genl_connect` * `nbd_genl_reconfigure` * `__nbd_ioctl` * `nbd_set_size` * `find_fallback` * `nbd_genl_foreach_sock` Now, let's quickly check whether `nbd_genl_foreach_sock` is static... Yep, it is. And `nbd_genl_connect_sock_cb`? Also static. Okay, that's good information for fuzzing, helps with narrowing. So, refining that list again, just to make sure: * `nbd_add_socket` * `nbd_genl_connect` * `nbd_genl_reconfigure` * `__nbd_ioctl` * `nbd_set_size` * `find_fallback` * `nbd_genl_foreach_sock` Still no other config dependencies to consider? Good. Double-checking... Nope. So, the reasoning here is pretty clear: This patch is reworking the NBD driver, fixing socket handling, hardware queues, and the netlink socket parsing. These are all core NBD functions reachable via ioctl *and* netlink. Given that, they're prime candidates for fuzzing to probe for vulnerabilities. That sounds like a solid starting point. Time to call set-results. |
| 16/2 | 2026/07/27 19:05 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BLK_DEV_NBD"
],
"FocusSymbols": [
"nbd_add_socket",
"nbd_genl_connect",
"nbd_genl_reconfigure",
"__nbd_ioctl",
"nbd_set_size",
"find_fallback",
"nbd_genl_foreach_sock"
],
"Reasoning": "The patch modifies the Network Block Device (NBD) driver to fix socket handling, add a module parameter for hardware queues, and refactor netlink socket parsing. These changes affect core NBD functionality reachable via ioctl and netlink, making them functional and worth fuzzing.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BLK_DEV_NBD"
],
"FocusSymbols": [
"nbd_add_socket",
"nbd_genl_connect",
"nbd_genl_reconfigure",
"__nbd_ioctl",
"nbd_set_size",
"find_fallback",
"nbd_genl_foreach_sock"
],
"Reasoning": "The patch modifies the Network Block Device (NBD) driver to fix socket handling, add a module parameter for hardware queues, and refactor netlink socket parsing. These changes affect core NBD functionality reachable via ioctl and netlink, making them functional and worth fuzzing.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|