| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/12 05:24 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"PCI",
"VFIO",
"VFIO_PCI"
],
"FocusSymbols": [
"pci_reset_bus_cond",
"pci_reset_function",
"pci_reset_function_locked",
"pci_try_reset_function",
"pci_reset_bus",
"vfio_pci_core_ioctl",
"vfio_pci_core_disable",
"vfio_pci_core_enable"
],
"KMSANReasoning": "The patch modifies the PCI reset logic to prevent resetting SR-IOV Physical Functions (PFs) when Virtual Functions (VFs) are active. It introduces a conditional bus reset function (`pci_reset_bus_cond`) that accepts a callback to check devices before performing a reset. In the VFIO PCI core, it replaces a cached `reset_works` boolean with direct calls to `pci_reset_supported()` and uses the new conditional reset API to check for active VFs.\n\nThese changes are purely related to control flow, device state management, and PCI subsystem APIs. They do not introduce new data structures sent to user space, nor do they modify buffer allocations, padding, or initialization logic that could lead to uninitialized memory reads or information leaks. The `vfio_device_info` structure modified in `vfio_pci_ioctl_get_info` is already fully zero-initialized (`struct vfio_device_info info = {};`).\n\nAny potential bugs introduced by this patch (e.g., locking issues, use-after-free, or NULL pointer dereferences) would be caught by standard KASAN, LOCKDEP, and other default sanitizers. There is no risk of uninitialized memory usage that would require a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces `pci_reset_bus_cond` and modifies PCI reset functions to prevent resetting SR-IOV PFs with active VFs. It also updates VFIO PCI core to use these new checks. These are reachable core PCI and VFIO functions that can be triggered in virtualized environments.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/12 05:24 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 4c8e00cc4bae4fcb838d7780a4591c2fc148f69c\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Aug 12 05:24:52 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/pci/pci.c b/drivers/pci/pci.c\nindex 77b17b13ee615..0b4f13397da24 100644\n--- a/drivers/pci/pci.c\n+++ b/drivers/pci/pci.c\n@@ -98,6 +98,7 @@ bool pci_reset_supported(struct pci_dev *dev)\n {\n \treturn dev-\u003ereset_methods[0] != 0;\n }\n+EXPORT_SYMBOL_GPL(pci_reset_supported);\n \n #ifdef CONFIG_PCI_DOMAINS\n int pci_domains_supported = 1;\n@@ -5222,11 +5223,22 @@ int pci_reset_function(struct pci_dev *dev)\n \t\tpci_dev_lock(bridge);\n \n \tpci_dev_lock(dev);\n+\n+\t/*\n+\t * Reset of an SR-IOV PF necessarily resets any active VFs. Such resets are\n+\t * beyond the scope advertised for pci_reset_function() and variants, refuse.\n+\t */\n+\tif (pci_num_vf(dev) \u003e 0) {\n+\t\trc = -ENOTTY;\n+\t\tgoto unlock;\n+\t}\n+\n \tpci_dev_save_and_disable(dev);\n \n \trc = __pci_reset_function_locked(dev);\n \n \tpci_dev_restore(dev);\n+unlock:\n \tpci_dev_unlock(dev);\n \n \tif (bridge)\n@@ -5264,6 +5276,9 @@ int pci_reset_function_locked(struct pci_dev *dev)\n \tif (!pci_reset_supported(dev))\n \t\treturn -ENOTTY;\n \n+\tif (pci_num_vf(dev) \u003e 0)\n+\t\treturn -ENOTTY;\n+\n \tpci_dev_save_and_disable(dev);\n \n \trc = __pci_reset_function_locked(dev);\n@@ -5290,6 +5305,11 @@ int pci_try_reset_function(struct pci_dev *dev)\n \tif (!pci_dev_trylock(dev))\n \t\treturn -EAGAIN;\n \n+\tif (pci_num_vf(dev) \u003e 0) {\n+\t\tpci_dev_unlock(dev);\n+\t\treturn -ENOTTY;\n+\t}\n+\n \tpci_dev_save_and_disable(dev);\n \trc = __pci_reset_function_locked(dev);\n \tpci_dev_restore(dev);\n@@ -5548,9 +5568,36 @@ int pci_probe_reset_slot(struct pci_slot *slot)\n }\n EXPORT_SYMBOL_GPL(pci_probe_reset_slot);\n \n+/* Call @cb on every device a slot or bus reset affects, stopping on error. */\n+static int pci_walk_reset_check(struct pci_bus *bus, struct pci_slot *slot,\n+\t\t\t\tint (*cb)(struct pci_dev *dev, void *data),\n+\t\t\t\tvoid *data)\n+{\n+\tstruct pci_dev *dev;\n+\tint rc;\n+\n+\tlist_for_each_entry(dev, \u0026bus-\u003edevices, bus_list) {\n+\t\tif (slot \u0026\u0026 (!dev-\u003eslot || dev-\u003eslot != slot))\n+\t\t\tcontinue;\n+\t\trc = cb(dev, data);\n+\t\tif (rc)\n+\t\t\treturn rc;\n+\t\tif (dev-\u003esubordinate) {\n+\t\t\trc = pci_walk_reset_check(dev-\u003esubordinate,\n+\t\t\t\t\t\t NULL, cb, data);\n+\t\t\tif (rc)\n+\t\t\t\treturn rc;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n /**\n * pci_try_reset_slot - Try to reset a PCI slot\n * @slot: PCI slot to reset\n+ * @check: optional per-device callback that can abort the reset\n+ * @data: opaque argument for @check\n *\n * A PCI bus may host multiple slots, each slot may support a reset mechanism\n * independent of other slots. For instance, some slots may support slot power\n@@ -5563,7 +5610,9 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot);\n *\n * Same as above except return -EAGAIN if the slot cannot be locked\n */\n-static int pci_try_reset_slot(struct pci_slot *slot)\n+static int pci_try_reset_slot(struct pci_slot *slot,\n+\t\t\t int (*check)(struct pci_dev *dev, void *data),\n+\t\t\t void *data)\n {\n \tint rc;\n \n@@ -5572,10 +5621,14 @@ static int pci_try_reset_slot(struct pci_slot *slot)\n \t\treturn rc;\n \n \tif (pci_slot_trylock(slot)) {\n-\t\tpci_slot_save_and_disable_locked(slot);\n-\t\tmight_sleep();\n-\t\trc = pci_reset_hotplug_slot(slot-\u003ehotplug, PCI_RESET_DO_RESET);\n-\t\tpci_slot_restore_locked(slot);\n+\t\trc = check ? pci_walk_reset_check(slot-\u003ebus, slot, check, data) : 0;\n+\t\tif (!rc) {\n+\t\t\tpci_slot_save_and_disable_locked(slot);\n+\t\t\tmight_sleep();\n+\t\t\trc = pci_reset_hotplug_slot(slot-\u003ehotplug,\n+\t\t\t\t\t\t PCI_RESET_DO_RESET);\n+\t\t\tpci_slot_restore_locked(slot);\n+\t\t}\n \t\tpci_slot_unlock(slot);\n \t} else\n \t\trc = -EAGAIN;\n@@ -5607,10 +5660,14 @@ static int pci_bus_reset(struct pci_bus *bus, bool probe)\n /**\n * pci_try_reset_bus - Try to reset a PCI bus\n * @bus: top level PCI bus to reset\n+ * @check: optional per-device callback that can abort the reset\n+ * @data: opaque argument for @check\n *\n * Same as above except return -EAGAIN if the bus cannot be locked\n */\n-static int pci_try_reset_bus(struct pci_bus *bus)\n+static int pci_try_reset_bus(struct pci_bus *bus,\n+\t\t\t int (*check)(struct pci_dev *dev, void *data),\n+\t\t\t void *data)\n {\n \tint rc;\n \n@@ -5619,10 +5676,13 @@ static int pci_try_reset_bus(struct pci_bus *bus)\n \t\treturn rc;\n \n \tif (pci_bus_trylock(bus)) {\n-\t\tpci_bus_save_and_disable_locked(bus);\n-\t\tmight_sleep();\n-\t\trc = pci_bridge_secondary_bus_reset(bus-\u003eself);\n-\t\tpci_bus_restore_locked(bus);\n+\t\trc = check ? pci_walk_reset_check(bus, NULL, check, data) : 0;\n+\t\tif (!rc) {\n+\t\t\tpci_bus_save_and_disable_locked(bus);\n+\t\t\tmight_sleep();\n+\t\t\trc = pci_bridge_secondary_bus_reset(bus-\u003eself);\n+\t\t\tpci_bus_restore_locked(bus);\n+\t\t}\n \t\tpci_bus_unlock(bus);\n \t} else\n \t\trc = -EAGAIN;\n@@ -5661,7 +5721,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)\n \n \tlist_for_each_entry(slot, \u0026bus-\u003eslots, list) {\n \t\tif (restore)\n-\t\t\tret = pci_try_reset_slot(slot);\n+\t\t\tret = pci_try_reset_slot(slot, NULL, NULL);\n \t\telse\n \t\t\tret = pci_slot_reset(slot, PCI_RESET_DO_RESET);\n \n@@ -5675,7 +5735,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)\n \tmutex_unlock(\u0026pci_slot_mutex);\n \n \tif (restore)\n-\t\treturn pci_try_reset_bus(bus);\n+\t\treturn pci_try_reset_bus(bus, NULL, NULL);\n \treturn pci_bus_reset(bridge-\u003esubordinate, PCI_RESET_DO_RESET);\n }\n \n@@ -5705,16 +5765,43 @@ int pci_probe_reset_bus(struct pci_bus *bus)\n }\n EXPORT_SYMBOL_GPL(pci_probe_reset_bus);\n \n+/**\n+ * pci_reset_bus_cond - conditionally reset the slot or bus containing a device\n+ * @pdev: top level PCI device to reset via slot/bus\n+ * @check: optional callback invoked on each affected device before the reset\n+ * @data: opaque argument passed to @check\n+ *\n+ * Reset the slot or bus containing @pdev. Once the entire physical bus/slot\n+ * hierarchy is locked, @check (if not NULL) is called on each of those locked\n+ * devices. A nonzero return aborts the reset and is returned to the caller,\n+ * otherwise the reset proceeds.\n+ *\n+ * NB. @check runs with the full set of device_locks noted above held; callbacks\n+ * must take these locking semantics into account. Use NULL to perform an\n+ * unconditional reset.\n+ *\n+ * Return: 0 on success, -ENOTTY if @pdev is not resettable, -EAGAIN if the\n+ * devices cannot be locked, or the value returned by @check.\n+ */\n+int pci_reset_bus_cond(struct pci_dev *pdev,\n+\t\t int (*check)(struct pci_dev *dev, void *data),\n+\t\t void *data)\n+{\n+\treturn !pci_probe_reset_slot(pdev-\u003eslot) ?\n+\t\tpci_try_reset_slot(pdev-\u003eslot, check, data) :\n+\t\tpci_try_reset_bus(pdev-\u003ebus, check, data);\n+}\n+EXPORT_SYMBOL_GPL(pci_reset_bus_cond);\n+\n /**\n * pci_reset_bus - Try to reset a PCI bus\n * @pdev: top level PCI device to reset via slot/bus\n *\n- * Same as above except return -EAGAIN if the bus cannot be locked\n+ * Same as above without the conditional check.\n */\n int pci_reset_bus(struct pci_dev *pdev)\n {\n-\treturn (!pci_probe_reset_slot(pdev-\u003eslot)) ?\n-\t pci_try_reset_slot(pdev-\u003eslot) : pci_try_reset_bus(pdev-\u003ebus);\n+\treturn pci_reset_bus_cond(pdev, NULL, NULL);\n }\n EXPORT_SYMBOL_GPL(pci_reset_bus);\n \ndiff --git a/drivers/pci/pci.h b/drivers/pci/pci.h\nindex 4469e1a77f3c1..416fd6b74abe4 100644\n--- a/drivers/pci/pci.h\n+++ b/drivers/pci/pci.h\n@@ -230,7 +230,6 @@ enum pci_mmap_api {\n int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,\n \t\t enum pci_mmap_api mmap_api);\n \n-bool pci_reset_supported(struct pci_dev *dev);\n void pci_init_reset_methods(struct pci_dev *dev);\n int pci_bridge_secondary_bus_reset(struct pci_dev *dev);\n int pci_bus_error_reset(struct pci_dev *dev);\ndiff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c\nindex 3f11a9624b9c0..8e42342d56d3c 100644\n--- a/drivers/vfio/pci/vfio_pci_core.c\n+++ b/drivers/vfio/pci/vfio_pci_core.c\n@@ -609,7 +609,6 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)\n \tif (ret == -EAGAIN)\n \t\tgoto out_disable_device;\n \n-\tvdev-\u003ereset_works = !ret;\n \tpci_save_state(pdev);\n \tvdev-\u003epci_saved_state = pci_store_saved_state(pdev);\n \tif (!vdev-\u003epci_saved_state)\n@@ -766,7 +765,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)\n \tif (pci_load_and_free_saved_state(pdev, \u0026vdev-\u003epci_saved_state)) {\n \t\tpci_info(pdev, \"%s: Couldn't reload saved state\\n\", __func__);\n \n-\t\tif (!vdev-\u003ereset_works)\n+\t\tif (!pci_reset_supported(pdev))\n \t\t\tgoto out;\n \n \t\tpci_save_state(pdev);\n@@ -785,12 +784,14 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)\n \t * We can not use the \"try\" reset interface here, which will\n \t * overwrite the previously restored configuration information.\n \t */\n-\tif (vdev-\u003ereset_works) {\n+\tif (pci_reset_supported(pdev)) {\n \t\tbridge = pci_upstream_bridge(pdev);\n \t\tif (bridge \u0026\u0026 !pci_dev_trylock(bridge))\n \t\t\tgoto out_restore_state;\n \t\tif (pci_dev_trylock(pdev)) {\n-\t\t\tif (!__pci_reset_function_locked(pdev))\n+\t\t\t/* Enforce function scope under lock for SR-IOV PFs */\n+\t\t\tif (!pci_num_vf(pdev) \u0026\u0026\n+\t\t\t !__pci_reset_function_locked(pdev))\n \t\t\t\tvdev-\u003eneeds_reset = false;\n \t\t\tpci_dev_unlock(pdev);\n \t\t}\n@@ -892,6 +893,17 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)\n \treturn 0;\n }\n \n+/*\n+ * PCI walk callback to check for SR-IOV PFs with active VFs. VFs are not\n+ * enumerated when determining affected devices and may be owned by separate\n+ * userspace processes from the PF. It's therefore the user's responsibility\n+ * to teardown VFs for any affected PF before performing a hot-reset.\n+ */\n+static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data)\n+{\n+\treturn pci_num_vf(pdev) ? -EBUSY : 0;\n+}\n+\n struct vfio_pci_fill_info {\n \tstruct vfio_device *vdev;\n \tstruct vfio_pci_dependent_device *devices;\n@@ -1085,7 +1097,7 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,\n \n \tinfo.flags = VFIO_DEVICE_FLAGS_PCI;\n \n-\tif (vdev-\u003ereset_works)\n+\tif (pci_reset_supported(vdev-\u003epdev))\n \t\tinfo.flags |= VFIO_DEVICE_FLAGS_RESET;\n \n \tinfo.num_regions = VFIO_PCI_NUM_REGIONS + vdev-\u003enum_regions;\n@@ -1317,7 +1329,7 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,\n {\n \tint ret;\n \n-\tif (!vdev-\u003ereset_works)\n+\tif (!pci_reset_supported(vdev-\u003epdev))\n \t\treturn -EINVAL;\n \n \tvfio_pci_zap_and_down_write_memory_lock(vdev);\n@@ -2596,7 +2608,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,\n \tlist_for_each_entry(vdev, \u0026dev_set-\u003edevice_list, vdev.dev_set_list)\n \t\tvfio_pci_set_power_state(vdev, PCI_D0);\n \n-\tret = pci_reset_bus(pdev);\n+\tret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL);\n \n \tvdev = list_last_entry(\u0026dev_set-\u003edevice_list,\n \t\t\t struct vfio_pci_core_device, vdev.dev_set_list);\n@@ -2659,7 +2671,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)\n \tif (vfio_pci_dev_set_pm_runtime_get(dev_set))\n \t\treturn;\n \n-\tif (!pci_reset_bus(pdev))\n+\tif (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL))\n \t\treset_done = true;\n \n \tlist_for_each_entry(cur, \u0026dev_set-\u003edevice_list, vdev.dev_set_list) {\ndiff --git a/include/linux/pci.h b/include/linux/pci.h\nindex 64b308b6e61c1..4de21e6ac538f 100644\n--- a/include/linux/pci.h\n+++ b/include/linux/pci.h\n@@ -1474,12 +1474,16 @@ void pcie_print_link_status(struct pci_dev *dev);\n int pcie_reset_flr(struct pci_dev *dev, bool probe);\n int pcie_flr(struct pci_dev *dev);\n int __pci_reset_function_locked(struct pci_dev *dev);\n+bool pci_reset_supported(struct pci_dev *dev);\n int pci_reset_function(struct pci_dev *dev);\n int pci_reset_function_locked(struct pci_dev *dev);\n int pci_try_reset_function(struct pci_dev *dev);\n int pci_probe_reset_slot(struct pci_slot *slot);\n int pci_probe_reset_bus(struct pci_bus *bus);\n int pci_reset_bus(struct pci_dev *dev);\n+int pci_reset_bus_cond(struct pci_dev *pdev,\n+\t\t int (*check)(struct pci_dev *dev, void *data),\n+\t\t void *data);\n void pci_reset_secondary_bus(struct pci_dev *dev);\n void pcibios_reset_secondary_bus(struct pci_dev *dev);\n void pci_update_resource(struct pci_dev *dev, int resno);\ndiff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h\nindex 9a1674c152aa2..6fb599ec29191 100644\n--- a/include/linux/vfio_pci_core.h\n+++ b/include/linux/vfio_pci_core.h\n@@ -121,7 +121,6 @@ struct vfio_pci_core_device {\n \t/* Flags only modified on setup/release - bitfield ok */\n \tbool\t\t\thas_dyn_msix:1;\n \tbool\t\t\tpci_2_3:1;\n-\tbool\t\t\treset_works:1;\n \tbool\t\t\textended_caps:1;\n \tbool\t\t\thas_vga:1;\n \tbool\t\t\tnointx:1;\ndiff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h\nindex 5de618a3a5eee..8603959f17350 100644\n--- a/include/uapi/linux/vfio.h\n+++ b/include/uapi/linux/vfio.h\n@@ -772,6 +772,9 @@ struct vfio_pci_hot_reset_info {\n * Mixed usage of legacy groups and cdevs across the set of affected\n * devices is not supported.\n *\n+ * Hot reset of SR-IOV PFs with active VFs is not supported, SR-IOV\n+ * should first be disabled on any affected PF.\n+ *\n * Return: 0 on success, -errno on failure.\n */\n struct vfio_pci_hot_reset {\n"
} |
| 2/1 | 2026/08/12 05:24 | agent | patch-evaluator |
1mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"PCI",
"VFIO",
"VFIO_PCI"
],
"FocusSymbols": [
"pci_reset_bus_cond",
"pci_reset_function",
"pci_reset_function_locked",
"pci_try_reset_function",
"pci_reset_bus",
"vfio_pci_core_ioctl",
"vfio_pci_core_disable",
"vfio_pci_core_enable"
],
"Reasoning": "The patch introduces `pci_reset_bus_cond` and modifies PCI reset functions to prevent resetting SR-IOV PFs with active VFs. It also updates VFIO PCI core to use these new checks. These are reachable core PCI and VFIO functions that can be triggered in virtualized environments.",
"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 4c8e00cc4bae4fcb838d7780a4591c2fc148f69c
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 12 05:24:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 77b17b13ee615..0b4f13397da24 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -98,6 +98,7 @@ bool pci_reset_supported(struct pci_dev *dev)
{
return dev->reset_methods[0] != 0;
}
+EXPORT_SYMBOL_GPL(pci_reset_supported);
#ifdef CONFIG_PCI_DOMAINS
int pci_domains_supported = 1;
@@ -5222,11 +5223,22 @@ int pci_reset_function(struct pci_dev *dev)
pci_dev_lock(bridge);
pci_dev_lock(dev);
+
+ /*
+ * Reset of an SR-IOV PF necessarily resets any active VFs. Such resets are
+ * beyond the scope advertised for pci_reset_function() and variants, refuse.
+ */
+ if (pci_num_vf(dev) > 0) {
+ rc = -ENOTTY;
+ goto unlock;
+ }
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
+unlock:
pci_dev_unlock(dev);
if (bridge)
@@ -5264,6 +5276,9 @@ int pci_reset_function_locked(struct pci_dev *dev)
if (!pci_reset_supported(dev))
return -ENOTTY;
+ if (pci_num_vf(dev) > 0)
+ return -ENOTTY;
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
@@ -5290,6 +5305,11 @@ int pci_try_reset_function(struct pci_dev *dev)
if (!pci_dev_trylock(dev))
return -EAGAIN;
+ if (pci_num_vf(dev) > 0) {
+ pci_dev_unlock(dev);
+ return -ENOTTY;
+ }
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
@@ -5548,9 +5568,36 @@ int pci_probe_reset_slot(struct pci_slot *slot)
}
EXPORT_SYMBOL_GPL(pci_probe_reset_slot);
+/* Call @cb on every device a slot or bus reset affects, stopping on error. */
+static int pci_walk_reset_check(struct pci_bus *bus, struct pci_slot *slot,
+ int (*cb)(struct pci_dev *dev, void *data),
+ void *data)
+{
+ struct pci_dev *dev;
+ int rc;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (slot && (!dev->slot || dev->slot != slot))
+ continue;
+ rc = cb(dev, data);
+ if (rc)
+ return rc;
+ if (dev->subordinate) {
+ rc = pci_walk_reset_check(dev->subordinate,
+ NULL, cb, data);
+ if (rc)
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
/**
* pci_try_reset_slot - Try to reset a PCI slot
* @slot: PCI slot to reset
+ * @check: optional per-device callback that can abort the reset
+ * @data: opaque argument for @check
*
* A PCI bus may host multiple slots, each slot may support a reset mechanism
* independent of other slots. For instance, some slots may support slot power
@@ -5563,7 +5610,9 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot);
*
* Same as above except return -EAGAIN if the slot cannot be locked
*/
-static int pci_try_reset_slot(struct pci_slot *slot)
+static int pci_try_reset_slot(struct pci_slot *slot,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
{
int rc;
@@ -5572,10 +5621,14 @@ static int pci_try_reset_slot(struct pci_slot *slot)
return rc;
if (pci_slot_trylock(slot)) {
- pci_slot_save_and_disable_locked(slot);
- might_sleep();
- rc = pci_reset_hotplug_slot(slot->hotplug, PCI_RESET_DO_RESET);
- pci_slot_restore_locked(slot);
+ rc = check ? pci_walk_reset_check(slot->bus, slot, check, data) : 0;
+ if (!rc) {
+ pci_slot_save_and_disable_locked(slot);
+ might_sleep();
+ rc = pci_reset_hotplug_slot(slot->hotplug,
+ PCI_RESET_DO_RESET);
+ pci_slot_restore_locked(slot);
+ }
pci_slot_unlock(slot);
} else
rc = -EAGAIN;
@@ -5607,10 +5660,14 @@ static int pci_bus_reset(struct pci_bus *bus, bool probe)
/**
* pci_try_reset_bus - Try to reset a PCI bus
* @bus: top level PCI bus to reset
+ * @check: optional per-device callback that can abort the reset
+ * @data: opaque argument for @check
*
* Same as above except return -EAGAIN if the bus cannot be locked
*/
-static int pci_try_reset_bus(struct pci_bus *bus)
+static int pci_try_reset_bus(struct pci_bus *bus,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
{
int rc;
@@ -5619,10 +5676,13 @@ static int pci_try_reset_bus(struct pci_bus *bus)
return rc;
if (pci_bus_trylock(bus)) {
- pci_bus_save_and_disable_locked(bus);
- might_sleep();
- rc = pci_bridge_secondary_bus_reset(bus->self);
- pci_bus_restore_locked(bus);
+ rc = check ? pci_walk_reset_check(bus, NULL, check, data) : 0;
+ if (!rc) {
+ pci_bus_save_and_disable_locked(bus);
+ might_sleep();
+ rc = pci_bridge_secondary_bus_reset(bus->self);
+ pci_bus_restore_locked(bus);
+ }
pci_bus_unlock(bus);
} else
rc = -EAGAIN;
@@ -5661,7 +5721,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)
list_for_each_entry(slot, &bus->slots, list) {
if (restore)
- ret = pci_try_reset_slot(slot);
+ ret = pci_try_reset_slot(slot, NULL, NULL);
else
ret = pci_slot_reset(slot, PCI_RESET_DO_RESET);
@@ -5675,7 +5735,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)
mutex_unlock(&pci_slot_mutex);
if (restore)
- return pci_try_reset_bus(bus);
+ return pci_try_reset_bus(bus, NULL, NULL);
return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET);
}
@@ -5705,16 +5765,43 @@ int pci_probe_reset_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pci_probe_reset_bus);
+/**
+ * pci_reset_bus_cond - conditionally reset the slot or bus containing a device
+ * @pdev: top level PCI device to reset via slot/bus
+ * @check: optional callback invoked on each affected device before the reset
+ * @data: opaque argument passed to @check
+ *
+ * Reset the slot or bus containing @pdev. Once the entire physical bus/slot
+ * hierarchy is locked, @check (if not NULL) is called on each of those locked
+ * devices. A nonzero return aborts the reset and is returned to the caller,
+ * otherwise the reset proceeds.
+ *
+ * NB. @check runs with the full set of device_locks noted above held; callbacks
+ * must take these locking semantics into account. Use NULL to perform an
+ * unconditional reset.
+ *
+ * Return: 0 on success, -ENOTTY if @pdev is not resettable, -EAGAIN if the
+ * devices cannot be locked, or the value returned by @check.
+ */
+int pci_reset_bus_cond(struct pci_dev *pdev,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
+{
+ return !pci_probe_reset_slot(pdev->slot) ?
+ pci_try_reset_slot(pdev->slot, check, data) :
+ pci_try_reset_bus(pdev->bus, check, data);
+}
+EXPORT_SYMBOL_GPL(pci_reset_bus_cond);
+
/**
* pci_reset_bus - Try to reset a PCI bus
* @pdev: top level PCI device to reset via slot/bus
*
- * Same as above except return -EAGAIN if the bus cannot be locked
+ * Same as above without the conditional check.
*/
int pci_reset_bus(struct pci_dev *pdev)
{
- return (!pci_probe_reset_slot(pdev->slot)) ?
- pci_try_reset_slot(pdev->slot) : pci_try_reset_bus(pdev->bus);
+ return pci_reset_bus_cond(pdev, NULL, NULL);
}
EXPORT_SYMBOL_GPL(pci_reset_bus);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4469e1a77f3c1..416fd6b74abe4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -230,7 +230,6 @@ enum pci_mmap_api {
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
enum pci_mmap_api mmap_api);
-bool pci_reset_supported(struct pci_dev *dev);
void pci_init_reset_methods(struct pci_dev *dev);
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
int pci_bus_error_reset(struct pci_dev *dev);
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 3f11a9624b9c0..8e42342d56d3c 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -609,7 +609,6 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
if (ret == -EAGAIN)
goto out_disable_device;
- vdev->reset_works = !ret;
pci_save_state(pdev);
vdev->pci_saved_state = pci_store_saved_state(pdev);
if (!vdev->pci_saved_state)
@@ -766,7 +765,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
- if (!vdev->reset_works)
+ if (!pci_reset_supported(pdev))
goto out;
pci_save_state(pdev);
@@ -785,12 +784,14 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
* We can not use the "try" reset interface here, which will
* overwrite the previously restored configuration information.
*/
- if (vdev->reset_works) {
+ if (pci_reset_supported(pdev)) {
bridge = pci_upstream_bridge(pdev);
if (bridge && !pci_dev_trylock(bridge))
goto out_restore_state;
if (pci_dev_trylock(pdev)) {
- if (!__pci_reset_function_locked(pdev))
+ /* Enforce function scope under lock for SR-IOV PFs */
+ if (!pci_num_vf(pdev) &&
+ !__pci_reset_function_locked(pdev))
vdev->needs_reset = false;
pci_dev_unlock(pdev);
}
@@ -892,6 +893,17 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
return 0;
}
+/*
+ * PCI walk callback to check for SR-IOV PFs with active VFs. VFs are not
+ * enumerated when determining affected devices and may be owned by separate
+ * userspace processes from the PF. It's therefore the user's responsibility
+ * to teardown VFs for any affected PF before performing a hot-reset.
+ */
+static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data)
+{
+ return pci_num_vf(pdev) ? -EBUSY : 0;
+}
+
struct vfio_pci_fill_info {
struct vfio_device *vdev;
struct vfio_pci_dependent_device *devices;
@@ -1085,7 +1097,7 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
info.flags = VFIO_DEVICE_FLAGS_PCI;
- if (vdev->reset_works)
+ if (pci_reset_supported(vdev->pdev))
info.flags |= VFIO_DEVICE_FLAGS_RESET;
info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
@@ -1317,7 +1329,7 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
{
int ret;
- if (!vdev->reset_works)
+ if (!pci_reset_supported(vdev->pdev))
return -EINVAL;
vfio_pci_zap_and_down_write_memory_lock(vdev);
@@ -2596,7 +2608,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list)
vfio_pci_set_power_state(vdev, PCI_D0);
- ret = pci_reset_bus(pdev);
+ ret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL);
vdev = list_last_entry(&dev_set->device_list,
struct vfio_pci_core_device, vdev.dev_set_list);
@@ -2659,7 +2671,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
if (vfio_pci_dev_set_pm_runtime_get(dev_set))
return;
- if (!pci_reset_bus(pdev))
+ if (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL))
reset_done = true;
list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 64b308b6e61c1..4de21e6ac538f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1474,12 +1474,16 @@ void pcie_print_link_status(struct pci_dev *dev);
int pcie_reset_flr(struct pci_dev *dev, bool probe);
int pcie_flr(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev);
+bool pci_reset_supported(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev);
int pci_reset_function_locked(struct pci_dev *dev);
int pci_try_reset_function(struct pci_dev *dev);
int pci_probe_reset_slot(struct pci_slot *slot);
int pci_probe_reset_bus(struct pci_bus *bus);
int pci_reset_bus(struct pci_dev *dev);
+int pci_reset_bus_cond(struct pci_dev *pdev,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data);
void pci_reset_secondary_bus(struct pci_dev *dev);
void pcibios_reset_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno);
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 9a1674c152aa2..6fb599ec29191 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -121,7 +121,6 @@ struct vfio_pci_core_device {
/* Flags only modified on setup/release - bitfield ok */
bool has_dyn_msix:1;
bool pci_2_3:1;
- bool reset_works:1;
bool extended_caps:1;
bool has_vga:1;
bool nointx:1;
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5de618a3a5eee..8603959f17350 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -772,6 +772,9 @@ struct vfio_pci_hot_reset_info {
* Mixed usage of legacy groups and cdevs across the set of affected
* devices is not supported.
*
+ * Hot reset of SR-IOV PFs with active VFs is not supported, SR-IOV
+ * should first be disabled on any affected PF.
+ *
* Return: 0 on success, -errno on failure.
*/
struct vfio_pci_hot_reset {
|
| 3/2 | 2026/08/12 05:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7190 output: 37 thoughts: 532 Thoughts: **Fuzzing Target Identification: PCI Reset Logic** Okay, so I've got this patch that I need to assess for fuzzing potential. My initial thought is that this definitely introduces functional changes to the kernel, specifically within the PCI subsystem and the VFIO PCI core, so it warrants further investigation. It touches `drivers/pci/pci.c` and `drivers/vfio/pci/vfio_pci_core.c`, which are critical areas. The core of the change seems to center around the PCI reset logic. I see modifications to `pci_reset_function`, `pci_reset_function_locked`, and `pci_try_reset_function`, adding checks related to the number of virtual functions (`pci_num_vf(dev) > 0`). It introduces `pci_reset_bus_cond` and alters how `pci_try_reset_slot` and `pci_try_reset_bus` work, incorporating a callback function. The VFIO side leverages this new `pci_reset_bus_cond` with a `vfio_pci_dev_has_vfs` callback to prevent hot resets of SR-IOV Physical Functions with active Virtual Functions. I'm also seeing some cleanup where `vdev->reset_works` is removed in favor of a direct check with `pci_reset_supported(pdev)`. The crucial question is, can this be triggered in a virtualized environment? Considering VFIO and PCI resets are QEMU controllable, the answer is a yes. Now, QEMU has some support for SR-IOV (igb, nvme). However, even without SR-IOV, the core PCI reset functions like `pci_reset_function` and the new `pci_reset_bus_cond` will be reached, so this needs to be fuzzed even if SR-IOV is not present. This patch changes the core PCI functions: `pci_reset_function`, `pci_reset_function_locked`, `pci_try_reset_function`, `pci_reset_bus_cond`, `pci_reset_bus`. I'll check the reachability of these modified functions. I know that `pci_reset_function` is exported and used by various drivers, plus sysfs, so there are multiple entry points. `pci_reset_bus_cond` is also exported and, crucially, used by VFIO, which gives us a great target. Now, let's nail down the configuration options. I'll need `CONFIG_PCI`, obviously. Then, for sure, I'll need `CONFIG_VFIO_PCI` to activate the VFIO changes. I'll search for `pci_reset_bus_cond` in `drivers/pci/pci.c` for any extra config option info. |
| 4/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "pci_reset_bus_cond",
"PathPrefix": "drivers/pci/pci.c"
}Results: {
"Output": "drivers/pci/pci.c=5766=EXPORT_SYMBOL_GPL(pci_probe_reset_bus);\n--\ndrivers/pci/pci.c-5768-/**\ndrivers/pci/pci.c:5769: * pci_reset_bus_cond - conditionally reset the slot or bus containing a device\ndrivers/pci/pci.c-5770- * @pdev: top level PCI device to reset via slot/bus\n--\ndrivers/pci/pci.c-5785- */\ndrivers/pci/pci.c:5786:int pci_reset_bus_cond(struct pci_dev *pdev,\ndrivers/pci/pci.c-5787-\t\t int (*check)(struct pci_dev *dev, void *data),\n--\ndrivers/pci/pci.c-5793-}\ndrivers/pci/pci.c:5794:EXPORT_SYMBOL_GPL(pci_reset_bus_cond);\ndrivers/pci/pci.c-5795-\n--\ndrivers/pci/pci.c=5802=int pci_reset_bus(struct pci_dev *pdev)\ndrivers/pci/pci.c-5803-{\ndrivers/pci/pci.c:5804:\treturn pci_reset_bus_cond(pdev, NULL, NULL);\ndrivers/pci/pci.c-5805-}\n"
} |
| 5/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8765 output: 49 thoughts: 38 Thoughts: Here's my summary, as if I were thinking these thoughts: **Analyzing VFIO-PCI Device Capabilities** Okay, so I need to figure out how a VFIO-PCI device is handling virtual functions (VFs). Let's dive right into the core of the matter, which means I should start by examining the `vfio_pci_core.c` file within the `drivers/vfio/pci` directory. Specifically, I'm going to focus on the `vfio_pci_dev_has_vfs` function. This should give me a solid understanding of how the VFIO driver determines if a given PCI device is set up to expose virtual functions, and the mechanisms it uses to manage them. Understanding this function's logic will give me the best insight into the driver's VF capabilities. |
| 6/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "vfio_pci_dev_has_vfs",
"PathPrefix": "drivers/vfio/pci/vfio_pci_core.c"
}Results: {
"Output": "drivers/vfio/pci/vfio_pci_core.c=890=static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)\n--\ndrivers/vfio/pci/vfio_pci_core.c-901- */\ndrivers/vfio/pci/vfio_pci_core.c:902:static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data)\ndrivers/vfio/pci/vfio_pci_core.c-903-{\n--\ndrivers/vfio/pci/vfio_pci_core.c=2516=static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,\n--\ndrivers/vfio/pci/vfio_pci_core.c-2610-\ndrivers/vfio/pci/vfio_pci_core.c:2611:\tret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL);\ndrivers/vfio/pci/vfio_pci_core.c-2612-\n--\ndrivers/vfio/pci/vfio_pci_core.c=2653=static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)\n--\ndrivers/vfio/pci/vfio_pci_core.c-2673-\ndrivers/vfio/pci/vfio_pci_core.c:2674:\tif (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL))\ndrivers/vfio/pci/vfio_pci_core.c-2675-\t\treset_done = true;\n"
} |
| 7/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9512 output: 35 thoughts: 106 Thoughts: **Focusing on the VFIO Reset Landscape** Alright, let's get down to brass tacks. I need to zero in on the key functions involved in managing PCI resets, specifically within the VFIO context. My immediate focus is on these functions: `pci_reset_bus_cond`, `pci_reset_function`, `pci_reset_function_locked`, `pci_try_reset_function`, `vfio_pci_dev_set_hot_reset`, `vfio_pci_dev_set_try_reset`, and `vfio_pci_ioctl_reset`. Each one likely plays a vital role in orchestrating the reset procedures, and I need to understand their interactions and responsibilities. Before I dive into their implementations, I should double check the Kconfig to ensure that VFIO_PCI is enabled. This will give me further context for the importance and impact of the reset code. |
| 8/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "config VFIO_PCI",
"PathPrefix": "drivers/vfio/pci/Kconfig"
}Results: {
"Output": "drivers/vfio/pci/Kconfig=2=menu \"VFIO support for PCI devices\"\n--\ndrivers/vfio/pci/Kconfig-4-\ndrivers/vfio/pci/Kconfig:5:config VFIO_PCI_CORE\ndrivers/vfio/pci/Kconfig-6-\ttristate\n--\ndrivers/vfio/pci/Kconfig-9-\ndrivers/vfio/pci/Kconfig:10:config VFIO_PCI_INTX\ndrivers/vfio/pci/Kconfig-11-\tdef_bool y if !S390\n--\ndrivers/vfio/pci/Kconfig-13-\ndrivers/vfio/pci/Kconfig:14:config VFIO_PCI\ndrivers/vfio/pci/Kconfig-15-\ttristate \"Generic VFIO support for any PCI device\"\n--\ndrivers/vfio/pci/Kconfig=23=if VFIO_PCI\ndrivers/vfio/pci/Kconfig:24:config VFIO_PCI_VGA\ndrivers/vfio/pci/Kconfig-25-\tbool \"Generic VFIO PCI support for VGA devices\"\n--\ndrivers/vfio/pci/Kconfig-33-\ndrivers/vfio/pci/Kconfig:34:config VFIO_PCI_IGD\ndrivers/vfio/pci/Kconfig-35-\tbool \"Generic VFIO PCI extensions for Intel graphics (GVT-d)\"\n--\ndrivers/vfio/pci/Kconfig=45=endif\ndrivers/vfio/pci/Kconfig-46-\ndrivers/vfio/pci/Kconfig:47:config VFIO_PCI_ZDEV_KVM\ndrivers/vfio/pci/Kconfig-48-\tbool \"VFIO PCI extensions for s390x KVM passthrough\"\n--\ndrivers/vfio/pci/Kconfig-57-\ndrivers/vfio/pci/Kconfig:58:config VFIO_PCI_DMABUF\ndrivers/vfio/pci/Kconfig-59-\tdef_bool y if VFIO_PCI_CORE \u0026\u0026 PCI_P2PDMA \u0026\u0026 DMA_SHARED_BUFFER\n"
} |
| 9/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10390 output: 45 thoughts: 91 Thoughts: Okay, here's my breakdown of what I'm looking at: **VFIO-PCI Reset Functionality Deep Dive** Alright, so we're talking about `VFIO_PCI` here, that's our target. My main concern right now is understanding the reset capabilities within this setup. Specifically, I'm digging into how the PCI bus and individual functions are reset. First things first: Let me confirm if the kernel exports the crucial functions we need. I'm checking if `pci_reset_bus_cond` is exposed as a symbol and, sure enough, it's there, flagged as `EXPORT_SYMBOL_GPL`. Perfect! Then, let me quickly double-check the availability of `pci_reset_function`, Yep, that's there too. Finally, what about the locked version of that, `pci_reset_function_locked`? I need to know if that's also available. |
| 10/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(pci_reset_function_locked\\)",
"PathPrefix": "drivers/pci/pci.c"
}Results: {
"Output": "drivers/pci/pci.c=5270=int pci_reset_function_locked(struct pci_dev *dev)\n--\ndrivers/pci/pci.c-5289-}\ndrivers/pci/pci.c:5290:EXPORT_SYMBOL_GPL(pci_reset_function_locked);\ndrivers/pci/pci.c-5291-\n"
} |
| 11/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10839 output: 45 thoughts: 18 Thoughts: Okay, here's my summary, considering my expertise: **Checking Function Export** Alright, let's get down to brass tacks. I need to quickly determine if the `pci_try_reset_function` function is exposed, i.e., exported, for use outside the kernel module that *likely* defines it. This is a common first step, especially when interacting with PCI devices or trying to write a driver module. If it's not exported, then I need to consider alternatives – whether there's an equivalent functionality already exposed, if I'll need to rewrite code or build the module against a custom kernel or, worst case, if I have to consider a complete change of approach. The answer here dictates a *lot* of the next steps, so I need this information at hand before I start doing any kind of heavy-lifting work. |
| 12/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(pci_try_reset_function\\)",
"PathPrefix": "drivers/pci/pci.c"
}Results: {
"Output": "drivers/pci/pci.c=5298=int pci_try_reset_function(struct pci_dev *dev)\n--\ndrivers/pci/pci.c-5319-}\ndrivers/pci/pci.c:5320:EXPORT_SYMBOL_GPL(pci_try_reset_function);\ndrivers/pci/pci.c-5321-\n"
} |
| 13/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11195 output: 43 thoughts: 16 Thoughts: Okay, here's my summary, framed as my internal thought process: **PCI Bus Reset Export Check** Alright, before diving too deep into this, I need to confirm something fundamental. I'm going to quickly check if the `pci_reset_bus` function is actually exported. This is a critical first step. I can't proceed with any assumptions about its availability or usage if it's not actually made public. Knowing whether it's exported dictates the entire approach I'll take. If it isn't, I'll need to immediately re-evaluate and look for alternative methods. So, let's verify that export status before moving any further. |
| 14/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(pci_reset_bus\\)",
"PathPrefix": "drivers/pci/pci.c"
}Results: {
"Output": "drivers/pci/pci.c=5802=int pci_reset_bus(struct pci_dev *pdev)\n--\ndrivers/pci/pci.c-5805-}\ndrivers/pci/pci.c:5806:EXPORT_SYMBOL_GPL(pci_reset_bus);\ndrivers/pci/pci.c-5807-\n"
} |
| 15/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11505 output: 43 thoughts: 16 Thoughts: Okay, let's see. Here's how I'd approach summarizing those thoughts: **Checking Kernel Symbol Export Status** Alright, the first thing that pops into my head is to verify if the `pci_reset_supported` symbol is actually exported by the kernel. This is a crucial first step. If the symbol isn't exported, there's no point in even trying to use it – it won't be visible to modules or external code. It's basic due diligence, ensuring we're not chasing a ghost and that the functionality we're aiming to leverage is, in fact, available for us to work with. Before diving any deeper, this check is mandatory. It's a fundamental part of the debugging process. |
| 16/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(pci_reset_supported\\)",
"PathPrefix": "drivers/pci/pci.c"
}Results: {
"Output": "drivers/pci/pci.c=97=bool pci_reset_supported(struct pci_dev *dev)\n--\ndrivers/pci/pci.c-100-}\ndrivers/pci/pci.c:101:EXPORT_SYMBOL_GPL(pci_reset_supported);\ndrivers/pci/pci.c-102-\n"
} |
| 17/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11824 output: 54 thoughts: 282 Thoughts: **Analyzing the PCI Reset Patch** Okay, so this patch is introducing `pci_reset_bus_cond` and then tweaking several existing functions: `pci_reset_function`, `pci_reset_function_locked`, `pci_try_reset_function`, and `pci_reset_bus`. That's the core PCI reset infrastructure being touched, which makes sense. I see that `vfio_pci_core.c` is also getting modified to make use of the new conditional bus reset function and `pci_reset_supported`. It looks like we're tightening the integration with VFIO. Let's break down the key functions implicated in this change: `pci_reset_bus_cond`, the primary new one, is naturally the priority. Then, the standard `pci_reset_function` family is getting revised. It also looks like the VFIO code has seen significant change, since `vfio_pci_core.c` is being altered. Specifically, `vfio_pci_ioctl_reset`, which handles the ioctl for reset, is static, but it's *called* from `vfio_pci_core_ioctl` which is, as an ioctl handler, exported. Then, we have `vfio_pci_dev_set_hot_reset`, and `vfio_pci_dev_set_try_reset`, which are also static, with the latter being used during VFIO device disable. Hold on... `vfio_pci_ioctl_reset` is static, which is interesting. But if it's being used by `vfio_pci_core_ioctl`, then that means it's still being accessed externally. I should confirm that `vfio_pci_core_ioctl` is indeed exported. It's a critical point to ensure the VFIO reset mechanism is properly exposed. |
| 18/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(vfio_pci_core_ioctl\\)",
"PathPrefix": "drivers/vfio/pci/vfio_pci_core.c"
}Results: {
"Output": "drivers/vfio/pci/vfio_pci_core.c=1567=long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,\n--\ndrivers/vfio/pci/vfio_pci_core.c-1592-}\ndrivers/vfio/pci/vfio_pci_core.c:1593:EXPORT_SYMBOL_GPL(vfio_pci_core_ioctl);\ndrivers/vfio/pci/vfio_pci_core.c-1594-\n"
} |
| 19/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12721 output: 54 thoughts: 44 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Identifying the Key Focus for Investigation** Okay, so I need to choose the best focus for digging into this. `vfio_pci_core_ioctl`... while it *is* the generic ioctl handler, that's almost too broad, isn't it? It’s probably going to lead to a lot of noise. Maybe starting there is a good idea to get the bigger picture, but it might be inefficient. `vfio_pci_core_disable`… now *that* seems more promising. Specifically, *disabling* a function, could reveal more about any specific issues present. Let's start with that and then circle back to the IoCtl handler if we need to. |
| 20/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(vfio_pci_core_disable\\)",
"PathPrefix": "drivers/vfio/pci/vfio_pci_core.c"
}Results: {
"Output": "drivers/vfio/pci/vfio_pci_core.c=678=void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)\n--\ndrivers/vfio/pci/vfio_pci_core.c-812-}\ndrivers/vfio/pci/vfio_pci_core.c:813:EXPORT_SYMBOL_GPL(vfio_pci_core_disable);\ndrivers/vfio/pci/vfio_pci_core.c-814-\n"
} |
| 21/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13136 output: 54 thoughts: 31 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Checking VFIO-PCI's Exported Symbols** Alright, so `vfio_pci_core_disable` is definitely exported. That confirms a piece of the puzzle. Now, the natural follow-up question is… what about its counterpart? Is `vfio_pci_core_enable` also exposed? I need to know if I have the corresponding function or if there is another mechanism for the enable procedure. This could impact how I approach X on my current project. I need to verify that. I'll need to check the symbol table directly to be certain. |
| 22/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "EXPORT_SYMBOL_GPL\\(vfio_pci_core_enable\\)",
"PathPrefix": "drivers/vfio/pci/vfio_pci_core.c"
}Results: {
"Output": "drivers/vfio/pci/vfio_pci_core.c=587=int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)\n--\ndrivers/vfio/pci/vfio_pci_core.c-675-}\ndrivers/vfio/pci/vfio_pci_core.c:676:EXPORT_SYMBOL_GPL(vfio_pci_core_enable);\ndrivers/vfio/pci/vfio_pci_core.c-677-\n"
} |
| 23/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13513 output: 32 thoughts: 251 Thoughts: **Analyzing the VFIO PCI Reset Patch** Okay, let's break down this patch. My immediate focus is on how it's altering the reset mechanisms within the VFIO-PCI framework. It looks like the core changes are centered around `vfio_pci_core_enable` and `vfio_pci_core_disable`. I need to understand how these routines are being modified and how that affects the device reset lifecycle. To get a clearer picture, I'll need to focus on some key symbols. I'm noting the following functions, as they are likely where the heavy lifting is happening: `pci_reset_bus_cond`, `pci_reset_function`, `pci_reset_function_locked`, `pci_try_reset_function`, `vfio_pci_core_ioctl`, `vfio_pci_core_disable`, and `vfio_pci_core_enable`. Wait a minute, I see that `pci_reset_bus` is also being touched, which is now calling `pci_reset_bus_cond`. That's an important change; I'll have to investigate that function as well. I need to understand the impact of the conditional reset logic here. A quick check reveals that `pci_reset_supported` is being exported. This suggests it's becoming more widely accessible, which could be an interesting architectural shift. I'll need to see where it's being used. Now, to compile this, I'll need to ensure the correct kernel configurations are enabled. From a quick glance, I'm going to need `PCI` and `VFIO_PCI`. But I should double-check dependencies. Let me see... yes, `VFIO_PCI` depends on `VFIO` and `PCI`. That confirms my initial assessment. I'll need to keep an eye out for other dependencies too, but this seems like a solid starting point. |
| 24/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "depends on",
"PathPrefix": "drivers/vfio/pci/Kconfig"
}Results: {
"Output": "drivers/vfio/pci/Kconfig=2=menu \"VFIO support for PCI devices\"\ndrivers/vfio/pci/Kconfig:3:\tdepends on PCI\ndrivers/vfio/pci/Kconfig-4-\n--\ndrivers/vfio/pci/Kconfig=10=config VFIO_PCI_INTX\ndrivers/vfio/pci/Kconfig-11-\tdef_bool y if !S390\ndrivers/vfio/pci/Kconfig:12:\tdepends on VFIO_PCI_CORE\ndrivers/vfio/pci/Kconfig-13-\n--\ndrivers/vfio/pci/Kconfig=24=config VFIO_PCI_VGA\ndrivers/vfio/pci/Kconfig-25-\tbool \"Generic VFIO PCI support for VGA devices\"\ndrivers/vfio/pci/Kconfig:26:\tdepends on X86 \u0026\u0026 VGA_ARB\ndrivers/vfio/pci/Kconfig-27-\thelp\n--\ndrivers/vfio/pci/Kconfig=34=config VFIO_PCI_IGD\ndrivers/vfio/pci/Kconfig-35-\tbool \"Generic VFIO PCI extensions for Intel graphics (GVT-d)\"\ndrivers/vfio/pci/Kconfig:36:\tdepends on X86\ndrivers/vfio/pci/Kconfig-37-\tdefault y\n--\ndrivers/vfio/pci/Kconfig=47=config VFIO_PCI_ZDEV_KVM\ndrivers/vfio/pci/Kconfig-48-\tbool \"VFIO PCI extensions for s390x KVM passthrough\"\ndrivers/vfio/pci/Kconfig:49:\tdepends on S390 \u0026\u0026 KVM\ndrivers/vfio/pci/Kconfig-50-\tdefault y\n"
} |
| 25/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 14664 output: 30 thoughts: 39 Thoughts: Okay, here's my take on those thoughts, framed as my own: **Dependencies and Verification - VFIO's Foundation** Right, so I'm thinking about `VFIO_PCI`. It's pretty clear that it has a dependency on `PCI`, that's fundamental. And naturally, `VFIO` itself is required for `VFIO_PCI` to do its thing. Let's quickly verify that the `VFIO` pieces are correctly set up. I'll need to jump into `drivers/vfio/Kconfig` to check the configuration options and dependencies. I'm after the core `VFIO` configuration. Need to make sure that's all lined up properly. |
| 26/2 | 2026/08/12 05:25 | tool | grepper |
0mArgs:{
"Expression": "config VFIO",
"PathPrefix": "drivers/vfio/Kconfig"
}Results: {
"Output": "drivers/vfio/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/vfio/Kconfig:2:menuconfig VFIO\ndrivers/vfio/Kconfig-3-\ttristate \"VFIO Non-Privileged userspace driver framework\"\n--\ndrivers/vfio/Kconfig=16=if VFIO\ndrivers/vfio/Kconfig:17:config VFIO_DEVICE_CDEV\ndrivers/vfio/Kconfig-18-\tbool \"Support for the VFIO cdev /dev/vfio/devices/vfioX\"\n--\ndrivers/vfio/Kconfig-29-\ndrivers/vfio/Kconfig:30:config VFIO_GROUP\ndrivers/vfio/Kconfig-31-\tbool \"Support for the VFIO group /dev/vfio/$group_id\"\n--\ndrivers/vfio/Kconfig-39-\ndrivers/vfio/Kconfig:40:config VFIO_CONTAINER\ndrivers/vfio/Kconfig-41-\tbool \"Support for the VFIO container /dev/vfio/vfio\"\n--\ndrivers/vfio/Kconfig=52=if VFIO_CONTAINER\ndrivers/vfio/Kconfig:53:config VFIO_IOMMU_TYPE1\ndrivers/vfio/Kconfig-54-\ttristate\n--\ndrivers/vfio/Kconfig-56-\ndrivers/vfio/Kconfig:57:config VFIO_IOMMU_SPAPR_TCE\ndrivers/vfio/Kconfig-58-\ttristate\n--\ndrivers/vfio/Kconfig=61=endif\ndrivers/vfio/Kconfig-62-\ndrivers/vfio/Kconfig:63:config VFIO_NOIOMMU\ndrivers/vfio/Kconfig-64-\tbool \"VFIO No-IOMMU support\"\n--\ndrivers/vfio/Kconfig-77-\ndrivers/vfio/Kconfig:78:config VFIO_VIRQFD\ndrivers/vfio/Kconfig-79-\tbool\n--\ndrivers/vfio/Kconfig-82-\ndrivers/vfio/Kconfig:83:config VFIO_DEBUGFS\ndrivers/vfio/Kconfig-84-\tbool \"Export VFIO internals in DebugFS\"\n"
} |
| 27/2 | 2026/08/12 05:25 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 15442 output: 195 thoughts: 249 Thoughts: **My Assessment of the PCI and VFIO Integration** Okay, so I'm integrating some crucial updates. First, I'm adding `PCI`, `VFIO`, and `VFIO_PCI` to the `EnableConfigs`. This is essential to ensure these features are properly enabled in the system. Now, let's verify a critical detail: is `pci_reset_bus_cond` exported? Yep, looks good. This is a key function. These changes seem functional and reachable. The logic behind these changes is sound. The patch introduces `pci_reset_bus_cond` and then it modifies those PCI reset functions so that we avoid the scenario of resetting SR-IOV Physical Functions (PFs) when their Virtual Functions (VFs) are actively in use. It also makes sure the VFIO PCI core is updated to leverage these new checks. These functions, especially `pci_reset_bus_cond`, are reachable core PCI and VFIO functions, and they are critical in virtualized environments. I've got the following functions and configurations in mind: * The critical function, `pci_reset_bus_cond`. * PCI reset functions: `pci_reset_function`, `pci_reset_function_locked`, `pci_try_reset_function`, and `pci_reset_bus` which will need the `pci_reset_bus_cond`. * And finally the VFIO functions which must be considered: `vfio_pci_core_ioctl`, `vfio_pci_core_disable`, and `vfio_pci_core_enable`. I'm setting up these configurations: `PCI`, `VFIO`, and `VFIO_PCI`. Alright, I'm going to call `set-results` now. Everything looks good. |
| 28/2 | 2026/08/12 05:25 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"PCI",
"VFIO",
"VFIO_PCI"
],
"FocusSymbols": [
"pci_reset_bus_cond",
"pci_reset_function",
"pci_reset_function_locked",
"pci_try_reset_function",
"pci_reset_bus",
"vfio_pci_core_ioctl",
"vfio_pci_core_disable",
"vfio_pci_core_enable"
],
"Reasoning": "The patch introduces `pci_reset_bus_cond` and modifies PCI reset functions to prevent resetting SR-IOV PFs with active VFs. It also updates VFIO PCI core to use these new checks. These are reachable core PCI and VFIO functions that can be triggered in virtualized environments.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"PCI",
"VFIO",
"VFIO_PCI"
],
"FocusSymbols": [
"pci_reset_bus_cond",
"pci_reset_function",
"pci_reset_function_locked",
"pci_try_reset_function",
"pci_reset_bus",
"vfio_pci_core_ioctl",
"vfio_pci_core_disable",
"vfio_pci_core_enable"
],
"Reasoning": "The patch introduces `pci_reset_bus_cond` and modifies PCI reset functions to prevent resetting SR-IOV PFs with active VFs. It also updates VFIO PCI core to use these new checks. These are reachable core PCI and VFIO functions that can be triggered in virtualized environments.",
"WorthFuzzing": true
} |
| 29/1 | 2026/08/12 05:25 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 30/2 | 2026/08/12 05:25 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch modifies the PCI reset logic to prevent resetting SR-IOV Physical Functions (PFs) when Virtual Functions (VFs) are active. It introduces a conditional bus reset function (`pci_reset_bus_cond`) that accepts a callback to check devices before performing a reset. In the VFIO PCI core, it replaces a cached `reset_works` boolean with direct calls to `pci_reset_supported()` and uses the new conditional reset API to check for active VFs.\n\nThese changes are purely related to control flow, device state management, and PCI subsystem APIs. They do not introduce new data structures sent to user space, nor do they modify buffer allocations, padding, or initialization logic that could lead to uninitialized memory reads or information leaks. The `vfio_device_info` structure modified in `vfio_pci_ioctl_get_info` is already fully zero-initialized (`struct vfio_device_info info = {};`).\n\nAny potential bugs introduced by this patch (e.g., locking issues, use-after-free, or NULL pointer dereferences) would be caught by standard KASAN, LOCKDEP, and other default sanitizers. There is no risk of uninitialized memory usage that would require a dedicated KMSAN fuzzing session.",
"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 4c8e00cc4bae4fcb838d7780a4591c2fc148f69c
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Aug 12 05:24:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 77b17b13ee615..0b4f13397da24 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -98,6 +98,7 @@ bool pci_reset_supported(struct pci_dev *dev)
{
return dev->reset_methods[0] != 0;
}
+EXPORT_SYMBOL_GPL(pci_reset_supported);
#ifdef CONFIG_PCI_DOMAINS
int pci_domains_supported = 1;
@@ -5222,11 +5223,22 @@ int pci_reset_function(struct pci_dev *dev)
pci_dev_lock(bridge);
pci_dev_lock(dev);
+
+ /*
+ * Reset of an SR-IOV PF necessarily resets any active VFs. Such resets are
+ * beyond the scope advertised for pci_reset_function() and variants, refuse.
+ */
+ if (pci_num_vf(dev) > 0) {
+ rc = -ENOTTY;
+ goto unlock;
+ }
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
+unlock:
pci_dev_unlock(dev);
if (bridge)
@@ -5264,6 +5276,9 @@ int pci_reset_function_locked(struct pci_dev *dev)
if (!pci_reset_supported(dev))
return -ENOTTY;
+ if (pci_num_vf(dev) > 0)
+ return -ENOTTY;
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
@@ -5290,6 +5305,11 @@ int pci_try_reset_function(struct pci_dev *dev)
if (!pci_dev_trylock(dev))
return -EAGAIN;
+ if (pci_num_vf(dev) > 0) {
+ pci_dev_unlock(dev);
+ return -ENOTTY;
+ }
+
pci_dev_save_and_disable(dev);
rc = __pci_reset_function_locked(dev);
pci_dev_restore(dev);
@@ -5548,9 +5568,36 @@ int pci_probe_reset_slot(struct pci_slot *slot)
}
EXPORT_SYMBOL_GPL(pci_probe_reset_slot);
+/* Call @cb on every device a slot or bus reset affects, stopping on error. */
+static int pci_walk_reset_check(struct pci_bus *bus, struct pci_slot *slot,
+ int (*cb)(struct pci_dev *dev, void *data),
+ void *data)
+{
+ struct pci_dev *dev;
+ int rc;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (slot && (!dev->slot || dev->slot != slot))
+ continue;
+ rc = cb(dev, data);
+ if (rc)
+ return rc;
+ if (dev->subordinate) {
+ rc = pci_walk_reset_check(dev->subordinate,
+ NULL, cb, data);
+ if (rc)
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
/**
* pci_try_reset_slot - Try to reset a PCI slot
* @slot: PCI slot to reset
+ * @check: optional per-device callback that can abort the reset
+ * @data: opaque argument for @check
*
* A PCI bus may host multiple slots, each slot may support a reset mechanism
* independent of other slots. For instance, some slots may support slot power
@@ -5563,7 +5610,9 @@ EXPORT_SYMBOL_GPL(pci_probe_reset_slot);
*
* Same as above except return -EAGAIN if the slot cannot be locked
*/
-static int pci_try_reset_slot(struct pci_slot *slot)
+static int pci_try_reset_slot(struct pci_slot *slot,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
{
int rc;
@@ -5572,10 +5621,14 @@ static int pci_try_reset_slot(struct pci_slot *slot)
return rc;
if (pci_slot_trylock(slot)) {
- pci_slot_save_and_disable_locked(slot);
- might_sleep();
- rc = pci_reset_hotplug_slot(slot->hotplug, PCI_RESET_DO_RESET);
- pci_slot_restore_locked(slot);
+ rc = check ? pci_walk_reset_check(slot->bus, slot, check, data) : 0;
+ if (!rc) {
+ pci_slot_save_and_disable_locked(slot);
+ might_sleep();
+ rc = pci_reset_hotplug_slot(slot->hotplug,
+ PCI_RESET_DO_RESET);
+ pci_slot_restore_locked(slot);
+ }
pci_slot_unlock(slot);
} else
rc = -EAGAIN;
@@ -5607,10 +5660,14 @@ static int pci_bus_reset(struct pci_bus *bus, bool probe)
/**
* pci_try_reset_bus - Try to reset a PCI bus
* @bus: top level PCI bus to reset
+ * @check: optional per-device callback that can abort the reset
+ * @data: opaque argument for @check
*
* Same as above except return -EAGAIN if the bus cannot be locked
*/
-static int pci_try_reset_bus(struct pci_bus *bus)
+static int pci_try_reset_bus(struct pci_bus *bus,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
{
int rc;
@@ -5619,10 +5676,13 @@ static int pci_try_reset_bus(struct pci_bus *bus)
return rc;
if (pci_bus_trylock(bus)) {
- pci_bus_save_and_disable_locked(bus);
- might_sleep();
- rc = pci_bridge_secondary_bus_reset(bus->self);
- pci_bus_restore_locked(bus);
+ rc = check ? pci_walk_reset_check(bus, NULL, check, data) : 0;
+ if (!rc) {
+ pci_bus_save_and_disable_locked(bus);
+ might_sleep();
+ rc = pci_bridge_secondary_bus_reset(bus->self);
+ pci_bus_restore_locked(bus);
+ }
pci_bus_unlock(bus);
} else
rc = -EAGAIN;
@@ -5661,7 +5721,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)
list_for_each_entry(slot, &bus->slots, list) {
if (restore)
- ret = pci_try_reset_slot(slot);
+ ret = pci_try_reset_slot(slot, NULL, NULL);
else
ret = pci_slot_reset(slot, PCI_RESET_DO_RESET);
@@ -5675,7 +5735,7 @@ static int pci_reset_bridge(struct pci_dev *bridge, bool restore)
mutex_unlock(&pci_slot_mutex);
if (restore)
- return pci_try_reset_bus(bus);
+ return pci_try_reset_bus(bus, NULL, NULL);
return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET);
}
@@ -5705,16 +5765,43 @@ int pci_probe_reset_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL_GPL(pci_probe_reset_bus);
+/**
+ * pci_reset_bus_cond - conditionally reset the slot or bus containing a device
+ * @pdev: top level PCI device to reset via slot/bus
+ * @check: optional callback invoked on each affected device before the reset
+ * @data: opaque argument passed to @check
+ *
+ * Reset the slot or bus containing @pdev. Once the entire physical bus/slot
+ * hierarchy is locked, @check (if not NULL) is called on each of those locked
+ * devices. A nonzero return aborts the reset and is returned to the caller,
+ * otherwise the reset proceeds.
+ *
+ * NB. @check runs with the full set of device_locks noted above held; callbacks
+ * must take these locking semantics into account. Use NULL to perform an
+ * unconditional reset.
+ *
+ * Return: 0 on success, -ENOTTY if @pdev is not resettable, -EAGAIN if the
+ * devices cannot be locked, or the value returned by @check.
+ */
+int pci_reset_bus_cond(struct pci_dev *pdev,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data)
+{
+ return !pci_probe_reset_slot(pdev->slot) ?
+ pci_try_reset_slot(pdev->slot, check, data) :
+ pci_try_reset_bus(pdev->bus, check, data);
+}
+EXPORT_SYMBOL_GPL(pci_reset_bus_cond);
+
/**
* pci_reset_bus - Try to reset a PCI bus
* @pdev: top level PCI device to reset via slot/bus
*
- * Same as above except return -EAGAIN if the bus cannot be locked
+ * Same as above without the conditional check.
*/
int pci_reset_bus(struct pci_dev *pdev)
{
- return (!pci_probe_reset_slot(pdev->slot)) ?
- pci_try_reset_slot(pdev->slot) : pci_try_reset_bus(pdev->bus);
+ return pci_reset_bus_cond(pdev, NULL, NULL);
}
EXPORT_SYMBOL_GPL(pci_reset_bus);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 4469e1a77f3c1..416fd6b74abe4 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -230,7 +230,6 @@ enum pci_mmap_api {
int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
enum pci_mmap_api mmap_api);
-bool pci_reset_supported(struct pci_dev *dev);
void pci_init_reset_methods(struct pci_dev *dev);
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
int pci_bus_error_reset(struct pci_dev *dev);
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 3f11a9624b9c0..8e42342d56d3c 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -609,7 +609,6 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
if (ret == -EAGAIN)
goto out_disable_device;
- vdev->reset_works = !ret;
pci_save_state(pdev);
vdev->pci_saved_state = pci_store_saved_state(pdev);
if (!vdev->pci_saved_state)
@@ -766,7 +765,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
if (pci_load_and_free_saved_state(pdev, &vdev->pci_saved_state)) {
pci_info(pdev, "%s: Couldn't reload saved state\n", __func__);
- if (!vdev->reset_works)
+ if (!pci_reset_supported(pdev))
goto out;
pci_save_state(pdev);
@@ -785,12 +784,14 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
* We can not use the "try" reset interface here, which will
* overwrite the previously restored configuration information.
*/
- if (vdev->reset_works) {
+ if (pci_reset_supported(pdev)) {
bridge = pci_upstream_bridge(pdev);
if (bridge && !pci_dev_trylock(bridge))
goto out_restore_state;
if (pci_dev_trylock(pdev)) {
- if (!__pci_reset_function_locked(pdev))
+ /* Enforce function scope under lock for SR-IOV PFs */
+ if (!pci_num_vf(pdev) &&
+ !__pci_reset_function_locked(pdev))
vdev->needs_reset = false;
pci_dev_unlock(pdev);
}
@@ -892,6 +893,17 @@ static int vfio_pci_count_devs(struct pci_dev *pdev, void *data)
return 0;
}
+/*
+ * PCI walk callback to check for SR-IOV PFs with active VFs. VFs are not
+ * enumerated when determining affected devices and may be owned by separate
+ * userspace processes from the PF. It's therefore the user's responsibility
+ * to teardown VFs for any affected PF before performing a hot-reset.
+ */
+static int vfio_pci_dev_has_vfs(struct pci_dev *pdev, void *data)
+{
+ return pci_num_vf(pdev) ? -EBUSY : 0;
+}
+
struct vfio_pci_fill_info {
struct vfio_device *vdev;
struct vfio_pci_dependent_device *devices;
@@ -1085,7 +1097,7 @@ static int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,
info.flags = VFIO_DEVICE_FLAGS_PCI;
- if (vdev->reset_works)
+ if (pci_reset_supported(vdev->pdev))
info.flags |= VFIO_DEVICE_FLAGS_RESET;
info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
@@ -1317,7 +1329,7 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
{
int ret;
- if (!vdev->reset_works)
+ if (!pci_reset_supported(vdev->pdev))
return -EINVAL;
vfio_pci_zap_and_down_write_memory_lock(vdev);
@@ -2596,7 +2608,7 @@ static int vfio_pci_dev_set_hot_reset(struct vfio_device_set *dev_set,
list_for_each_entry(vdev, &dev_set->device_list, vdev.dev_set_list)
vfio_pci_set_power_state(vdev, PCI_D0);
- ret = pci_reset_bus(pdev);
+ ret = pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL);
vdev = list_last_entry(&dev_set->device_list,
struct vfio_pci_core_device, vdev.dev_set_list);
@@ -2659,7 +2671,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set)
if (vfio_pci_dev_set_pm_runtime_get(dev_set))
return;
- if (!pci_reset_bus(pdev))
+ if (!pci_reset_bus_cond(pdev, vfio_pci_dev_has_vfs, NULL))
reset_done = true;
list_for_each_entry(cur, &dev_set->device_list, vdev.dev_set_list) {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 64b308b6e61c1..4de21e6ac538f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1474,12 +1474,16 @@ void pcie_print_link_status(struct pci_dev *dev);
int pcie_reset_flr(struct pci_dev *dev, bool probe);
int pcie_flr(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev);
+bool pci_reset_supported(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev);
int pci_reset_function_locked(struct pci_dev *dev);
int pci_try_reset_function(struct pci_dev *dev);
int pci_probe_reset_slot(struct pci_slot *slot);
int pci_probe_reset_bus(struct pci_bus *bus);
int pci_reset_bus(struct pci_dev *dev);
+int pci_reset_bus_cond(struct pci_dev *pdev,
+ int (*check)(struct pci_dev *dev, void *data),
+ void *data);
void pci_reset_secondary_bus(struct pci_dev *dev);
void pcibios_reset_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno);
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index 9a1674c152aa2..6fb599ec29191 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -121,7 +121,6 @@ struct vfio_pci_core_device {
/* Flags only modified on setup/release - bitfield ok */
bool has_dyn_msix:1;
bool pci_2_3:1;
- bool reset_works:1;
bool extended_caps:1;
bool has_vga:1;
bool nointx:1;
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5de618a3a5eee..8603959f17350 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -772,6 +772,9 @@ struct vfio_pci_hot_reset_info {
* Mixed usage of legacy groups and cdevs across the set of affected
* devices is not supported.
*
+ * Hot reset of SR-IOV PFs with active VFs is not supported, SR-IOV
+ * should first be disabled on any affected PF.
+ *
* Return: 0 on success, -errno on failure.
*/
struct vfio_pci_hot_reset {
|
| 31/3 | 2026/08/12 05:25 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7187 output: 46 thoughts: 489 Thoughts: **Analyzing the PCI Reset Patch for SR-IOV PFs** Okay, so I'm looking at this patch and immediately, it's clear this is about tightening up the PCI reset functionality, specifically when we have Single Root I/O Virtualization (SR-IOV) Physical Functions (PFs) with active Virtual Functions (VFs). The primary goal seems to be preventing accidental resets of the PF if VFs are in use – a critical safeguard. The key change is the introduction of `pci_num_vf(dev) > 0` checks. This simple check is added to block PF resets when VFs are present. Smart. It's also making use of `pci_reset_bus_cond`, which lets us inject a callback for device status checks *before* a bus or slot reset is initiated. That's a powerful tool, providing more granular control. I see that `vfio_pci_core.c` has been refactored. The `vdev->reset_works` flag is gone, replaced with `pci_reset_supported(pdev)`. Function calls are generally preferred over flags for this kind of logic. In the context of `vfio_pci_core.c`, I'll need to check how the removal of that flag affects existing logic; this would be most important, especially related to the `VFIO_DEVICE_GET_INFO` ioctl. The addition of the `vfio_pci_dev_has_vfs` callback, returning `-EBUSY` when VFs are active, is clever. It's elegantly integrated into `pci_reset_bus_cond` within `vfio_pci_dev_set_hot_reset` and `vfio_pci_dev_set_try_reset`. This ensures that even attempts to reset through hot reset or try reset will respect the VF presence. My immediate concern is around potential uninitialized memory risks. I need to be sure the changes don't open up any vulnerabilities. While the patch mostly modifies control flow, returning `-ENOTTY` or `-EBUSY`, and swaps a flag for a function call, I need to verify that. I'm focusing on the change from `reset_works` to `pci_reset_supported(pdev)` – this is the crucial point to evaluate, particularly the context around `VFIO_DEVICE_GET_INFO` and the setting of `info.flags`. Okay, so looking at the code around `vfio_pci_ioctl_get_info`, it looks like `info` is a local variable. The patch is simply changing the criteria for setting `VFIO_DEVICE_FLAGS_RESET` through the use of `pci_reset_supported(vdev->pdev)`. I'll confirm that `info` is fully initialized, and that existing code path is covered by existing checks. I'll take a look at `drivers/vfio/pci/vfio_pci_core.c` around line 1085 to make sure. Let me use `default_api:read-file` to do a quick check... |
| 32/3 | 2026/08/12 05:26 | tool | read-file |
0mArgs:{
"File": "drivers/vfio/pci/vfio_pci_core.c",
"FirstLine": 1080,
"LineCount": 50
}Results: {
"Contents": "1080:\t}\n1081:\t\n1082:\tstatic int vfio_pci_ioctl_get_info(struct vfio_pci_core_device *vdev,\n1083:\t\t\t\t\t struct vfio_device_info __user *arg)\n1084:\t{\n1085:\t\tunsigned long minsz = offsetofend(struct vfio_device_info, num_irqs);\n1086:\t\tstruct vfio_device_info info = {};\n1087:\t\tstruct vfio_info_cap caps = { .buf = NULL, .size = 0 };\n1088:\t\tint ret;\n1089:\t\n1090:\t\tif (copy_from_user(\u0026info, arg, minsz))\n1091:\t\t\treturn -EFAULT;\n1092:\t\n1093:\t\tif (info.argsz \u003c minsz)\n1094:\t\t\treturn -EINVAL;\n1095:\t\n1096:\t\tminsz = min_t(size_t, info.argsz, sizeof(info));\n1097:\t\n1098:\t\tinfo.flags = VFIO_DEVICE_FLAGS_PCI;\n1099:\t\n1100:\t\tif (pci_reset_supported(vdev-\u003epdev))\n1101:\t\t\tinfo.flags |= VFIO_DEVICE_FLAGS_RESET;\n1102:\t\n1103:\t\tinfo.num_regions = VFIO_PCI_NUM_REGIONS + vdev-\u003enum_regions;\n1104:\t\tinfo.num_irqs = VFIO_PCI_NUM_IRQS;\n1105:\t\n1106:\t\tret = vfio_pci_info_zdev_add_caps(vdev, \u0026caps);\n1107:\t\tif (ret \u0026\u0026 ret != -ENODEV) {\n1108:\t\t\tpci_warn(vdev-\u003epdev,\n1109:\t\t\t\t \"Failed to setup zPCI info capabilities\\n\");\n1110:\t\t\treturn ret;\n1111:\t\t}\n1112:\t\n1113:\t\tret = vfio_pci_info_atomic_cap(vdev, \u0026caps);\n1114:\t\tif (ret \u0026\u0026 ret != -ENODEV) {\n1115:\t\t\tpci_warn(vdev-\u003epdev,\n1116:\t\t\t\t \"Failed to setup AtomicOps info capability\\n\");\n1117:\t\t\treturn ret;\n1118:\t\t}\n1119:\t\n1120:\t\tif (caps.size) {\n1121:\t\t\tinfo.flags |= VFIO_DEVICE_FLAGS_CAPS;\n1122:\t\t\tif (info.argsz \u003c sizeof(info) + caps.size) {\n1123:\t\t\t\tinfo.argsz = sizeof(info) + caps.size;\n1124:\t\t\t} else {\n1125:\t\t\t\tvfio_info_cap_shift(\u0026caps, sizeof(info));\n1126:\t\t\t\tif (copy_to_user(arg + 1, caps.buf, caps.size)) {\n1127:\t\t\t\t\tkfree(caps.buf);\n1128:\t\t\t\t\treturn -EFAULT;\n1129:\t\t\t\t}\n"
} |
| 33/3 | 2026/08/12 05:26 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9218 output: 292 thoughts: 526 Thoughts: **My Assessment of the PCI Reset Patch**
Okay, let's break this down. My initial impression is that this patch is pretty straightforward from a safety perspective, specifically concerning uninitialized memory. The `info` struct being initialized to `{}` right off the bat ensures it starts zeroed. The core of the patch focuses on modifying the logic around PCI device resets, particularly avoiding the reset of SR-IOV Physical Functions (PFs) that have active Virtual Functions (VFs).
The introduction of `pci_reset_bus_cond` is a key addition; it takes a callback, allowing for more granular device checks *before* a reset is triggered. This callback, `vfio_pci_dev_has_vfs` specifically, is used to prevent the reset of those PFs with active VFs. We are also introducing functions to aid the process in `pci_walk_reset_check`, `pci_try_reset_slot`, and `pci_try_reset_bus`, as well as exporting `pci_reset_supported`.
So, nothing jumps out as an uninitialized memory risk, info leaks, or complex data structures being sent to user space without proper initialization. KASAN and other standard bug detectors are the right tools here. The changes are largely about controlling the flow of the reset process and making sure the right PCI devices are targeted or skipped. I've confirmed this by examining all of the other changes: `vfio_pci_core_enable`, `vfio_pci_core_disable`, `vfio_pci_ioctl_get_info`, `vfio_pci_ioctl_reset`, `vfio_pci_dev_set_hot_reset`, and `vfio_pci_dev_set_try_reset` all seem to be leveraging this new conditional logic.
Given this, I'm comfortable setting `NeedsKMSAN=false` for this patch. The primary risk is the logic of when a reset happens, not *how* memory is handled.
|
| 34/3 | 2026/08/12 05:26 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch modifies the PCI reset logic to prevent resetting SR-IOV Physical Functions (PFs) when Virtual Functions (VFs) are active. It introduces a conditional bus reset function (`pci_reset_bus_cond`) that accepts a callback to check devices before performing a reset. In the VFIO PCI core, it replaces a cached `reset_works` boolean with direct calls to `pci_reset_supported()` and uses the new conditional reset API to check for active VFs.\n\nThese changes are purely related to control flow, device state management, and PCI subsystem APIs. They do not introduce new data structures sent to user space, nor do they modify buffer allocations, padding, or initialization logic that could lead to uninitialized memory reads or information leaks. The `vfio_device_info` structure modified in `vfio_pci_ioctl_get_info` is already fully zero-initialized (`struct vfio_device_info info = {};`).\n\nAny potential bugs introduced by this patch (e.g., locking issues, use-after-free, or NULL pointer dereferences) would be caught by standard KASAN, LOCKDEP, and other default sanitizers. There is no risk of uninitialized memory usage that would require a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch modifies the PCI reset logic to prevent resetting SR-IOV Physical Functions (PFs) when Virtual Functions (VFs) are active. It introduces a conditional bus reset function (`pci_reset_bus_cond`) that accepts a callback to check devices before performing a reset. In the VFIO PCI core, it replaces a cached `reset_works` boolean with direct calls to `pci_reset_supported()` and uses the new conditional reset API to check for active VFs.\n\nThese changes are purely related to control flow, device state management, and PCI subsystem APIs. They do not introduce new data structures sent to user space, nor do they modify buffer allocations, padding, or initialization logic that could lead to uninitialized memory reads or information leaks. The `vfio_device_info` structure modified in `vfio_pci_ioctl_get_info` is already fully zero-initialized (`struct vfio_device_info info = {};`).\n\nAny potential bugs introduced by this patch (e.g., locking issues, use-after-free, or NULL pointer dereferences) would be caught by standard KASAN, LOCKDEP, and other default sanitizers. There is no risk of uninitialized memory usage that would require a dedicated KMSAN fuzzing session.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|