Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fbnic: close fw_log race between users and teardown

Fixes a theoretical race on fw_log between the teardown path and fw_log
write functions.

fw_log is written inside fbnic_fw_log_write() and can be reached from
the mailbox handler fbnic_fw_msix_intr(), but fw_log is freed before
IRQ/MBX teardown during cleanup, resulting in a potential data race of
dereferencing a freed/null variable.

Possible Interleaving Scenario:
CPU0: fbnic_fw_msix_intr() // Entry
fbnic_fw_log_write()
if (fbnic_fw_log_ready()) // true
... preempt ...
CPU1: fbnic_remove() // Entry
fbnic_fw_log_free()
vfree(log->data_start);
log->data_start = NULL;
CPU0: continues, walks log->entries or writes to log->data_start

The initialization also has an incorrect order problem, as the fw_log
is currently allocated after MBX setup during initialization.
Fix the problems by adjusting the synchronization order to put
initialization in place before the mailbox is enabled, and not cleared
until after the mailbox has been disabled.

Fixes: ecc53b1b46c89 ("eth: fbnic: Enable firmware logging")
Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
Link: https://patch.msgid.link/20260211191329.530886-1-dg573847474@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Chengfeng Ye and committed by
Jakub Kicinski
ee5492fd 36e83863

+12 -10
-3
drivers/net/ethernet/meta/fbnic/fbnic_fw_log.c
··· 51 51 log->data_start = data; 52 52 log->data_end = data + FBNIC_FW_LOG_SIZE; 53 53 54 - fbnic_fw_log_enable(fbd, true); 55 - 56 54 return 0; 57 55 } 58 56 ··· 61 63 if (!fbnic_fw_log_ready(fbd)) 62 64 return; 63 65 64 - fbnic_fw_log_disable(fbd); 65 66 INIT_LIST_HEAD(&log->entries); 66 67 log->size = 0; 67 68 vfree(log->data_start);
+12 -7
drivers/net/ethernet/meta/fbnic/fbnic_pci.c
··· 311 311 goto free_irqs; 312 312 } 313 313 314 + err = fbnic_fw_log_init(fbd); 315 + if (err) 316 + dev_warn(fbd->dev, 317 + "Unable to initialize firmware log buffer: %d\n", 318 + err); 319 + 314 320 err = fbnic_fw_request_mbx(fbd); 315 321 if (err) { 316 322 dev_err(&pdev->dev, 317 323 "Firmware mailbox initialization failure\n"); 318 - goto free_irqs; 324 + goto free_fw_log; 319 325 } 320 326 321 327 /* Send the request to enable the FW logging to host. Note if this ··· 329 323 * possible the FW is just too old to support the logging and needs 330 324 * to be updated. 331 325 */ 332 - err = fbnic_fw_log_init(fbd); 333 - if (err) 334 - dev_warn(fbd->dev, 335 - "Unable to initialize firmware log buffer: %d\n", 336 - err); 326 + fbnic_fw_log_enable(fbd, true); 337 327 338 328 fbnic_devlink_register(fbd); 339 329 fbnic_devlink_otp_check(fbd, "error detected during probe"); ··· 376 374 * firmware updates for fixes. 377 375 */ 378 376 return 0; 377 + free_fw_log: 378 + fbnic_fw_log_free(fbd); 379 379 free_irqs: 380 380 fbnic_free_irqs(fbd); 381 381 err_destroy_health: ··· 412 408 fbnic_hwmon_unregister(fbd); 413 409 fbnic_dbg_fbd_exit(fbd); 414 410 fbnic_devlink_unregister(fbd); 415 - fbnic_fw_log_free(fbd); 411 + fbnic_fw_log_disable(fbd); 416 412 fbnic_fw_free_mbx(fbd); 413 + fbnic_fw_log_free(fbd); 417 414 fbnic_free_irqs(fbd); 418 415 419 416 fbnic_devlink_health_destroy(fbd);