During device initialization in dvb_usbv2_probe(), the dvb-usb-v2 core allocates the dvb_usb_device structure and its private state (struct mxl111sf_state) via kzalloc(), then invokes dvb_usbv2_init(). Within dvb_usbv2_init(), dvb_usbv2_i2c_init() registers the I2C adapter with i2c_add_adapter(), which immediately exposes the I2C adapter to userspace via the /dev/i2c-X character device. However, state->d was only assigned later during frontend attachment inside dvb_usbv2_adapter_frontend_init() via d->props->frontend_attach(). If userspace performs an I2C transaction before frontend_attach() completes, mxl111sf_i2c_xfer() delegates to mxl111sf_ctrl_msg(), which reads state->d and passes it to dvb_usbv2_generic_write() or dvb_usbv2_generic_rw(). Since state->d is still NULL, dereferencing &d->usb_mutex inside dvb_usbv2_generic_write() triggers a null-pointer dereference crash. Although the selected 2026-10-02 report was captured in compat mode with PTI, the failure is illustrated by the following x64/NOPTI trace: Oops: general protection fault, probably for non-canonical address 0xdffffc0000000018: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x00000000000000c0-0x00000000000000c7] RIP: 0010:__mutex_lock_common kernel/locking/mutex.c:625 [inline] RIP: 0010:__mutex_lock+0x149/0x1550 kernel/locking/mutex.c:821 Call Trace: dvb_usbv2_generic_write+0x26/0x60 drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c:77 mxl111sf_ctrl_msg+0x160/0x2f0 drivers/media/usb/dvb-usb-v2/mxl111sf.c:73 mxl111sf_write_reg+0xa9/0x1b0 drivers/media/usb/dvb-usb-v2/mxl111sf.c:123 mxl111sf_i2c_start drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c:130 [inline] mxl111sf_i2c_sw_xfer_msg drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c:-1 [inline] mxl111sf_i2c_xfer+0x463/0x5060 drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c:813 __i2c_transfer+0x7bf/0x1fe0 drivers/i2c/i2c-core-base.c:-1 i2c_transfer+0x1cb/0x2d0 drivers/i2c/i2c-core-base.c:2350 i2cdev_ioctl_rdwr+0x460/0x740 drivers/i2c/i2c-dev.c:306 i2cdev_ioctl+0x6a5/0x880 drivers/i2c/i2c-dev.c:467 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:597 [inline] __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f Additionally, state->fe_lock was initialized in mxl111sf_init() (called via d->props->init()), which runs after frontend attachment, leaving the mutex uninitialized during frontend registration. Although the selected I2C fault does not demonstrate a frontend lock race, fe_lock should also be initialized before frontend registration. Fix this by setting state->d = dev and initializing state->fe_lock in mxl111sf_probe(), which runs before dvb_usbv2_init() registers the I2C adapter or attaches frontends. Furthermore, remove the redundant mutex_init(&state->fe_lock) from mxl111sf_init() and the redundant assignments of state->d in the frontend attach functions. Fixes: 4c66c9205c07 ("[media] dvb-usb: add ATSC support for the Hauppauge WinTV-Aero-M") Assisted-by: Gemini:gemini-3.8-flash syzbot Reported-by: syzbot+f9f5333782a854509322@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=f9f5333782a854509322 Link: https://syzkaller.appspot.com/ai_job?id=60bc5497-9c9b-4886-b53d-32db7cd4696e To: To: "Mauro Carvalho Chehab" To: "Michael Krufky" To: "Michael Krufky" Cc: --- v2: - Clarified in commit description that the quoted x64/NOPTI trace is distinguished from the 2026-10-02 PTI/compat report - Noted in commit description that fe_lock is initialized before frontend registration, and that the I2C fault does not demonstrate a frontend lock race v1: https://lore.kernel.org/all/b8b6fc2d-1c9a-4046-bba5-c9ef864bfae3@mail.kernel.org/T/ --- diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 6404eb74d..fc4010b6e 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -431,8 +431,6 @@ static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe pr_debug("%s()\n", __func__); - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; state->alt_mode = adap_state->alt_mode; @@ -502,8 +500,6 @@ static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i pr_debug("%s()\n", __func__); - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; state->alt_mode = adap_state->alt_mode; @@ -587,8 +583,6 @@ static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_i pr_debug("%s()\n", __func__); - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; state->alt_mode = adap_state->alt_mode; @@ -674,8 +668,6 @@ static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 pr_debug("%s()\n", __func__); - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1; state->alt_mode = adap_state->alt_mode; @@ -749,8 +741,6 @@ static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id) pr_debug("%s()\n", __func__); - /* save a pointer to the dvb_usb_device in device state */ - state->d = d; adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2; state->alt_mode = adap_state->alt_mode; @@ -935,8 +925,6 @@ static int mxl111sf_init(struct dvb_usb_device *d) if (mxl_fail(ret)) pr_err("failed to get chip info during probe"); - mutex_init(&state->fe_lock); - if (state->chip_rev > MXL111SF_V6) mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1); @@ -1068,7 +1056,9 @@ static int mxl111sf_probe(struct dvb_usb_device *dev) { struct mxl111sf_state *state = d_to_priv(dev); + state->d = dev; mutex_init(&state->msg_lock); + mutex_init(&state->fe_lock); return 0; } base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222 -- This is an AI-generated patch subject to moderation. Reply with '#syz upstream' to Sign-off the patch as a human author and send it to the upstream kernel mailing lists. Reply with '#syz reject' to reject it ('#syz unreject' to undo). See https://goo.gle/syzbot-ai-patches for information about AI-generated patches. You can comment on the patch as usual, syzbot will try to address the comments and send a new version of the patch if necessary. syzbot engineers can be reached at syzkaller@googlegroups.com.