[Bug 295764] ctl/camsim: cfcs_init() leaves CTL port registered on later init failure, causing panic during module load rollback

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 01 Jun 2026 04:10:56 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=295764

            Bug ID: 295764
           Summary: ctl/camsim: cfcs_init() leaves CTL port registered on
                    later init failure, causing panic during module load
                    rollback
           Product: Base System
           Version: 14.4-RELEASE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: lihaoxiang@isrc.iscas.ac.cn

Created attachment 271389
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=271389&action=edit
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.

-- 
You are receiving this mail because:
You are the assignee for the bug.