| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/24 18:46 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"PTP_1588_CLOCK_OCP"
],
"FocusSymbols": [
"ptp_ocp_cpld_i2c_write",
"ptp_ocp_cpld_i2c_read",
"i2c_bus_ctrl_store",
"i2c_bus_ctrl_show",
"tap_i2c_errno_to_byte"
],
"Reasoning": "The patch adds new sysfs attributes (`cpld_i2c_xfer` and `i2c_bus_ctrl`) to the `ptp_ocp` driver for the ADVA x1 TAP board. These attributes allow userspace to perform I2C transfers and control the I2C bus arbitration register. The `ptp_ocp_cpld_i2c_write` function parses user input, allocates memory, and initiates I2C transfers, which is functional logic that should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/24 18:46 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 0fd4d0bd5e8d29f9381f10da37d958688c00f219\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Jul 24 18:46:16 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/ABI/testing/sysfs-timecard b/Documentation/ABI/testing/sysfs-timecard\nindex 3ae41b7634ac9e..c62766df7a202e 100644\n--- a/Documentation/ABI/testing/sysfs-timecard\n+++ b/Documentation/ABI/testing/sysfs-timecard\n@@ -11,6 +11,62 @@ Contact:\tJonathan Lemon \u003cjonathan.lemon@gmail.com\u003e\n Description:\tThis directory contains the attributes of the Nth timecard\n \t\tregistered.\n \n+What:\t\t/sys/class/timecard/ocpN/cpld_i2c_xfer\n+Date:\t\tJuly 2026\n+Contact:\tSagi Maimon \u003csagi.maimon@adva.com\u003e\n+Description:\t(RW) Binary sysfs attribute providing a raw I2C passthrough to\n+\t\tthe CPLD and I2C mux on ADVA x1 TAP boards. Only present on\n+\t\tthat board variant.\n+\n+\t\tEach write initiates one I2C transaction. The write payload\n+\t\tmust be exactly four header bytes followed by the write data:\n+\n+\t\t Byte 0: slave address (only 0x40 and 0x74 are permitted)\n+\t\t Byte 1: number of bytes to write (0..67)\n+\t\t Byte 2: number of bytes to read back (0..20)\n+\t\t Byte 3: flags\n+\t\t bit 0 - suppress the repeated START before the\n+\t\t read segment (I2C_M_NOSTART); only valid\n+\t\t when both write and read lengths are\n+\t\t non-zero\n+\t\t Bytes 4..: write data (write_len bytes)\n+\n+\t\tA subsequent read() returns:\n+\n+\t\t Byte 0: status (0 = success, positive errno on error)\n+\t\t Bytes 1..: read data (read_len bytes), present only when\n+\t\t status is 0 and read_len \u003e 0\n+\n+\t\tThe write and read portions of the sysfs file share a single\n+\t\tper-device response buffer protected by a mutex; a single\n+\t\topen() / write() / read() sequence must be used to avoid\n+\t\tdata races between concurrent users.\n+\n+\t\tOnly slave addresses 0x40 (Lattice CPLD) and 0x74 (PCA9548\n+\t\tI2C mux) are accepted; all others return EPERM.\n+\n+What:\t\t/sys/class/timecard/ocpN/i2c_bus_ctrl\n+Date:\t\tJuly 2026\n+Contact:\tSagi Maimon \u003csagi.maimon@adva.com\u003e\n+Description:\t(RW) Exposes the MicroBlaze I2C bus arbitration register for\n+\t\tthe shared I2C bus on ADVA x1 and x2 TAP boards. Only\n+\t\tpresent when the board has a pps_select register block.\n+\n+\t\tUserspace must complete a three-step handshake before\n+\t\tdriving the bus:\n+\n+\t\t 1. Read - value must be 0x00000000 (bus is free).\n+\t\t 2. Write - 0x0000ffff (request ownership).\n+\t\t 3. Poll - read until the value is 0xffffffff (MicroBlaze\n+\t\t has acknowledged the handover).\n+\n+\t\tAfter all I2C traffic is complete the bus must be released\n+\t\tby writing 0x00000000.\n+\n+\t\tThe poll read is a PCIe non-posted read and therefore also\n+\t\tflushes the preceding posted write to the FPGA; no\n+\t\tadditional read-back is required for ordering.\n+\n What:\t\t/sys/class/timecard/ocpN/available_clock_sources\n Date:\t\tSeptember 2021\n Contact:\tJonathan Lemon \u003cjonathan.lemon@gmail.com\u003e\ndiff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c\nindex 35e911f1ad78c0..79fec5161c997b 100644\n--- a/drivers/ptp/ptp_ocp.c\n+++ b/drivers/ptp/ptp_ocp.c\n@@ -163,7 +163,8 @@ struct gpio_reg {\n \tu32\tgpio1;\n \tu32\t__pad0;\n \tu32\tgpio2;\n-\tu32\t__pad1;\n+\t/* adva_x1: I2C bus ownership register; reserved on other variants */\n+\tu32\ti2c_bus_ctrl;\n };\n \n struct irig_master_reg {\n@@ -416,6 +417,11 @@ struct ptp_ocp {\n \tdpll_tracker tracker;\n \tint signals_nr;\n \tint freq_in_nr;\n+\t/* cpld_i2c_xfer sysfs (adva_x1) */\n+\tstruct mutex\t\ttap_i2c_lock;\n+\tint\t\t\ttap_i2c_adap_nr; /* adapter nr; -1 if absent */\n+\tu8\t\t\ttap_i2c_rsp[21]; /* [status, read_data...] */\n+\tsize_t\t\t\ttap_i2c_rsp_len;\n };\n \n #define OCP_REQ_TIMESTAMP\tBIT(0)\n@@ -4224,6 +4230,205 @@ static const struct ocp_attr_group art_timecard_groups[] = {\n \t{ },\n };\n \n+/*\n+ * i2c_bus_ctrl exposes the MicroBlaze I2C bus arbitration register.\n+ *\n+ * The shared bus requires a three-step handshake before use:\n+ * read 0x00000000 (free) -\u003e write 0x0000ffff (request) -\u003e\n+ * poll until 0xffffffff (MicroBlaze confirms release).\n+ *\n+ * The poll is a PCIe non-posted read, which also flushes the preceding\n+ * posted write to the FPGA, so no separate kernel read-back is needed.\n+ */\n+static ssize_t\n+i2c_bus_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(dev);\n+\n+\tif (!bp-\u003epps_select)\n+\t\treturn -ENODEV;\n+\treturn sysfs_emit(buf, \"0x%08x\\n\",\n+\t\t\t ioread32(\u0026bp-\u003epps_select-\u003ei2c_bus_ctrl));\n+}\n+\n+static ssize_t\n+i2c_bus_ctrl_store(struct device *dev, struct device_attribute *attr,\n+\t\t const char *buf, size_t count)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(dev);\n+\tu32 val;\n+\n+\tif (!bp-\u003epps_select)\n+\t\treturn -ENODEV;\n+\tif (kstrtou32(buf, 0, \u0026val))\n+\t\treturn -EINVAL;\n+\tiowrite32(val, \u0026bp-\u003epps_select-\u003ei2c_bus_ctrl);\n+\treturn count;\n+}\n+\n+static DEVICE_ATTR_RW(i2c_bus_ctrl);\n+\n+/*\n+ * cpld_i2c_xfer - sysfs binary I2C passthrough for adva_x1 TAP CPLD.\n+ *\n+ * write: [addr][write_len][read_len][flags][write_data...]\n+ * flags bit 0: I2C_M_NOSTART on the read segment\n+ * read: [status][read_data...]\n+ * status 0 = success, else positive errno\n+ *\n+ * Only addresses 0x40 (CPLD) and 0x74 (mux) are permitted.\n+ */\n+#define TAP_I2C_ALLOWED_ADDRS_NUM 2\n+static const u8 tap_i2c_allowed_addrs[TAP_I2C_ALLOWED_ADDRS_NUM] = {\n+\t0x40, /* CPLD */\n+\t0x74, /* mux */\n+};\n+\n+/*\n+ * tap_i2c_errno_to_byte - encode a kernel errno as a one-byte status.\n+ *\n+ * Errnos \u003e 255 (e.g. ENOTSUPP=524) or multiples of 256 would truncate\n+ * to a wrong or zero value with a plain (u8) cast. Map those to EIO.\n+ */\n+static u8 tap_i2c_errno_to_byte(int err)\n+{\n+\tint val = (err \u003c 0) ? -err : EIO;\n+\n+\treturn (val \u003e 0 \u0026\u0026 val \u003c= 0xFF) ? (u8)val : EIO;\n+}\n+\n+#define TAP_I2C_REQ_HDR_LEN 4\n+#define TAP_I2C_MAX_WRITE_LEN 67\n+#define TAP_I2C_MAX_READ_LEN 20\n+#define TAP_I2C_FLAG_NOSTART BIT(0)\n+\n+static ssize_t\n+ptp_ocp_cpld_i2c_write(struct file *file, struct kobject *kobj,\n+\t\t const struct bin_attribute *attr,\n+\t\t char *buf, loff_t off, size_t count)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));\n+\tconst u8 *req = (const u8 *)buf;\n+\tu8 addr, write_len, read_len, flags;\n+\tstruct i2c_adapter *adap;\n+\tstruct i2c_msg msgs[2];\n+\tu8 *rdbuf = NULL;\n+\tint nmsgs, ret, i;\n+\n+\t/* Each write is one atomic request; non-zero offset means a\n+\t * mid-buffer pwrite() which would misparse the header.\n+\t */\n+\tif (off != 0)\n+\t\treturn -EINVAL;\n+\tif (count \u003c TAP_I2C_REQ_HDR_LEN || count \u003e TAP_I2C_REQ_HDR_LEN + TAP_I2C_MAX_WRITE_LEN)\n+\t\treturn -EINVAL;\n+\n+\taddr = req[0];\n+\twrite_len = req[1];\n+\tread_len = req[2];\n+\tflags = req[3];\n+\n+\t/* Validate */\n+\tfor (i = 0; i \u003c TAP_I2C_ALLOWED_ADDRS_NUM; i++)\n+\t\tif (addr == tap_i2c_allowed_addrs[i])\n+\t\t\tbreak;\n+\tif (i == TAP_I2C_ALLOWED_ADDRS_NUM)\n+\t\treturn -EPERM;\n+\n+\tif (write_len \u003e TAP_I2C_MAX_WRITE_LEN)\n+\t\treturn -EINVAL;\n+\tif (read_len \u003e TAP_I2C_MAX_READ_LEN)\n+\t\treturn -EINVAL;\n+\tif (write_len + TAP_I2C_REQ_HDR_LEN \u003e count)\n+\t\treturn -EINVAL;\n+\tif (write_len == 0 \u0026\u0026 read_len == 0)\n+\t\treturn -EINVAL;\n+\t/* I2C_M_NOSTART suppresses the repeated START between write and read\n+\t * segments; it has no meaning on a first-and-only message.\n+\t */\n+\tif ((flags \u0026 TAP_I2C_FLAG_NOSTART) \u0026\u0026 write_len == 0)\n+\t\treturn -EINVAL;\n+\n+\t/* i2c_get_adapter() takes a reference under core_lock; safe against\n+\t * concurrent adapter unbind.\n+\t */\n+\tadap = i2c_get_adapter(READ_ONCE(bp-\u003etap_i2c_adap_nr));\n+\tif (!adap)\n+\t\treturn -ENODEV;\n+\n+\tnmsgs = 0;\n+\tif (write_len \u003e 0) {\n+\t\tmsgs[nmsgs].addr = addr;\n+\t\tmsgs[nmsgs].flags = 0;\n+\t\tmsgs[nmsgs].len = write_len;\n+\t\tmsgs[nmsgs].buf = (u8 *)req + TAP_I2C_REQ_HDR_LEN;\n+\t\tnmsgs++;\n+\t}\n+\tif (read_len \u003e 0) {\n+\t\tu16 rd_flags = I2C_M_RD;\n+\n+\t\tif (flags \u0026 TAP_I2C_FLAG_NOSTART)\n+\t\t\trd_flags |= I2C_M_NOSTART;\n+\t\tmsgs[nmsgs].addr = addr;\n+\t\tmsgs[nmsgs].flags = rd_flags | I2C_M_DMA_SAFE;\n+\t\tmsgs[nmsgs].len = read_len;\n+\t\trdbuf = kzalloc(read_len, GFP_KERNEL);\n+\t\tif (!rdbuf) {\n+\t\t\ti2c_put_adapter(adap);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t\tmsgs[nmsgs].buf = rdbuf;\n+\t\tnmsgs++;\n+\t}\n+\n+\t/* Serialise transfer+publish so concurrent writers cannot overwrite\n+\t * each other's response in tap_i2c_rsp.\n+\t */\n+\tmutex_lock(\u0026bp-\u003etap_i2c_lock);\n+\tret = i2c_transfer(adap, msgs, nmsgs);\n+\tif (ret == nmsgs) {\n+\t\tbp-\u003etap_i2c_rsp[0] = 0;\n+\t\tif (read_len \u003e 0)\n+\t\t\tmemcpy(\u0026bp-\u003etap_i2c_rsp[1], rdbuf, read_len);\n+\t\tbp-\u003etap_i2c_rsp_len = 1 + read_len;\n+\t\tret = count;\n+\t} else {\n+\t\tbp-\u003etap_i2c_rsp[0] = tap_i2c_errno_to_byte(ret);\n+\t\tbp-\u003etap_i2c_rsp_len = 1;\n+\t\tret = (ret \u003c 0) ? ret : -EIO;\n+\t}\n+\tmutex_unlock(\u0026bp-\u003etap_i2c_lock);\n+\tkfree(rdbuf);\n+\ti2c_put_adapter(adap);\n+\n+\treturn ret;\n+}\n+\n+static ssize_t\n+ptp_ocp_cpld_i2c_read(struct file *file, struct kobject *kobj,\n+\t\t const struct bin_attribute *attr,\n+\t\t char *buf, loff_t off, size_t count)\n+{\n+\tstruct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));\n+\tssize_t ret;\n+\n+\tmutex_lock(\u0026bp-\u003etap_i2c_lock);\n+\tif (off \u003e= bp-\u003etap_i2c_rsp_len) {\n+\t\tret = 0;\n+\t} else {\n+\t\tret = min(count, bp-\u003etap_i2c_rsp_len - (size_t)off);\n+\t\tmemcpy(buf, bp-\u003etap_i2c_rsp + off, ret);\n+\t}\n+\tmutex_unlock(\u0026bp-\u003etap_i2c_lock);\n+\treturn ret;\n+}\n+\n+static const struct bin_attribute tap_i2c_bin_attr = {\n+\t.attr = { .name = \"cpld_i2c_xfer\", .mode = 0600 },\n+\t.write = ptp_ocp_cpld_i2c_write,\n+\t.read = ptp_ocp_cpld_i2c_read,\n+};\n+\n static struct attribute *adva_timecard_attrs[] = {\n \t\u0026dev_attr_serialnum.attr,\n \t\u0026dev_attr_gnss_sync.attr,\n@@ -4272,11 +4477,18 @@ static struct attribute *adva_timecard_x1_attrs[] = {\n \t\u0026dev_attr_ts_window_adjust.attr,\n \t\u0026dev_attr_utc_tai_offset.attr,\n \t\u0026dev_attr_tod_correction.attr,\n+\t\u0026dev_attr_i2c_bus_ctrl.attr,\n+\tNULL,\n+};\n+\n+static const struct bin_attribute *const bin_adva_x1_timecard_attrs[] = {\n+\t\u0026tap_i2c_bin_attr,\n \tNULL,\n };\n \n static const struct attribute_group adva_timecard_x1_group = {\n-\t.attrs = adva_timecard_x1_attrs,\n+\t.attrs = adva_timecard_x1_attrs,\n+\t.bin_attrs = bin_adva_x1_timecard_attrs,\n };\n \n static const struct ocp_attr_group adva_timecard_x1_groups[] = {\n@@ -4902,6 +5114,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)\n \t\tclk_hw_unregister_fixed_rate(bp-\u003ei2c_clk);\n \tif (bp-\u003en_irqs)\n \t\tpci_free_irq_vectors(bp-\u003epdev);\n+\tmutex_destroy(\u0026bp-\u003etap_i2c_lock);\n \tdevice_unregister(\u0026bp-\u003edev);\n }\n \n@@ -5078,6 +5291,17 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \tif (err)\n \t\tgoto out_disable;\n \n+\t/* Must be before the first error path that calls ptp_ocp_detach(),\n+\t * so mutex_destroy() always runs on an initialised mutex.\n+\t * Must also be before ptp_ocp_register_resources(): the I2C bus\n+\t * notifier (ptp_ocp_i2c_notifier_call) fires when the adapter\n+\t * registers and stores the adapter number in tap_i2c_adap_nr; the\n+\t * -1 sentinel below must already be written so that a notifier\n+\t * firing during registration is never overwritten by this init.\n+\t */\n+\tmutex_init(\u0026bp-\u003etap_i2c_lock);\n+\tbp-\u003etap_i2c_adap_nr = -1;\n+\n \tINIT_DELAYED_WORK(\u0026bp-\u003esync_work, ptp_ocp_sync_work);\n \n \t/* compat mode.\n@@ -5217,11 +5441,16 @@ ptp_ocp_i2c_notifier_call(struct notifier_block *nb,\n \n found:\n \tbp = dev_get_drvdata(dev);\n-\tif (add)\n+\tif (add) {\n \t\tptp_ocp_symlink(bp, child, \"i2c\");\n-\telse\n+\t\t/* Cache adapter number; cpld_i2c_xfer uses i2c_get_adapter()\n+\t\t * for a reference-counted, unbind-safe lookup.\n+\t\t */\n+\t\tWRITE_ONCE(bp-\u003etap_i2c_adap_nr, i2c_verify_adapter(child)-\u003enr);\n+\t} else {\n+\t\tWRITE_ONCE(bp-\u003etap_i2c_adap_nr, -1);\t/* invalidate before free */\n \t\tsysfs_remove_link(\u0026bp-\u003edev.kobj, \"i2c\");\n-\n+\t}\n \treturn 0;\n }\n \n"
} |
| 2/1 | 2026/07/24 18:46 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"PTP_1588_CLOCK_OCP"
],
"FocusSymbols": [
"ptp_ocp_cpld_i2c_write",
"ptp_ocp_cpld_i2c_read",
"i2c_bus_ctrl_store",
"i2c_bus_ctrl_show",
"tap_i2c_errno_to_byte"
],
"Reasoning": "The patch adds new sysfs attributes (`cpld_i2c_xfer` and `i2c_bus_ctrl`) to the `ptp_ocp` driver for the ADVA x1 TAP board. These attributes allow userspace to perform I2C transfers and control the I2C bus arbitration register. The `ptp_ocp_cpld_i2c_write` function parses user input, allocates memory, and initiates I2C transfers, which is functional logic that should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). 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. 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. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. 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 0fd4d0bd5e8d29f9381f10da37d958688c00f219
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Jul 24 18:46:16 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/ABI/testing/sysfs-timecard b/Documentation/ABI/testing/sysfs-timecard
index 3ae41b7634ac9e..c62766df7a202e 100644
--- a/Documentation/ABI/testing/sysfs-timecard
+++ b/Documentation/ABI/testing/sysfs-timecard
@@ -11,6 +11,62 @@ Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
Description: This directory contains the attributes of the Nth timecard
registered.
+What: /sys/class/timecard/ocpN/cpld_i2c_xfer
+Date: July 2026
+Contact: Sagi Maimon <sagi.maimon@adva.com>
+Description: (RW) Binary sysfs attribute providing a raw I2C passthrough to
+ the CPLD and I2C mux on ADVA x1 TAP boards. Only present on
+ that board variant.
+
+ Each write initiates one I2C transaction. The write payload
+ must be exactly four header bytes followed by the write data:
+
+ Byte 0: slave address (only 0x40 and 0x74 are permitted)
+ Byte 1: number of bytes to write (0..67)
+ Byte 2: number of bytes to read back (0..20)
+ Byte 3: flags
+ bit 0 - suppress the repeated START before the
+ read segment (I2C_M_NOSTART); only valid
+ when both write and read lengths are
+ non-zero
+ Bytes 4..: write data (write_len bytes)
+
+ A subsequent read() returns:
+
+ Byte 0: status (0 = success, positive errno on error)
+ Bytes 1..: read data (read_len bytes), present only when
+ status is 0 and read_len > 0
+
+ The write and read portions of the sysfs file share a single
+ per-device response buffer protected by a mutex; a single
+ open() / write() / read() sequence must be used to avoid
+ data races between concurrent users.
+
+ Only slave addresses 0x40 (Lattice CPLD) and 0x74 (PCA9548
+ I2C mux) are accepted; all others return EPERM.
+
+What: /sys/class/timecard/ocpN/i2c_bus_ctrl
+Date: July 2026
+Contact: Sagi Maimon <sagi.maimon@adva.com>
+Description: (RW) Exposes the MicroBlaze I2C bus arbitration register for
+ the shared I2C bus on ADVA x1 and x2 TAP boards. Only
+ present when the board has a pps_select register block.
+
+ Userspace must complete a three-step handshake before
+ driving the bus:
+
+ 1. Read - value must be 0x00000000 (bus is free).
+ 2. Write - 0x0000ffff (request ownership).
+ 3. Poll - read until the value is 0xffffffff (MicroBlaze
+ has acknowledged the handover).
+
+ After all I2C traffic is complete the bus must be released
+ by writing 0x00000000.
+
+ The poll read is a PCIe non-posted read and therefore also
+ flushes the preceding posted write to the FPGA; no
+ additional read-back is required for ordering.
+
What: /sys/class/timecard/ocpN/available_clock_sources
Date: September 2021
Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 35e911f1ad78c0..79fec5161c997b 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -163,7 +163,8 @@ struct gpio_reg {
u32 gpio1;
u32 __pad0;
u32 gpio2;
- u32 __pad1;
+ /* adva_x1: I2C bus ownership register; reserved on other variants */
+ u32 i2c_bus_ctrl;
};
struct irig_master_reg {
@@ -416,6 +417,11 @@ struct ptp_ocp {
dpll_tracker tracker;
int signals_nr;
int freq_in_nr;
+ /* cpld_i2c_xfer sysfs (adva_x1) */
+ struct mutex tap_i2c_lock;
+ int tap_i2c_adap_nr; /* adapter nr; -1 if absent */
+ u8 tap_i2c_rsp[21]; /* [status, read_data...] */
+ size_t tap_i2c_rsp_len;
};
#define OCP_REQ_TIMESTAMP BIT(0)
@@ -4224,6 +4230,205 @@ static const struct ocp_attr_group art_timecard_groups[] = {
{ },
};
+/*
+ * i2c_bus_ctrl exposes the MicroBlaze I2C bus arbitration register.
+ *
+ * The shared bus requires a three-step handshake before use:
+ * read 0x00000000 (free) -> write 0x0000ffff (request) ->
+ * poll until 0xffffffff (MicroBlaze confirms release).
+ *
+ * The poll is a PCIe non-posted read, which also flushes the preceding
+ * posted write to the FPGA, so no separate kernel read-back is needed.
+ */
+static ssize_t
+i2c_bus_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+
+ if (!bp->pps_select)
+ return -ENODEV;
+ return sysfs_emit(buf, "0x%08x\n",
+ ioread32(&bp->pps_select->i2c_bus_ctrl));
+}
+
+static ssize_t
+i2c_bus_ctrl_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ if (!bp->pps_select)
+ return -ENODEV;
+ if (kstrtou32(buf, 0, &val))
+ return -EINVAL;
+ iowrite32(val, &bp->pps_select->i2c_bus_ctrl);
+ return count;
+}
+
+static DEVICE_ATTR_RW(i2c_bus_ctrl);
+
+/*
+ * cpld_i2c_xfer - sysfs binary I2C passthrough for adva_x1 TAP CPLD.
+ *
+ * write: [addr][write_len][read_len][flags][write_data...]
+ * flags bit 0: I2C_M_NOSTART on the read segment
+ * read: [status][read_data...]
+ * status 0 = success, else positive errno
+ *
+ * Only addresses 0x40 (CPLD) and 0x74 (mux) are permitted.
+ */
+#define TAP_I2C_ALLOWED_ADDRS_NUM 2
+static const u8 tap_i2c_allowed_addrs[TAP_I2C_ALLOWED_ADDRS_NUM] = {
+ 0x40, /* CPLD */
+ 0x74, /* mux */
+};
+
+/*
+ * tap_i2c_errno_to_byte - encode a kernel errno as a one-byte status.
+ *
+ * Errnos > 255 (e.g. ENOTSUPP=524) or multiples of 256 would truncate
+ * to a wrong or zero value with a plain (u8) cast. Map those to EIO.
+ */
+static u8 tap_i2c_errno_to_byte(int err)
+{
+ int val = (err < 0) ? -err : EIO;
+
+ return (val > 0 && val <= 0xFF) ? (u8)val : EIO;
+}
+
+#define TAP_I2C_REQ_HDR_LEN 4
+#define TAP_I2C_MAX_WRITE_LEN 67
+#define TAP_I2C_MAX_READ_LEN 20
+#define TAP_I2C_FLAG_NOSTART BIT(0)
+
+static ssize_t
+ptp_ocp_cpld_i2c_write(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
+ const u8 *req = (const u8 *)buf;
+ u8 addr, write_len, read_len, flags;
+ struct i2c_adapter *adap;
+ struct i2c_msg msgs[2];
+ u8 *rdbuf = NULL;
+ int nmsgs, ret, i;
+
+ /* Each write is one atomic request; non-zero offset means a
+ * mid-buffer pwrite() which would misparse the header.
+ */
+ if (off != 0)
+ return -EINVAL;
+ if (count < TAP_I2C_REQ_HDR_LEN || count > TAP_I2C_REQ_HDR_LEN + TAP_I2C_MAX_WRITE_LEN)
+ return -EINVAL;
+
+ addr = req[0];
+ write_len = req[1];
+ read_len = req[2];
+ flags = req[3];
+
+ /* Validate */
+ for (i = 0; i < TAP_I2C_ALLOWED_ADDRS_NUM; i++)
+ if (addr == tap_i2c_allowed_addrs[i])
+ break;
+ if (i == TAP_I2C_ALLOWED_ADDRS_NUM)
+ return -EPERM;
+
+ if (write_len > TAP_I2C_MAX_WRITE_LEN)
+ return -EINVAL;
+ if (read_len > TAP_I2C_MAX_READ_LEN)
+ return -EINVAL;
+ if (write_len + TAP_I2C_REQ_HDR_LEN > count)
+ return -EINVAL;
+ if (write_len == 0 && read_len == 0)
+ return -EINVAL;
+ /* I2C_M_NOSTART suppresses the repeated START between write and read
+ * segments; it has no meaning on a first-and-only message.
+ */
+ if ((flags & TAP_I2C_FLAG_NOSTART) && write_len == 0)
+ return -EINVAL;
+
+ /* i2c_get_adapter() takes a reference under core_lock; safe against
+ * concurrent adapter unbind.
+ */
+ adap = i2c_get_adapter(READ_ONCE(bp->tap_i2c_adap_nr));
+ if (!adap)
+ return -ENODEV;
+
+ nmsgs = 0;
+ if (write_len > 0) {
+ msgs[nmsgs].addr = addr;
+ msgs[nmsgs].flags = 0;
+ msgs[nmsgs].len = write_len;
+ msgs[nmsgs].buf = (u8 *)req + TAP_I2C_REQ_HDR_LEN;
+ nmsgs++;
+ }
+ if (read_len > 0) {
+ u16 rd_flags = I2C_M_RD;
+
+ if (flags & TAP_I2C_FLAG_NOSTART)
+ rd_flags |= I2C_M_NOSTART;
+ msgs[nmsgs].addr = addr;
+ msgs[nmsgs].flags = rd_flags | I2C_M_DMA_SAFE;
+ msgs[nmsgs].len = read_len;
+ rdbuf = kzalloc(read_len, GFP_KERNEL);
+ if (!rdbuf) {
+ i2c_put_adapter(adap);
+ return -ENOMEM;
+ }
+ msgs[nmsgs].buf = rdbuf;
+ nmsgs++;
+ }
+
+ /* Serialise transfer+publish so concurrent writers cannot overwrite
+ * each other's response in tap_i2c_rsp.
+ */
+ mutex_lock(&bp->tap_i2c_lock);
+ ret = i2c_transfer(adap, msgs, nmsgs);
+ if (ret == nmsgs) {
+ bp->tap_i2c_rsp[0] = 0;
+ if (read_len > 0)
+ memcpy(&bp->tap_i2c_rsp[1], rdbuf, read_len);
+ bp->tap_i2c_rsp_len = 1 + read_len;
+ ret = count;
+ } else {
+ bp->tap_i2c_rsp[0] = tap_i2c_errno_to_byte(ret);
+ bp->tap_i2c_rsp_len = 1;
+ ret = (ret < 0) ? ret : -EIO;
+ }
+ mutex_unlock(&bp->tap_i2c_lock);
+ kfree(rdbuf);
+ i2c_put_adapter(adap);
+
+ return ret;
+}
+
+static ssize_t
+ptp_ocp_cpld_i2c_read(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
+ ssize_t ret;
+
+ mutex_lock(&bp->tap_i2c_lock);
+ if (off >= bp->tap_i2c_rsp_len) {
+ ret = 0;
+ } else {
+ ret = min(count, bp->tap_i2c_rsp_len - (size_t)off);
+ memcpy(buf, bp->tap_i2c_rsp + off, ret);
+ }
+ mutex_unlock(&bp->tap_i2c_lock);
+ return ret;
+}
+
+static const struct bin_attribute tap_i2c_bin_attr = {
+ .attr = { .name = "cpld_i2c_xfer", .mode = 0600 },
+ .write = ptp_ocp_cpld_i2c_write,
+ .read = ptp_ocp_cpld_i2c_read,
+};
+
static struct attribute *adva_timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gnss_sync.attr,
@@ -4272,11 +4477,18 @@ static struct attribute *adva_timecard_x1_attrs[] = {
&dev_attr_ts_window_adjust.attr,
&dev_attr_utc_tai_offset.attr,
&dev_attr_tod_correction.attr,
+ &dev_attr_i2c_bus_ctrl.attr,
+ NULL,
+};
+
+static const struct bin_attribute *const bin_adva_x1_timecard_attrs[] = {
+ &tap_i2c_bin_attr,
NULL,
};
static const struct attribute_group adva_timecard_x1_group = {
- .attrs = adva_timecard_x1_attrs,
+ .attrs = adva_timecard_x1_attrs,
+ .bin_attrs = bin_adva_x1_timecard_attrs,
};
static const struct ocp_attr_group adva_timecard_x1_groups[] = {
@@ -4902,6 +5114,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)
clk_hw_unregister_fixed_rate(bp->i2c_clk);
if (bp->n_irqs)
pci_free_irq_vectors(bp->pdev);
+ mutex_destroy(&bp->tap_i2c_lock);
device_unregister(&bp->dev);
}
@@ -5078,6 +5291,17 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto out_disable;
+ /* Must be before the first error path that calls ptp_ocp_detach(),
+ * so mutex_destroy() always runs on an initialised mutex.
+ * Must also be before ptp_ocp_register_resources(): the I2C bus
+ * notifier (ptp_ocp_i2c_notifier_call) fires when the adapter
+ * registers and stores the adapter number in tap_i2c_adap_nr; the
+ * -1 sentinel below must already be written so that a notifier
+ * firing during registration is never overwritten by this init.
+ */
+ mutex_init(&bp->tap_i2c_lock);
+ bp->tap_i2c_adap_nr = -1;
+
INIT_DELAYED_WORK(&bp->sync_work, ptp_ocp_sync_work);
/* compat mode.
@@ -5217,11 +5441,16 @@ ptp_ocp_i2c_notifier_call(struct notifier_block *nb,
found:
bp = dev_get_drvdata(dev);
- if (add)
+ if (add) {
ptp_ocp_symlink(bp, child, "i2c");
- else
+ /* Cache adapter number; cpld_i2c_xfer uses i2c_get_adapter()
+ * for a reference-counted, unbind-safe lookup.
+ */
+ WRITE_ONCE(bp->tap_i2c_adap_nr, i2c_verify_adapter(child)->nr);
+ } else {
+ WRITE_ONCE(bp->tap_i2c_adap_nr, -1); /* invalidate before free */
sysfs_remove_link(&bp->dev.kobj, "i2c");
-
+ }
return 0;
}
|
| 3/2 | 2026/07/24 18:46 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 6560 output: 27 thoughts: 207 Thoughts: **Analyzing a New Patch for the PTP OCP Driver** Okay, so I've got this patch here that introduces some new sysfs attributes to `drivers/ptp/ptp_ocp.c`. Specifically, they're adding `i2c_bus_ctrl`, which is read-write, and then `cpld_i2c_xfer`, which is a read-write binary attribute. My first thought is always to assess the fuzzing potential. Since it modifies a driver, it's a good candidate. This patch touches the "Open Compute Project time card" driver. I remember this one; it's a PCI device driver. The probe function is `ptp_ocp_probe`, and the patch adds these new sysfs attributes. Now, can syzkaller handle these sysfs attributes? Yes, it absolutely can. Either if there are direct descriptions or even just through generic sysfs fuzzing. Actually, I seem to recall syzkaller *does* have sysfs descriptions. Great. That's a huge plus. The next step, always, is to check if `ptp_ocp` is actually enabled in the kernel config. That's a crucial first step; no point in trying to fuzz something that isn't built! |
| 4/2 | 2026/07/24 18:46 | tool | grepper |
0mArgs:{
"Expression": "config PTP_1588_CLOCK_OCP"
}Results: {
"Output": "drivers/ptp/Kconfig=198=config PTP_1588_CLOCK_VMW\n--\ndrivers/ptp/Kconfig-209-\ndrivers/ptp/Kconfig:210:config PTP_1588_CLOCK_OCP\ndrivers/ptp/Kconfig-211-\ttristate \"OpenCompute TimeCard as PTP clock\"\n"
} |
| 5/2 | 2026/07/24 18:46 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7172 output: 29 thoughts: 9 Thoughts: Okay, let's break this down. **Analyzing Dependencies** Right, so the first thing I need to do is get a clear picture of all the pieces this thing relies on. I can't even begin to understand its behavior or potential issues until I map out its dependencies. It's like building a house – you need to know where the foundation, framing, and utilities are coming from before you can even think about the interior design. I need to know *everything* it's tied to. Understanding the interconnections is the critical first step. |
| 6/2 | 2026/07/24 18:46 | tool | grepper |
0mError:no matches Args: {
"Expression": "depends on.*PTP_1588_CLOCK_OCP"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/07/24 18:46 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7340 output: 35 thoughts: 23 Thoughts: Okay, let's dive into this. Here's my thought process on this Kconfig entry: **Analyzing the Kconfig Entry for PTP_1588_CLOCK_OCP** Alright, before I make any decisions or recommendations, I need to understand this Kconfig option, `PTP_1588_CLOCK_OCP`, inside and out. I'm going to start by meticulously reading it. What are its dependencies? What other configurations does it interact with? Are there any obvious conflicts or implications I need to consider for my current architecture or project goals? I'm looking for the granular details – the subtleties that will define how this clock integrates into the broader system and whether it truly leverages OCP as expected. I need to know how it might affect the precision and performance of the PTP implementation. I'll be keeping an open mind as I read, and make notes of the assumptions the author may have made and what possible edge-cases may need attention. Let's see what we've got! |
| 8/2 | 2026/07/24 18:46 | tool | read-file |
0mArgs:{
"File": "drivers/ptp/Kconfig",
"FirstLine": 210,
"LineCount": 20
}Results: {
"Contents": " 210:\tconfig PTP_1588_CLOCK_OCP\n 211:\t\ttristate \"OpenCompute TimeCard as PTP clock\"\n 212:\t\tdepends on PTP_1588_CLOCK\n 213:\t\tdepends on HAS_IOMEM \u0026\u0026 PCI\n 214:\t\tdepends on I2C \u0026\u0026 MTD\n 215:\t\tdepends on SERIAL_8250\n 216:\t\tdepends on !S390\n 217:\t\tdepends on COMMON_CLK\n 218:\t\tselect NET_DEVLINK\n 219:\t\tselect CRC16\n 220:\t\tselect DPLL\n 221:\t\thelp\n 222:\t\t This driver adds support for an OpenCompute time card.\n 223:\t\n 224:\t\t The OpenCompute time card is an atomic clock along with\n 225:\t\t a GPS receiver that provides a Grandmaster clock source\n 226:\t\t for a PTP enabled network.\n 227:\t\n 228:\t\t More information is available at http://www.timingcard.com/\n 229:\t\n"
} |
| 9/2 | 2026/07/24 18:46 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7913 output: 19 thoughts: 536 Thoughts: **My Fuzzing Strategy: A Deep Dive into the PTP OCP CPLD I2C Driver** Okay, so I'm looking at this driver, and immediately my mind goes to the dependencies: PCI, I2C, MTD, SERIAL_8250, and COMMON_CLK. It's a PCI driver, which is interesting because that means Syzkaller can probably use vPCI to fuzz it. My key focus right now is that this driver registers sysfs attributes - always a great attack surface. Specifically, I see these functions: `i2c_bus_ctrl_show`, `i2c_bus_ctrl_store`, `ptp_ocp_cpld_i2c_write`, and `ptp_ocp_cpld_i2c_read`. The big question is, can I reach `ptp_ocp_cpld_i2c_write`? Bingo! It's a sysfs binary attribute write function, and Syzkaller is perfect for fuzzing sysfs. Now, let's see if `ptp_ocp` is a module or built-in, and it looks like it can be built-in if we enable `PTP_1588_CLOCK_OCP`. So, I'll focus on these four: `ptp_ocp_cpld_i2c_write`, `ptp_ocp_cpld_i2c_read`, `i2c_bus_ctrl_store`, and `i2c_bus_ctrl_show`. I see some other functions, but `tap_i2c_errno_to_byte` is clearly a helper, and `ptp_ocp_i2c_notifier_call` seems to have some modifications. Is this fuzz-worthy? Absolutely! It's adding new sysfs attributes that parse user input, interact with I2C, and, crucially, interact with hardware registers. The `ptp_ocp_cpld_i2c_write` function is especially interesting because it parses a header, crafts I2C messages, allocates memory, and calls `i2c_transfer` - a classic recipe for interesting fuzzing targets. Now, I'm verifying that `PTP_1588_CLOCK_OCP` is the *only* required config, and it looks like that's the main key. But wait, `ptp_ocp_cpld_i2c_write` uses `i2c_get_adapter` and `i2c_transfer`, and I'm always thinking about specific hardware configurations. Are there any ADVA x1 TAP board specific configs? Quick check of `drivers/ptp/ptp_ocp.c` for `adva_x1`. I need to ensure the fuzzing covers all relevant configurations. |
| 10/2 | 2026/07/24 18:46 | tool | grepper |
0mArgs:{
"Expression": "adva_x1"
}Results: {
"Output": "drivers/ptp/ptp_ocp.c=162=struct gpio_reg {\n--\ndrivers/ptp/ptp_ocp.c-165-\tu32\tgpio2;\ndrivers/ptp/ptp_ocp.c:166:\t/* adva_x1: I2C bus ownership register; reserved on other variants */\ndrivers/ptp/ptp_ocp.c-167-\tu32\ti2c_bus_ctrl;\n--\ndrivers/ptp/ptp_ocp.c=360=struct ptp_ocp {\n--\ndrivers/ptp/ptp_ocp.c-419-\tint freq_in_nr;\ndrivers/ptp/ptp_ocp.c:420:\t/* cpld_i2c_xfer sysfs (adva_x1) */\ndrivers/ptp/ptp_ocp.c-421-\tstruct mutex\t\ttap_i2c_lock;\n--\ndrivers/ptp/ptp_ocp.c=458=static const struct ocp_sma_op ocp_adva_sma_op;\ndrivers/ptp/ptp_ocp.c:459:static const struct ocp_sma_op ocp_adva_x1_sma_op;\ndrivers/ptp/ptp_ocp.c-460-\n--\ndrivers/ptp/ptp_ocp.c=915=static struct ocp_resource ocp_adva_resource[] = {\n--\ndrivers/ptp/ptp_ocp.c-1079-\ndrivers/ptp/ptp_ocp.c:1080:static struct ocp_resource ocp_adva_x1_resource[] = {\ndrivers/ptp/ptp_ocp.c-1081-\t{\n--\ndrivers/ptp/ptp_ocp.c-1277-\t\t\t.flash_start = 0x1000000,\ndrivers/ptp/ptp_ocp.c:1278:\t\t\t.sma_op = \u0026ocp_adva_x1_sma_op,\ndrivers/ptp/ptp_ocp.c-1279-\t\t\t.signals_nr = 4,\n--\ndrivers/ptp/ptp_ocp.c=1287=static const struct pci_device_id ptp_ocp_pcidev_id[] = {\n--\ndrivers/ptp/ptp_ocp.c-1291-\t{ PCI_DEVICE_DATA(ADVA, TIMECARD, \u0026ocp_adva_resource) },\ndrivers/ptp/ptp_ocp.c:1292:\t{ PCI_DEVICE_DATA(ADVA, TIMECARD_X1, \u0026ocp_adva_x1_resource) },\ndrivers/ptp/ptp_ocp.c-1293-\t{ }\n--\ndrivers/ptp/ptp_ocp.c=1377=static const struct ocp_selector ptp_ocp_adva_sma_out[] = {\n--\ndrivers/ptp/ptp_ocp.c-1388-\ndrivers/ptp/ptp_ocp.c:1389:static const struct ocp_selector ptp_ocp_adva_x1_sma_in[] = {\ndrivers/ptp/ptp_ocp.c-1390-\t{ .name = \"PPS1\",\t.value = 0x0001, .frequency = 1 },\n--\ndrivers/ptp/ptp_ocp.c-1402-\ndrivers/ptp/ptp_ocp.c:1403:static const struct ocp_selector ptp_ocp_adva_x1_sma_out[] = {\ndrivers/ptp/ptp_ocp.c-1404-\t{ .name = \"10Mhz\",\t.value = 0x0000, .frequency = 10000000},\n--\ndrivers/ptp/ptp_ocp.c=2905=static const struct ocp_sma_op ocp_adva_sma_op = {\n--\ndrivers/ptp/ptp_ocp.c-2912-\ndrivers/ptp/ptp_ocp.c:2913:static const struct ocp_sma_op ocp_adva_x1_sma_op = {\ndrivers/ptp/ptp_ocp.c:2914:\t.tbl\t\t= { ptp_ocp_adva_x1_sma_in, ptp_ocp_adva_x1_sma_out },\ndrivers/ptp/ptp_ocp.c-2915-\t.init\t\t= ptp_ocp_sma_fb_init,\n--\ndrivers/ptp/ptp_ocp.c=4269=static DEVICE_ATTR_RW(i2c_bus_ctrl);\n--\ndrivers/ptp/ptp_ocp.c-4271-/*\ndrivers/ptp/ptp_ocp.c:4272: * cpld_i2c_xfer - sysfs binary I2C passthrough for adva_x1 TAP CPLD.\ndrivers/ptp/ptp_ocp.c-4273- *\n--\ndrivers/ptp/ptp_ocp.c=4464=static struct attribute *adva_timecard_x1_attrs[] = {\n--\ndrivers/ptp/ptp_ocp.c-4483-\ndrivers/ptp/ptp_ocp.c:4484:static const struct bin_attribute *const bin_adva_x1_timecard_attrs[] = {\ndrivers/ptp/ptp_ocp.c-4485-\t\u0026tap_i2c_bin_attr,\n--\ndrivers/ptp/ptp_ocp.c=4489=static const struct attribute_group adva_timecard_x1_group = {\ndrivers/ptp/ptp_ocp.c-4490-\t.attrs = adva_timecard_x1_attrs,\ndrivers/ptp/ptp_ocp.c:4491:\t.bin_attrs = bin_adva_x1_timecard_attrs,\ndrivers/ptp/ptp_ocp.c-4492-};\n"
} |
| 11/2 | 2026/07/24 18:46 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10688 output: 227 thoughts: 741 Thoughts: **Fuzzing the ADVA x1 TAP Board I2C Interface**
Okay, so the `adva_x1` is essentially just another PCI device variant. That means Syzkaller can, and should, fuzz it. The key is setting up the PCI device with the right vendor/device ID. The sysfs attributes are specific to the `adva_x1` variant, so we're only fuzzing the right target. Syzkaller's virtual PCI support should be able to handle this emulation. The required configuration seems straightforward: `PTP_1588_CLOCK_OCP`.
I need to confirm that `PTP_1588_CLOCK_OCP` is *all* we need. Let me double-check the `drivers/ptp/Kconfig` file... Yep, it depends on `PTP_1588_CLOCK`, `HAS_IOMEM`, `PCI`, `I2C`, `MTD`, `SERIAL_8250`, and `COMMON_CLK`, but we can enable those from the base config. Just enabling `PTP_1588_CLOCK_OCP` is enough.
Now, let's identify the specific functions to focus on for fuzzing. It's:
* `ptp_ocp_cpld_i2c_write`
* `ptp_ocp_cpld_i2c_read`
* `i2c_bus_ctrl_store`
* `i2c_bus_ctrl_show`
Is `tap_i2c_errno_to_byte` worth including? It's a small helper, but it's part of this new logic, so let's add it. What about `ptp_ocp_i2c_notifier_call`? That's been modified, but it's an existing function, so not critical for fuzzing. It's part of the base driver.
Quick double-check: `PTP_1588_CLOCK_OCP` is indeed the *only* specific config we need.
Reviewing the patch again confirms the key additions:
* `i2c_bus_ctrl_show`
* `i2c_bus_ctrl_store`
* `tap_i2c_errno_to_byte`
* `ptp_ocp_cpld_i2c_write`
* `ptp_ocp_cpld_i2c_read`
These are all *new* functions that are reachable via sysfs. This makes them ideal fuzzing targets for Syzkaller.
Therefore, here's what I'll do:
* Set `WorthFuzzing: true`
* Set `FocusSymbols:` to:
* `ptp_ocp_cpld_i2c_write`
* `ptp_ocp_cpld_i2c_read`
* `i2c_bus_ctrl_store`
* `i2c_bus_ctrl_show`
* `tap_i2c_errno_to_byte`
* Set `EnableConfigs:` to:
* `PTP_1588_CLOCK_OCP`
The reasoning is that the patch introduces new sysfs attributes (`cpld_i2c_xfer` and `i2c_bus_ctrl`) in the `ptp_ocp` driver specifically for the ADVA x1 TAP board. These allow userspace to initiate I2C transfers and control the I2C bus arbitration register. In particular, the `ptp_ocp_cpld_i2c_write` function handles user input, memory allocation, and I2C transfer initiation; this is complex functional logic and therefore a prime target for fuzzing.
|
| 12/2 | 2026/07/24 18:46 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"PTP_1588_CLOCK_OCP"
],
"FocusSymbols": [
"ptp_ocp_cpld_i2c_write",
"ptp_ocp_cpld_i2c_read",
"i2c_bus_ctrl_store",
"i2c_bus_ctrl_show",
"tap_i2c_errno_to_byte"
],
"Reasoning": "The patch adds new sysfs attributes (`cpld_i2c_xfer` and `i2c_bus_ctrl`) to the `ptp_ocp` driver for the ADVA x1 TAP board. These attributes allow userspace to perform I2C transfers and control the I2C bus arbitration register. The `ptp_ocp_cpld_i2c_write` function parses user input, allocates memory, and initiates I2C transfers, which is functional logic that should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"PTP_1588_CLOCK_OCP"
],
"FocusSymbols": [
"ptp_ocp_cpld_i2c_write",
"ptp_ocp_cpld_i2c_read",
"i2c_bus_ctrl_store",
"i2c_bus_ctrl_show",
"tap_i2c_errno_to_byte"
],
"Reasoning": "The patch adds new sysfs attributes (`cpld_i2c_xfer` and `i2c_bus_ctrl`) to the `ptp_ocp` driver for the ADVA x1 TAP board. These attributes allow userspace to perform I2C transfers and control the I2C bus arbitration register. The `ptp_ocp_cpld_i2c_write` function parses user input, allocates memory, and initiates I2C transfers, which is functional logic that should be fuzzed.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|