dev_user_map_buf() takes the handler's buffer pages with
get_user_pages(FOLL_WRITE). With SCST_USER_MEM_REUSE_* the buffer stays
cached in the SGV pool and is reused by later commands, so SCST keeps
these page references for a long time.
A page reference does not keep the handler and SCST on the same page
across fork(). After the handler forks, its private pages are shared
copy-on-write, and the handler's next write to a cached buffer moves the
handler to a new copy while SCST keeps using the old page. SCST then
returns stale data to the initiator. For READ CAPACITY it also takes the
stale bytes as the block length and changes the device geometry, for
example:
1 << 30 != 1145132097
scst_user: ...: Changed block shift from 12 into 30 / 30
Any fork() in the handler triggers this, including a crash reporter that
clones a minidump writer without CLONE_VM, system() and popen().
Pin the pages with FOLL_LONGTERM instead. Since Linux 5.9 (commit
70e806e4e645, "mm: Do early cow for pinned pages during fork() for
ptes"), fork() gives the child a copy of a pinned anonymous page, so the
handler and SCST keep sharing the same page. pin_user_pages() itself is
older, but before 5.9 fork() write-protects pinned pages like any other,
so pinning alone does not help there. Release them with
unpin_user_pages(), marking them dirty with SetPageDirty() as before.
unpin_user_pages_dirty_lock() is not usable here: it takes the page
lock, and on_free_cmd() can release an uncached buffer in atomic
context. Use the pin from Linux 5.9; older kernels, including
distribution kernels based on them, keep the existing code.
doc/scst_user_spec.sgml so far required handlers that fork() to mark
their data buffers MADV_DONTFORK. With the pin that is only needed on
kernels older than 5.9, and for private HugeTLB buffers on kernels older
than 5.12: fork() copies pinned HugeTLB pages only since commit
4eae4efa2c29 ("hugetlb: do early cow when page pinned on src mm"), which
5.10.y and 5.11.y do not have. Update that note and the source comment
accordingly. Also document that data
buffers should be anonymous or shared memory: since Linux 6.5 the kernel
refuses a long term writable pin of a MAP_SHARED mapping of a regular
file on a file system with writeback, and a command using such a buffer
then fails with INTERNAL TARGET FAILURE sense. Such a buffer was not
safe with get_user_pages() either, because SCST could write to it while
the file system wrote it back.
Add scst-USER-buffers, which maps a KUnit-owned user buffer with
dev_user_map_buf() and releases it with dev_user_unmap_buf() with
interrupts disabled, checking that the pages are unpinned and marked
dirty only after a write.
Run isolated tooling checks and separate Sparse and Smatch Make targets
on pushes to master and manual dispatch. Use the pinned kernel with
KUnit enabled and preserve full logs, policy and tool provenance.
During the source-fix rollout, completed source findings are advisory.
Tool, build, parser and coverage failures remain blocking, including an
empty scan or missing KUnit inputs. Local Make targets stay strict.
Validate the current run's report together with Make's exit status,
since Make maps both findings and incomplete analysis to status 2.
Prepare the runner and container for Coccinelle and Cppcheck as well,
but leave their matrix entries commented out. Cover all four report
formats and GNU Make exit mapping with isolated tooling fixtures.
Expose make cppcheck using freshly captured kernel CHECK commands and
real userspace compiler invocations. Keep their include paths and
definitions unchanged and analyze kernel and userspace contexts
separately.
Use the shared source scope without additional input exclusions, project
models or diagnostic suppressions. Relevant diffs trigger full
configured analysis; KUnit coverage follows the actual build
configuration.
Retain build logs, compilation databases, native XML and checker
coverage. Separate source findings from parser failures, missing inputs
and incomplete builds, with isolated report and capture fixtures.
Expose make coccicheck using report rules from the selected kernel and
the shared source policy, including userspace and KUnit sources. Diff
mode selects whole changed sources and headers.
Preserve full native output and record rule initialization, per-input
handling and finalization. Treat parser errors and missing coverage as
incomplete analysis even if spatch returns zero; report source findings
separately.
Add isolated log and policy fixtures. Do not introduce project macro
models, diagnostic exceptions or CI execution.
Build standalone Sparse and Smatch from recorded revisions, applying the
reviewed SCST Smatch frontend correction. Install matching native Smatch
data without replacing standalone Sparse or adding project models.
Reuse the existing checksum-pinned kernel headers. Record source
commits, patch and binary hashes, and installed model contents for CI
evidence. Fail preparation instead of silently falling back to different
tools; no SCST modules are built or loaded while preparing this image.
Use the dedicated native analyzer targets instead of regression wrappers
that return success after tool failures and summarize filtered output.
Remove their suffix switches and the analyzer-only IBM VIO option.
Update the regression caller and kernel-option parser together; the
maintained kernel list and compilation matrix are unchanged. Keep legacy
Checkpatch until its own integration series.
Run the native checkers through the ordered SCST module build with C=2.
Preserve Kbuild flags, full raw output and every attempted CHECK record.
Keep full, diff and explicit input selection on the shared scope; diff
selection triggers the complete configured module analysis.
Read exact diagnostic exceptions from policy/sparse.json and
smatch.json: two reviewed Smatch IRQ reports and the external FC
flexible-array warning. Keep the existing SCST matching boundaries and
reasons. Smatch uses its matching installed kernel data without
engine-specific additions.
Reject build, checker, frontend and truncation failures even when Kbuild
returns success. Retain per-invocation records and a machine-readable
run summary, and detect printed CHECK steps without a record. Require
selected C inputs to occur in the build. Keep findings distinct from
incompleteness.
Check native compatibility before compilation, and forward external
kernel capability probes to the real checker instead of skipping them as
inputs outside SCST. Include the pinned Smatch typeof frontend
correction and isolated fixtures for failure propagation and exact
exception boundaries.
Add show, files and validate commands to analyzer_policy.py and expose
policy inspection through make analyzer-policy. Support text and JSON
reports without installing or invoking an analyzer or preparing a build.
Show the configured roots, input exclusions and their reasons. The file
inventory uses the shared selector and reports eligible tracked inputs,
not completed analysis or build coverage. Configuration and Git failures
return an error instead of a successful empty report.
Expose only the common input policy at this stage. Individual analyzer
policies belong with their drivers. Keep the existing checkpatch and
kernel regression filtering separate and document that boundary.
Add isolated CLI fixtures for policy reporting, repository-relative input
inventory and visible failures. Document the inspection entry points.
Move the source roots, file types and input exclusions from lint_scope.py
into policy/common.json. Keep the existing scope, including KUnit sources,
the newer QLogic target and the exclusions for the legacy QLogic tree,
upstream QLogic sources, compiler probes and generated module metadata.
Adapt engine's reviewed-data and strict-loader approach to SCST. Require
reasons for input exclusions and reject malformed, missing or ambiguous
policy before selecting files. Do not import engine's exclusions or add
environment-based filtering or diagnostic suppression.
Use this policy for full, diff and explicit-file selection. Preserve both
lexical and resolved path checks, single-commit diff bases and index-based
selection. Treat policy paths literally in Git pathspecs as well as Python.
Add isolated fixtures for schema failures and policy-driven selection.
Extract the per-worktree build lock ahead of the Sparse/Smatch and
Cppcheck drivers. Keep one advisory lock file for analyzer builds that
share generated state; release the descriptor on success or exception
without unlinking the file.
Document that callers must hold the lock around build-state changes and
log reset, and that ordinary builds are not covered by this advisory lock.
Add isolated fixtures checking cross-process contention, lock reuse and
release after an exception. Kbuild collection and analyzer-specific build
targets remain with their respective integration series.
Provide common process, progress and report helpers for the upcoming
analyzer drivers. Preserve raw output bytes and command failure statuses,
keep progress separate from captured diagnostics, and terminate the owned
process group when an invocation is interrupted.
Forward valid inherited Make jobserver pipes without taking their tokens.
Document named-log truncation explicitly: a later run replaces that named
report unless the caller requests preservation.
Import the process and terminal fixtures and add raw-log coverage. No
analyzer-specific filtering or diagnostic exclusions are introduced.
Passing the base directly to git diff allows an option such as --quiet to
be interpreted as a flag. On a clean worktree it can succeed without
selecting any sources, instead of rejecting the invalid revision.
Resolve the base with rev-parse --verify --end-of-options and require a
commit before building the diff command. Reuse the resulting object ID so
options, ranges, tree objects and unknown revisions cannot turn an invalid
request into an empty selection.
Add a fixture covering rejected bases on a clean tree and a valid tag
before and after a source change. Expose the resolver for future patch
consumers as well.
Give the upcoming analyzer drivers one source-selection policy for full,
working-tree diff and explicit-file checks. Include product C sources and
headers, including KUnit, and keep both lexical and resolved paths within
the allowed directories.
Select only the newer QLogic SCST target directory. Exclude the legacy
QLogic tree, the upstream part of the newer driver, the two conftest trees
and generated .mod.c files. Document these input exclusions separately
from diagnostic filtering, which this helper does not perform.
Add temporary-repository fixtures and a make lint-test entry point. Keep
the existing checkpatch and kernel regression consumers unchanged until
their replacement drivers are introduced.
The Linux 3.10 backport selected uint unconditionally for ql2xmaxlun,
limiting the module parameter to 32 bits even on current kernels.
Select uint only when param_check_ullong is absent from the kernel's
module parameter API. Otherwise retain the upstream uint64_t/ullong type.
Use the same feature check for the extern declaration so all driver
translation units agree, including vendor kernels with this API backported.
The default value and existing 16-bit limit for older HBAs are unchanged.
The QLogic EDIF teardown now uses timer_shutdown(). Use the native helper
on Linux 6.2+, stable 6.1.158+ and 5.15.200+, RHEL 8.9+/9.3+, and the
Ubuntu kernels that backported it. Keep this compatibility change separate
from the import of upstream 292a089d78d3.
Also account for the timer_delete_sync() backport in Ubuntu 5.15.0-93.
Its headers report Linux 5.15.136, below the upstream stable 5.15.154
boundary, so the existing fallback redeclares a native kernel function.
The earlier Ubuntu fix covered timer_delete() but omitted its sync peer.
Limit the ABI check to the generic/HWE numbering range; flavour ABIs use
independent sequences.
Ubuntu 5.4.0-206 reports Linux 5.4.286 and is already covered by the
existing 5.4.274 stable boundary for timer_delete_sync().
On kernels without shutdown support, retain the previous timer_delete()
behavior. This fallback does not prevent rearming; that guarantee requires
support in the kernel timer implementation. Callers on these kernels still
have to exclude concurrent rearming themselves.
Fixes: d21b6f1457 ("scst: Port to Linux kernel v6.15")
Due to several bugs caused by timers being re-armed after they are
shutdown and just before they are freed, a new state of timers was added
called "shutdown". After a timer is set to this state, then it can no
longer be re-armed.
The following script was run to find all the trivial locations where
del_timer() or del_timer_sync() is called in the same function that the
object holding the timer is freed. It also ignores any locations where
the timer->function is modified between the del_timer*() and the free(),
as that is not considered a "trivial" case.
This was created by using a coccinelle script and the following
commands:
$ cat timer.cocci
@@
expression ptr, slab;
identifier timer, rfield;
@@
(
- del_timer(&ptr->timer);
+ timer_shutdown(&ptr->timer);
|
- del_timer_sync(&ptr->timer);
+ timer_shutdown_sync(&ptr->timer);
)
... when strict
when != ptr->timer
(
kfree_rcu(ptr, rfield);
|
kmem_cache_free(slab, ptr);
|
kfree(ptr);
)
$ spatch timer.cocci . > /tmp/t.patch
$ patch -p1 < /tmp/t.patch
Link: https://lore.kernel.org/lkml/20221123201306.823305113@linutronix.de/
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: Pavel Machek <pavel@ucw.cz> [ LED ]
Acked-by: Kalle Valo <kvalo@kernel.org> [ wireless ]
Acked-by: Paolo Abeni <pabeni@redhat.com> [ networking ]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[ commit 292a089d78d3e2f7944e60bb897c977785a321e3 upstream ]
The imported QLA29xx speed reporting uses FC_PORTSPEED_128GBIT. Supply
its upstream value before v4.16, following the existing 64 Gbit
definition and retaining vendor definitions when present. The newer
QLogic driver is the only current consumer; the legacy driver and other
transports are unaffected.
Use the existing BSG_JOB_TYPE compatibility selection for the five new
flash and MPI helpers. Older supported kernels use fc_bsg_job; vendor
kernels with the newer API already select bsg_job. This adapts upstream
2efa08b894c6 and 514664aa303d without changing their imports.
The imported 29xx CRC builder calls the protection SG walker
unconditionally, but SCST compiles that walker only with QLA_ENABLE_PI.
Match the existing 24xx caller so PI-disabled builds do not retain an
undefined symbol. Keep this SCST adaptation separate from upstream
b6781d71a414.
The module parameter is ql2xfc2target, but its MODULE_PARM_DESC() names
qla2xfc2target, so modinfo describes a parameter that does not exist and
shows no description for the real one.
Use the parameter name in the description.
Fixes: 877b03795fcf ("scsi: qla2xxx: Add option to disable FC2 Target support")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Link: https://patch.msgid.link/20260906171009.2560-1-kmehltretter@gmail.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 779f202a92ef10a426efc07d0f4267918cb07ca3 upstream ]
This loop timeout with "retries" set to -1, not 0. Fix the test for
failure.
Fixes: 7ec0effd30bb ("[SCSI] qla2xxx: Add support for ISP8044.")
Signed-off-by: Dan Carpenter <error27@gmail.com>
Link: https://patch.msgid.link/an1twcxTYSFkkUTA@stanley.mountain
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 11e48f5201fd86ffa038809dd9c41144d43ee2e4 upstream ]
Negative -EIO was intended instead of positive EIO. The caller, doesn't
care so this doesn't affect runtime. It's just a cleanup.
Signed-off-by: Dan Carpenter <error27@gmail.com>
Link: https://patch.msgid.link/an1taxANE_4_vzJT@stanley.mountain
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit ff9365a4c9991cca68fd48c7729808f2fdae2036 upstream ]
After commit c3930ec119cb ("scsi: qla2xxx: Add FC operational firmware
load for 29xx"), there is a warning due to an incorrect format specifier
for a 'size_t' variable when building for 32-bit platforms, for which
'size_t' is 'unsigned int':
drivers/scsi/qla2xxx/qla_init.c: In function 'qla29xx_process_rd_image':
drivers/scsi/qla2xxx/qla_init.c:9272:74: error: format '%lx' expects argument of type 'long unsigned int', but argument 6 has type 'size_t' {aka 'unsigned int'} [-Werror=format=]
9272 | "TIM section too large (0x%x bytes, ring 0x%lx bytes).\n",
| ~~^
| |
| long unsigned int
| %x
9273 | section_size,
9274 | req->length * qla_req_entry_size(ha));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| size_t {aka unsigned int}
cc1: all warnings being treated as errors
Use '%zx', the proper 'size_t' format specifier, to clear up the
warning.
Fixes: c3930ec119cb ("scsi: qla2xxx: Add FC operational firmware load for 29xx")
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20260811-scsi-qla2xxxx-qla_init-wformat-v1-1-50760021914f@kernel.org
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 431e735e9bb6b7fd8e2ea9d83f0627bb5c5687ee upstream ]
struct qla_i2c_access carries a 16-bit length field alongside a fixed
64-byte buffer:
struct qla_i2c_access {
uint16_t device, offset, option, length;
uint8_t buffer[0x40];
} __packed;
qla2x00_write_i2c() and qla2x00_read_i2c() use the user-supplied
i2c->length without any bounds check. i2c is overlaid on a 256-byte
on-stack buffer and sfp is a 256-byte DMA-pool buffer, so a length up to
65535 overruns both:
- write: memcpy(sfp, i2c->buffer, i2c->length) over-reads the stack and
over-writes the sfp heap buffer, and qla2x00_write_sfp() then DMAs
i2c->length bytes out of the 256-byte buffer.
- read: qla2x00_read_sfp() DMAs i2c->length bytes into the 256-byte sfp,
then memcpy(i2c->buffer, sfp, i2c->length) overflows the 64-byte
buffer inside the on-stack array.
A caller holding CAP_SYS_RAWIO can use this to corrupt the heap and the
kernel stack. Reject requests whose length exceeds the buffer before any
copy or DMA transfer in both handlers.
Fixes: 9ebb5d9c69f1 ("[SCSI] qla2xxx: Add I2C BSG interface.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-33-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 0918ee2c0eeb4d7f45b82b3dc11e65c2d9b7ad59 upstream ]
The FRU and I2C bsg handlers stage their transfer in a DMA_POOL_SIZE
(256-byte) bounce buffer obtained from dma_pool_alloc(), which does not
zero the allocation. They initialize only a few leading bytes before
handing the buffer to qla2x00_write_sfp().
qla2x00_write_sfp() can override the transfer length with a user-supplied
value:
if (len == 1)
opt |= BIT_0;
if (opt & BIT_0)
len = *sfp;
*sfp is the first byte of the (user-controlled) payload, so len can grow
up to 255. The device then DMA-reads len bytes from the 256-byte pool
buffer. Since only a small prefix was written
(e.g. MAX_FRU_SIZE == 36 bytes for a FRU version, one byte for a FRU
status register), the hardware reads past the initialized region and
writes up to ~219 bytes of stale DMA-pool heap memory to the device
flash.
Allocate the buffer with dma_pool_zalloc() in all five FRU/I2C handlers
so any bytes beyond the initialized data are zero rather than stale heap
contents.
Fixes: 697a4bc69159 ("[SCSI] qla2xxx: Provide method for updating I2C attached VPD.")
Fixes: 9ebb5d9c69f1 ("[SCSI] qla2xxx: Add I2C BSG interface.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-32-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit b47d4a1547d9ef21b2e9d1a739fe2204d4be05dc upstream ]
The FC BSG transport allocates job->request via memdup_user() using the
exact user-supplied request_len. For FC_BSG_HST_VENDOR,
fc_bsg_host_dispatch() only guarantees request_len covers msgcode and
vendor_id; it does not account for the vendor_cmd[] flexible array.
qla2xxx then reads the command selector vendor_cmd[0] and, in several
sub-handlers, vendor_cmd[1]/[2] or structures overlaid on the vendor
command area without verifying request_len. A caller holding
CAP_SYS_RAWIO can submit a short request whose vendor_id matches the
host, triggering out-of-bounds heap reads (KASAN-detectable, and able to
mis-select a command or panic).
Add a central guard in qla2x00_process_vendor_specific() so the selector
is always in bounds, restrict the early vendor_cmd[0] read in
qla24xx_bsg_request() to sufficiently long vendor messages, and add
request_len checks to the sub-handlers that read further:
qla24xx_proc_fcp_prio_cfg_cmd(), qla2x00_process_loopback(),
qla84xx_reset(), qla84xx_updatefw(), qla2x00_read_optrom(),
qla2x00_update_optrom(), qlafx00_mgmt_cmd() and
qla28xx_validate_flash_image().
Fixes: 01e0e15c8b3b ("scsi: don't use fc_bsg_job::request and fc_bsg_job::reply directly")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-31-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 4cf38dd9465736141263ebb63375868311a0ec81 upstream ]
Several bsg handlers stage their request/reply in an uninitialized 256-byte
on-stack buffer (uint8_t bsg[DMA_POOL_SIZE]) and fill it via
sg_copy_to_buffer(), which only copies as many bytes as the user-supplied
request payload. When the request is shorter than the structure, the
remainder of the buffer is left holding stale stack data.
qla2x00_read_fru_status() and qla2x00_read_i2c() then copy the full
structure back to the reply payload with sg_copy_from_buffer(), leaking the
uninitialized stack bytes to user space. The write/update paths do not copy
the buffer back, but can feed uninitialized fields to the device.
Zero the stack buffer at declaration in all five handlers, mirroring the
heap kzalloc() approach, so short requests can no longer expose stale
memory.
Fixes: 697a4bc69159 ("[SCSI] qla2xxx: Provide method for updating I2C attached VPD.")
Fixes: 9ebb5d9c69f1 ("[SCSI] qla2xxx: Add I2C BSG interface.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-30-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit b93d3bb3afe1b44489927de1eb4e66e8536a5935 upstream ]
qla26xx_dport_diagnostics() streaming-maps the caller's result buffer with
dma_map_single(). The bsg path passes &dd->buf from the __packed struct
qla_dport_diag, where buf lands at a 2-byte offset and shares cachelines
with the surrounding options/unused fields. Mapping such a misaligned
sub-buffer violates the DMA API requirement that streaming buffers be
cacheline aligned and not share a cacheline with other data, and can
corrupt data on non-DMA-coherent architectures.
Allocate a dedicated DMA-coherent buffer inside qla26xx_dport_diagnostics()
for the mailbox command and copy the result back into the caller's buffer.
This removes the streaming map of the misaligned sub-buffer entirely; the
caller's buffer is now only a plain CPU buffer, so its packing no longer
matters.
Fixes: ec89146215d1 ("qla2xxx: Add bsg interface to support D_Port Diagnostics.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-29-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 7c4f3f50d83af4545efaa99b3d0d46fb8d52031e upstream ]
The fcport->unsol_ctx_head list is modified from several contexts without
a common lock. Entries are added in qla2xxx_process_purls_iocb() from the
response queue ISR (under the qpair qp_lock), while they are removed from
qla2xxx_process_purls_pkt() (DPC/purex worker), qla_nvme_xmt_ls_rsp()
(NVMe-FC transport callback) and qla_nvme_release_lsrsp_cmd_kref() (SRB
completion). The qpair qp_lock cannot serialize this per-fcport list since
multiqueue adapters add entries through different qpairs, so a concurrent
add and delete (or two concurrent deletes) can corrupt the list pointers.
Introduce a dedicated per-fcport spinlock, unsol_ctx_lock, initialized in
qla2x00_alloc_fcport(), and take it around every list_add_tail()/list_del()
on unsol_ctx_head. The add nests under the existing qp_lock; no delete path
takes qp_lock, so the lock order is consistent and deadlock free.
Fixes: 875386b98857 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-28-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 76da0c43c63eb0496649e372ac64466364d0fe7d upstream ]
qla_nvme_xmt_ls_rsp() obtains uctx, which was linked into
fcport->unsol_ctx_head by qla2xxx_process_purls_iocb() and is still linked
when the NVMe transport calls back to transmit the LS response. On the
error (out:) path the function frees uctx with kfree() but never removes
it from the list. This leaves a freed node in fcport->unsol_ctx_head: the
next list_add_tail() for that fcport writes through the freed node, and a
subsequent list_del() can corrupt the list or panic.
Unlink uctx with list_del() before kfree() on the error path, matching the
other free sites in qla_nvme_release_lsrsp_cmd_kref() and
qla2xxx_process_purls_pkt(). qla2x00_rel_sp() in the failure path only
returns the SRB to its pool and does not invoke sp->put_fn, so the out:
path is the sole free and uctx is always still linked there.
Fixes: 875386b98857 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-27-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit e46160a5d4fa59bf4d5f3412b6b5cb79edb967dd upstream ]
qla_nvme_xmt_ls_rsp() bails out to the out: label when firmware is not
started (!ha->flags.fw_started), but the out: path unconditionally calls
qla_nvme_ls_reject_iocb(), which ends in qla2x00_start_iocbs() and an
unconditional doorbell write to the request queue in-pointer register.
This rings the firmware doorbell and queues an IOCB that stopped or
resetting firmware cannot consume, and touches MMIO during the reset/EEH
window where fw_started is also clear.
Only emit the LS reject IOCB (and ring the doorbell) when fw_started is
set; otherwise just clean up and return. The post-allocation failure
cases (SRB alloc / qla2x00_start_sp() failure) run with firmware started
and still send the reject. Apply the same guard to the reject emission
in qla2xxx_process_purls_pkt().
Fixes: 875386b98857 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-26-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit f7e46ebffc5781aab3f1f5a5d4350addbb5833f4 upstream ]
qla_nvme_ls_abort() and qla_nvme_fcp_abort() take a command reference with
kref_get_unless_zero() and then call schedule_work() on priv->abort_work,
ignoring its return value. qla_nvme_abort_work() runs once and drops
exactly one reference via kref_put(&sp->cmd_kref, sp->put_fn).
Since the per-abort INIT_WORK() was moved to submission time,
schedule_work() now returns false when the work is already pending, for
example on a concurrent transport teardown and timeout-driven abort of
the same command. In that case the reference taken for the second abort
is never released because the work still executes only once, leaking a
reference. The command is then never returned to the NVMe-FC transport,
which can hang the port.
Drop the reference when schedule_work() returns false, so each
kref_get_unless_zero() is balanced regardless of whether the work was
newly queued. The held reference keeps priv->sp valid for the put.
Fixes: 7e85f6dbc856 ("scsi: qla2xxx: Initialize NVMe abort_work once at submission")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-25-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 06b5b2a5d499323f1c3256ead35798e8e3d15e60 upstream ]
qla24xx_report_id_acquisition() format-1 handling drops vport_slock after
taking the vport reference and then calls qla_update_host_map() without
the lock. That reaches qla_update_vp_map(), which mutates the ha->host_map
btree via btree_insert32()/btree_update32()/btree_remove32() and is
documented to require vport_slock to be held by the caller. Running it
unlocked can race concurrent host_map updates and corrupt the btree.
The format-2 path in the same function already wraps its host_map update
(SET_AL_PA) in vport_slock; the format-1 path is the lone outlier.
Hold vport_slock across the format-1 qla_update_host_map() call to honor
the documented locking contract. The vref_count taken in the loop keeps
the vport valid, so this only adds the missing host_map serialization.
Fixes: 430eef03a763 ("scsi: qla2xxx: Relocate/rename vp map")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-24-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 7944039ba9cb5c3a935d17c91004e3b8649ff58e upstream ]
qla24xx_report_id_acquisition() format-1 handling takes the vport
reference under vport_slock but drops it outside the lock, after setting
vp->vp_flags and vp->dpc_flags:
set_bit(VP_IDX_ACQUIRED, &vp->vp_flags);
set_bit(REGISTER_FC4_NEEDED, &vp->dpc_flags);
set_bit(REGISTER_FDMI_NEEDED, &vp->dpc_flags);
atomic_dec(&vp->vref_count);
Neither set_bit() nor atomic_dec() imply a memory barrier, so on a weakly
ordered architecture the decrement can become visible before the flag
stores. qla24xx_deallocate_vp_id() polls vref_count under vport_slock and
unlinks the vport once it reads zero, after which qla24xx_vport_delete()
frees it via scsi_host_put(). The poller could therefore observe
vref_count == 0 early and tear the vport down while the pending vp_flags/
dpc_flags stores land on freed memory.
Drop the reference under vport_slock, as is done for the matching
increment and by every other vref_count user. The unlock release pairs
with the deallocate poller's lock acquire so the flag stores are ordered
before vref_count == 0 can be observed.
Fixes: 793cedee296f ("scsi: qla2xxx: Hold vport reference in qla24xx_report_id_acquisition()")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-23-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 1154b16439ffc562f9461494c4508c63446eb684 upstream ]
qla24xx_report_id_acquisition() format-1 handling walks ha->vp_list under
vport_slock, takes a vref_count on the matching vport and calls
qla_update_host_map() to register its port id.
A vport teardown via qla24xx_vport_delete() sets VPORT_DELETE, then
qla24xx_disable_vp() removes the vport from the host_map btree and zeroes
vha->d_id (RESET_AL_PA). The vport is only unlinked from vp_list later,
in qla24xx_deallocate_vp_id(), which clears vp_map[idx] (RESET_VP_IDX)
but does not touch host_map. In the window in between, report ID
acquisition can still find the vport on vp_list and call
qla_update_host_map(); with d_id already zeroed it takes the
btree_insert32() path and re-inserts the dying vport into host_map.
Nothing cleans that entry afterwards, so once scsi_host_put() frees the
vha a later host_map lookup dereferences freed memory.
Skip a vport that has VPORT_DELETE set before taking the reference, so it
is neither re-registered nor scheduled for DPC re-registration. This
mirrors the existing guard in qla2x00_alert_all_vps().
Fixes: 41dc529a4602 ("qla2xxx: Improve RSCN handling in driver")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-22-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 23582731afa35031c94fadb71a4f3b4afd094649 upstream ]
qla2x00_async_iocb_timeout() tries to abort a timed-out async IOCB. When
qla24xx_async_abort_cmd() fails, both the SRB_LOGIN_CMD path and the
SRB_CTRL_VP/default path scan outstanding_cmds[] for the SRB and then
call sp->done(sp, QLA_FUNCTION_TIMEOUT) unconditionally, without checking
whether the SRB was actually found and removed.
If the response ISR completes the same handle first, it removes the SRB
under qp_lock_ptr and runs sp->done() -> complete(sp->comp). The
submitter qla24xx_control_vp() wakes from wait_for_completion(), clears
sp->comp, drops its reference and returns, reclaiming the on-stack
completion. The timer reference keeps the SRB alive across the timeout
handler, but not the submitter's stack. The timeout then issues a second
sp->done() -> qla_ctrlvp_sp_done(), which evaluates "if (sp->comp)
complete(sp->comp)"; with the pointer loaded before the submitter's NULL
store, complete() writes into the freed stack frame, a use-after-free.
Track whether this path removed the SRB from outstanding_cmds and only
call sp->done() when it did, so the command is completed exactly once by
whichever path owns it. This mirrors the sp_found guard already used in
qla24xx_abort_iocb_timeout().
Fixes: f6145e86d21f ("scsi: qla2xxx: Fix race between switch cmd completion and timeout")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-21-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit bb45bc4bd53c95a7bf6f782577b5ede94c0f8aa8 upstream ]
ha->max_npiv_vports is taken from firmware (mcp->mb[11]) and only
constrained so that (max_npiv_vports + 1) is a multiple of
MIN_MULTI_ID_FABRIC, which permits values of 63, 127, 191 and 255.
NPIV vports are then allocated up to that count.
VP enable uses the VP_CONFIG IOCB, which addresses a vport through a
plain vp_index byte, so a vp_index beyond 128 is enabled without issue.
VP disable, however, uses the VP_CTRL IOCB, which selects target vports
through the fixed 128-bit vp_idx_map bitmap. qla24xx_control_vp()
rejects a vp_index past that bitmap and the IOCB builder cannot set a bit
beyond 127, yet qla24xx_vport_delete() frees the local state regardless.
A vport with vp_index > 128 can therefore be created and enabled but
never disabled, leaving it permanently active in firmware: a resource
leak.
Cap ha->max_npiv_vports at init to the vp_idx_map capacity so such
vports are never created. This collapses 191/255 to 127 (still
modulo-valid) and leaves the real-world 63/127 cases unaffected.
Fixes: 4d0ea24769c8 ("[SCSI] qla2xxx: Retrieve max-NPIV support capabilities from FW.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-20-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 2ac6a829843cf3df522d19e091276109b94c4c7a upstream ]
qla2x00_status_entry() filters out non-TYPE_SRB entries and the
SRB_NVME_CMD, SRB_BIDI_CMD and SRB_TM_CMD types, then falls through to a
SCSI fast path that assumes the command is an SRB_SCSI_CMD. The first
thing on that path, qla_chk_edif_rx_sa_delete_pending(), and the
subsequent handling both evaluate GET_CMD_SP(sp), i.e. sp->u.scmd.cmd.
The srb u union overlays the SCSI command pointer with other command
layouts (bsg_job, iocb_cmd). If firmware delivers an unexpected
STATUS_TYPE IOCB for a non-SCSI handle, sp->u.scmd.cmd can read as a
non-NULL garbage pointer, bypassing the NULL checks in
qla_chk_edif_rx_sa_delete_pending() and at the cp == NULL test, and
leading to a wild pointer dereference.
Reject any SRB whose type is not SRB_SCSI_CMD before entering the fast
path. The outstanding_cmds slot is left untouched so a genuinely
non-SCSI command still completes through its proper handler.
Fixes: dd30706e73b7 ("scsi: qla2xxx: edif: Add key update")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-19-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 0f41d07d72f2245208c45374ca8d0a1846cad667 upstream ]
qla2xxx_delete_qpair() deletes the request queue before the response
queue. qla25xx_delete_req_que() frees the request queue memory
(kfree(req) in qla25xx_free_req_que()), but the response-queue MSI-X is
only released later, in qla25xx_free_rsp_que(). In that window the
response interrupt can still fire, qla2xxx_msix_rsp_q() queues
qpair->q_work, and qla_do_work() -> qla24xx_process_response_queue()
dereferences the now-freed rsp->req (LOGINOUT/CT/ELS entries and the
status path), a use-after-free.
The cancel_work_sync() added for the qpair teardown lives in the
response free path, which runs after the request queue is already freed,
so it does not protect rsp->req.
Release the response-queue interrupt and flush qpair->q_work before
deleting the request queue, so no late completion can reach the freed
request queue. Clearing have_irq makes the subsequent
qla25xx_free_rsp_que() skip its free_irq(), and the firmware
queue-delete order (request then response) is preserved; the
request-delete mailbox completes on the default vector and is unaffected
by dropping the qpair response interrupt early.
Fixes: d74595278f4a ("scsi: qla2xxx: Add multiple queue pair functionality.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-18-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 505753ec2594c6af09a601f0dd60be7d840c1d2d upstream ]
qla2x00_error_entry() reads ha->req_q_map[que] twice: once for the NULL
check and again when assigning it to req. The map slot is cleared by
qla25xx_free_req_que() (ha->req_q_map[que_id] = NULL under mq_lock)
during queue teardown, while the response-queue interrupt that drives
qla2x00_error_entry() is still registered (the IRQ is released later in
qla25xx_free_rsp_que()). If the slot is set to NULL between the two
reads, req becomes NULL and is dereferenced.
Read the slot once into req and NULL-check the local before use. mq_lock
is a mutex and cannot be taken from interrupt context, so the single
read plus local check is the appropriate fix for the reported NULL
dereference.
Fixes: a6fe35c052c4 ("[SCSI] qla2xxx: Avoid invalid request queue dereference for bad response packets.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-17-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit deb8abde83a799d2501f3977f6d6051000253f5e upstream ]
In qla2x00_status_entry(), the FWI2 status path advances sense_data and
shrinks par_sense_len by rsp_info_len:
if (IS_FWI2_CAPABLE(ha)) {
sense_data += rsp_info_len;
par_sense_len -= rsp_info_len;
}
rsp_info_len is a 32-bit value taken directly from the target's FCP
response (sf.rsp_data_len), while par_sense_len is the IOCB data area
size (28 bytes for 24xx, 60 bytes for 29xx). A hostile or buggy target
reporting an rsp_info_len larger than par_sense_len makes the unsigned
subtraction underflow to a huge value and advances sense_data out of
bounds.
The underflowed par_sense_len then defeats the cap in
qla2x00_handle_sense():
if (sense_len > par_sense_len)
sense_len = par_sense_len;
memcpy(cp->sense_buffer, sense_data, sense_len);
so the memcpy reads up to SCSI_SENSE_BUFFERSIZE bytes from the
out-of-bounds sense_data pointer, leaking adjacent response-ring/heap
memory into the command's sense buffer.
Clamp rsp_info_len to par_sense_len before the subtraction so
par_sense_len can never underflow and sense_data stays within the IOCB
data area. The fix sits before the comp_status switch, covering both
qla2x00_handle_sense() call sites.
Fixes: 5544213be7b4 ("[SCSI] qla2xxx: Correct extended sense-data handling.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-16-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit ca6d880d6c70cb7946e7b3e05d7285f271b6d99e upstream ]
qla27xx_copy_multiple_pkt() and qla27xx_copy_fpin_pkt() poll
rsp_q->ring_ptr->signature for RESPONSE_PROCESSED (0xDEADDEAD) to decide
whether the next continuation IOCB has arrived, spinning on cpu_relax()
without advancing the ring or decrementing the entry count while it has
not. response_t::signature lives at byte offset 60, but a continuation
IOCB (sts_cont_entry_t / struct sts_cont_entry_ext) carries raw FC frame
payload at that offset (data[56..59]). A received frame whose payload
bytes happen to equal 0xDEADDEAD is therefore misread as "not yet
arrived", and the loop spins forever in interrupt/DPC context, causing a
CPU soft lockup.
The poll is also unnecessary: callers of qla27xx_copy_multiple_pkt()
(PT_LS4_UNSOL and the NVMe purls path) already gate on
qla_chk_cont_iocb_avail(), which guarantees all entry_count IOCBs are
present before copying begins. The sibling helper
__qla_copy_purex_to_buffer() already drops the signature poll and relies
on the entry_type == STATUS_CONT_TYPE guard instead.
Remove the signature busy-wait from both helpers, keeping the entry_type
guard, and gate the FPIN path with qla_chk_cont_iocb_avail() so it defers
and re-processes on the next interrupt once all continuation IOCBs have
arrived, mirroring the ELS_AUTH_ELS and PT_LS4_UNSOL arms. With this the
signature field is never read on a continuation IOCB, eliminating the
payload-aliasing lockup.
Fixes: 9f2475fe7406 ("scsi: qla2xxx: SAN congestion management implementation")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-15-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit d7e3fa7d06bf7fcaac186d3c4d635caac166d36c upstream ]
qla24xx_process_response_queue() advances ring_ptr past the head IOCB
before dispatching, so by the time __qla_consume_iocb() runs, ring_ptr
already points at the first continuation IOCB. The function however
looped purex->entry_count times starting at ring_ptr. As entry_count
includes the head, this consumed one entry too many: it stamped
RESPONSE_PROCESSED on the next, unrelated IOCB and advanced the ring
past it, silently dropping a legitimate firmware response. The head
IOCB's signature was also never marked.
Mark the head processed and account for it, then consume only the
entry_count - 1 continuation IOCBs, matching __qla_copy_purex_to_buffer().
Fixes: fac2807946c1 ("scsi: qla2xxx: edif: Add extraction of auth_els from the wire")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-14-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 3ba019bdd89d931499d9476456b5d9c7ab7fa753 upstream ]
When qla2x00_mem_alloc() fails, qla2x00_probe_one() jumps to
probe_hw_failed and calls qla2x00_mem_free(). Several error labels in
qla2x00_mem_alloc() freed adapter members (elsrej.c, purex_dma_pool,
flt, sfp_data, loop_id_map, async_pd, sf_init_cb, ex_init_cb, npiv_info)
but left the pointers dangling. qla2x00_mem_free() then freed them a
second time. Worse, for the dma_pool members it issued
dma_pool_free(ha->s_dma_pool, ...) after s_dma_pool had already been
destroyed and set to NULL at fail_s_dma_pool, dereferencing a NULL pool.
Clear each freed pointer (and its DMA handle) in the error labels so the
subsequent qla2x00_mem_free() skips them.
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-13-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 6d90f0feb929f6c0f3010f9af4747c7230b75993 upstream ]
For QLAFX00 the request ring is ioremapped device I/O memory
(ha->iobase + req_que_off), not DMA-coherent RAM, which is why the rest
of the FX00 path accesses it through memcpy_toio() and the wrt_reg_*
helpers. __qla2x00_alloc_iocbs() however zeroed the producer slot with a
plain memset(). On architectures such as ARM64 a regular memset() may
emit unaligned or block-zeroing instructions (e.g. DC ZVA) that are
invalid on Device memory, leading to a synchronous external abort.
Use memset_io() to clear the slot for QLAFX00, matching the I/O
accessors used elsewhere on this ring. Other adapters keep the plain
memset() on their DMA-coherent rings. The zero-fill is retained for FX00
because its IOCB builders (e.g. qlafx00_fxdisc_iocb()) copy only part of
the entry and rely on the unused tail being pre-zeroed.
Fixes: 8ae6d9c7eb10 ("[SCSI] qla2xxx: Enhancements to support ISPFx00.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-12-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 626e44f3d8a924a97a3848a9fd45833947e081e9 upstream ]
qla2x00_free_fce_trace() freed and cleared ha->fce while holding only
fce_mutex. The firmware-dump consumers qla27xx_fwdt_entry_t264() and
qla25xx_copy_fce() read ha->fce (NULL check followed by a copy of the
buffer) under hardware_lock and never take fce_mutex. A debugfs FCE
disable could therefore free the DMA buffer between a dump's NULL check
and its copy, resulting in a use-after-free.
Unpublish ha->fce under hardware_lock, then release the lock and free
the DMA buffer (dma_free_coherent() may sleep). A concurrent dump either
completes its check and copy with the buffer still valid, or observes
ha->fce == NULL and skips it.
Fixes: 841df27d619e ("scsi: qla2xxx: Move FCE Trace buffer allocation to user control")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-11-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 53298efcbbb0f0438366d45cb7ed7e6d93dd5531 upstream ]
qla2x00_dfs_fce_write() called kstrtoul() with a NULL result pointer,
so a successful parse would dereference NULL and oops. Worse, the int
return value (0 on success, negative errno on failure) was assigned to
the unsigned long enable flag, inverting the intended logic: a valid
number was treated as "disable" while a parse failure enabled FCE.
Parse the value into enable and propagate parse errors to userspace.
Fixes: 841df27d619e ("scsi: qla2xxx: Move FCE Trace buffer allocation to user control")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-10-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit b7368687e3d11f51392d3c4774ec0263d5fbf31f upstream ]
The mbx_cmd_t is allocated on the stack but left uninitialized.
qla2x00_mailbox_command() has several early-return paths (PCI permanent
failure, device failed, EEH busy, ISP abort pending, mailbox access
timeout, purge mbox) that return without writing the input mailbox
registers back into mcp->mb[]. qla2x00_get_firmware_state() then
unconditionally copies mcp->mb[1..6] (and mb[12]) into the caller's
states[] array regardless of the return value.
On such a failure the copied values are uninitialized kernel stack
memory, which is then exposed to userspace via the fw_state and
mpi_fw_state sysfs handlers. Zero the mailbox struct so a failed query
yields deterministic zeroed state instead of leaking stack contents.
Fixes: 4d4df1932b6b ("[SCSI] qla2xxx: Add ISP84XX support.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-9-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit 9efaa782845b4d5fb3e01242be0d06ebc7428d8f upstream ]
qla2x00_fw_state_show() initializes rval to QLA_FUNCTION_FAILED and jumps
to the out: label when the chip is down or EEH is busy. The out: block
then re-issued qla2x00_get_firmware_state() because rval != QLA_SUCCESS,
defeating the chip-down/EEH-busy guards and issuing a mailbox command
(outside optrom_mutex) during ISP reset or PCI error recovery, which can
hang the adapter. It also turned a normal in-lock mailbox failure into a
second unsynchronized mailbox attempt.
Make the out: fallback only mark the firmware state as unknown. The
mailbox is now issued at most once, inside optrom_mutex, and only when
the chip is up and not EEH-busy.
Fixes: b6faaaf796d7 ("scsi: qla2xxx: Serialize mailbox request")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-8-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
[ commit e0cebe20dcffbed9c078fe30e2d18cd5046d9eff upstream ]