Bug 295764 - ctl/camsim: cfcs_init() leaves CTL port registered on later init failure, causing panic during module load rollback
Summary: ctl/camsim: cfcs_init() leaves CTL port registered on later init failure, cau...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 14.4-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2026-06-01 04:10 UTC by Haoxiang Li
Modified: 2026-06-01 04:10 UTC (History)
0 users

See Also:


Attachments
ctl/camsim: clean up partially initialized cfcs state (2.65 KB, patch)
2026-06-01 04:10 UTC, Haoxiang Li
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Haoxiang Li 2026-06-01 04:10:56 UTC
Created attachment 271389 [details]
ctl/camsim: clean up partially initialized cfcs state

cfcs_init() registers its CTL port before allocating/registering the CAM SIM, If any step after ctl_port_register() fails, cfcs_init() jumps to bailout. The bailout path frees only CAM resources and does not deregister the CTL port. The port remains visible in CTL state even though the camsim frontend did not finish initialization.

This also makes module-load rollback unsafe. When cfcs_init() returns an error, the module loader may call the frontend shutdown path. cfcs_shutdown() currently assumes softc->sim and softc->path are valid and calls ctl_port_offline(), xpt_free_path(), xpt_bus_deregister(), and cam_sim_free() unconditionally.

With fault injection immediately after a successful ctl_port_register(), I reproduced a kernel panic in a FreeBSD 14.4-RELEASE amd64 QEMU guest.

Reproduction setup:
  1. Build ctl.ko with this temporary fault injection immediately after ctl_port_register() succeeds in cfcs_init():

       printf("%s: forcing failure after ctl_port_register() for repro\n", __func__);
       retval = ENOMEM;
       goto bailout;

  2. Boot FreeBSD 14.4-RELEASE amd64 in QEMU.
  3. Load the injected module:

       kldload /tmp/ctlmod/ctl.ko

  Observed result:

    cfcs_init: forcing failure after ctl_port_register() for repro
    camsim frontend init error: 12


    KDB: stack backtrace:
      ctl_port_offline+0x20
      cfcs_shutdown+0x12
      linker_load_module+0xbdf
      kern_kldload+0x165
      sys_kldload+0x59

Thus, If initialization fails after ctl_port_register(), cfcs_init() should deregister the CTL port and release any partially initialized CAM resources. cfcs_shutdown() should also tolerate being called after a partial initialization failure.