All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ali Ahmet Memis" <ali@iusegentoo.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 4/5] scsi: elx: efct: free the RQ buffers already allocated when one fails
Date: Thu, 06 Aug 2026 20:38:10 +0000	[thread overview]
Message-ID: <20260806203811.2BF171F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260806202205.345326-5-ali@iusegentoo.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Pre-existing issues:
- [High] Extensive memory and DMA buffer leaks on device probe and initialization error paths.
- [High] Double-free and use-after-free vulnerability on the error path of efct_hw_new_rq_set().
- [High] Unsafe teardown of stats_timer leading to Use-After-Free and timer wheel corruption.
- [High] Invalid use of `timer_setup()` within the timer callback.
- [High] Error path in efct_hw_setup_io() leaks successfully allocated hw->io[i] inner objects.
--

--- Patch [4]: [PATCH v2 4/5] scsi: elx: efct: free the RQ buffers already allocated when one fails ---
commit be8b053b462b939279de3cc82f2caf1d37ac0767
Author: Ali Ahmet Memis <ali@iusegentoo.com>

scsi: elx: efct: free the RQ buffers already allocated when one fails

efct_hw_rx_buffer_alloc() allocates an array of descriptors and then a
coherent DMA buffer for each entry. When one of those allocations fails it
frees the array and returns NULL, leaving every buffer allocated before it
mapped. This commit uses efct_hw_rx_buffer_free() for the entries that
were filled in to fix the leak.

> diff --git a/drivers/scsi/elx/efct/efct_hw.c b/drivers/scsi/elx/efct/efct_hw.c
> index db68516e80750..d645ce256b8aa 100644
> --- a/drivers/scsi/elx/efct/efct_hw.c
> +++ b/drivers/scsi/elx/efct/efct_hw.c
> @@ -1170,6 +1170,10 @@ efct_get_wwpn(struct efct_hw *hw)
>  	return get_unaligned_be64(p);
>  }
>  
> +static void
> +efct_hw_rx_buffer_free(struct efct_hw *hw, struct efc_hw_rq_buffer *rq_buf,
> +		       u32 count);
> +
>  static struct efc_hw_rq_buffer *
>  efct_hw_rx_buffer_alloc(struct efct_hw *hw, u32 rqindex, u32 count,
>  			u32 size)
> @@ -1196,7 +1200,7 @@ efct_hw_rx_buffer_alloc(struct efct_hw *hw, u32 rqindex, u32 count,
>  						   GFP_KERNEL);
>  		if (!prq->dma.virt) {
>  			efc_log_err(hw->os, "DMA allocation failed\n");
> -			kfree(rq_buf);
> +			efct_hw_rx_buffer_free(hw, rq_buf, i);
>  			return NULL;
>  		}
>  	}

[Severity: High]
This is a pre-existing issue, but does this error path still leak memory?

In efct_hw_rx_allocate():

	if (!rq->hdr_buf) {
		efc_log_err(efct, "rx_buffer_alloc hdr_buf failed\n");
		rc = -EIO;
		break;
	}

If efct_hw_rx_buffer_alloc() fails for any queue index, it breaks the loop
and returns -EIO, but it appears to leak all hdr_buf and payload_buf DMA
buffer arrays that were successfully allocated in previous iterations.

Furthermore, in efct_hw_init():

	rc = efct_hw_rx_allocate(hw);
	if (rc) {
		efc_log_err(hw->os, "rx_allocate failed\n");
		return rc;
	}

It returns early on nested allocation failures without cleaning up its own
previous local allocations.

Finally, in efct_xport_initialize():

	rc = efct_hw_init(&efct->hw);
	if (rc) {
		efc_log_err(efct, "efct_hw_init failure\n");
		goto out;
	}

It jumps directly to out: on efct_hw_init() failure, skipping the hw_init_out:
label where efct_hw_teardown() is called. This seems to leak hardware
resources initialized during efct_hw_setup() and efct_hw_init() when the probe
fails.


[Severity: High]
This is a pre-existing issue, but can this error path lead to a double-free?

In efct_hw_new_rq_set():

	list_add_tail(&rqs[i]->list_entry, &cqs[i]->q_list);
	size = sizeof(struct efc_hw_sequence *) * rqs[i]->entry_count;
	rqs[i]->rq_tracker = kzalloc(size, GFP_KERNEL);
	if (!rqs[i]->rq_tracker)
		goto error;

If kzalloc() fails, it jumps to the error label:

error:
	for (i = 0; i < num_rq_pairs; i++) {
		if (rqs[i]) {
			kfree(rqs[i]->rq_tracker);
			kfree(rqs[i]);
		}
	}

This frees rqs[i] but does not remove it from the cqs[i]->q_list. The function
then returns -EIO, triggering efct_hw_queue_teardown(hw), which calls
efct_hw_del_rq():

	list_del(&rq->list_entry);
	hw = rq->cq->eq->hw;
	hw->hw_rq[rq->instance] = NULL;
	kfree(rq);

The teardown iterates over the list, dereferences the already freed rq object,
calls list_del() on it, and then calls kfree(rq) again. Does this double-free
the object and corrupt the list?


[Severity: High]
This is a pre-existing issue, but is the teardown of stats_timer safe here?

In efct_xport_detach():

	if (timer_pending(&xport->stats_timer))
		timer_delete(&xport->stats_timer);

If the timer callback efct_xport_stats_timer_cb() is actively running on
another CPU, timer_pending() might return false. Even if timer_delete()
is called, it does not wait for the concurrent callback to finish.

This could allow efct_xport_detach() to proceed and eventually free the xport
object while the timer callback is still executing. The callback would then
access the freed xport memory and call mod_timer(), inserting a freed timer
structure back into the kernel's active timer wheel. Should this
unconditionally use timer_delete_sync() without the timer_pending() check?


[Severity: High]
This is a pre-existing issue, but is it correct to call timer_setup() here?

In efct_xport_config_stats_timer():

	timer_setup(&xport->stats_timer,
		    &efct_xport_stats_timer_cb, 0);
	mod_timer(&xport->stats_timer,
		  jiffies + msecs_to_jiffies(timeout));

This function is called both for initial setup and from within the timer
callback itself (efct_xport_stats_timer_cb()) to re-arm the timer.

Calling timer_setup() on a timer that is actively being processed by the timer
subsystem resets the structure, clearing list pointers and lock-related fields.
Does this destroy the active timer structure and lead to kernel state
corruption?


[Severity: High]
This is a pre-existing issue, but does this error path leak the inner IO
objects?

In efct_hw_setup_io():

	hw->wqe_buffs = kzalloc((hw->config.n_io * hw->sli.wqe_size),
				GFP_KERNEL);
	if (!hw->wqe_buffs) {
		kfree(hw->io);
		return -ENOMEM;
	}

If the allocation for hw->wqe_buffs fails, the code frees the outer hw->io
array and returns -ENOMEM. However, it appears to completely skip the loop in
the error block that frees the individual hw->io[i] objects allocated prior to
this, which would permanently leak them.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260806192345.328621-1-ali@iusegentoo.com?part=4

  reply	other threads:[~2026-08-06 20:38 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06 19:23 [PATCH 0/5] scsi: elx: efct: fix resources stranded on failure paths Ali Ahmet Memis
2026-08-06 19:23 ` [PATCH 1/5] scsi: elx: efct: check the HW state before allocating an HIO Ali Ahmet Memis
2026-08-06 19:44   ` sashiko-bot
2026-08-06 19:23 ` [PATCH 2/5] scsi: elx: efct: free the HIO when the WQE cannot be built Ali Ahmet Memis
2026-08-06 19:54   ` sashiko-bot
2026-08-06 19:23 ` [PATCH 3/5] scsi: elx: efct: free the request tag when the send frame WQE fails Ali Ahmet Memis
2026-08-06 19:50   ` sashiko-bot
2026-08-06 19:23 ` [PATCH 4/5] scsi: elx: efct: free the RQ buffers already allocated when one fails Ali Ahmet Memis
2026-08-06 20:00   ` sashiko-bot
2026-08-06 19:23 ` [PATCH 5/5] scsi: elx: efct: destroy the mailbox pools when setup fails Ali Ahmet Memis
2026-08-06 19:41   ` sashiko-bot
2026-08-06 20:22 ` [PATCH v2 0/5] scsi: elx: efct: fix resources stranded on failure paths Ali Ahmet Memis
2026-08-06 20:22 ` [PATCH v2 1/5] scsi: elx: efct: check the HW state before allocating an HIO Ali Ahmet Memis
2026-08-06 20:59   ` sashiko-bot
2026-08-06 20:22 ` [PATCH v2 2/5] scsi: elx: efct: free the HIO when the WQE cannot be built Ali Ahmet Memis
2026-08-06 20:52   ` sashiko-bot
2026-08-06 20:22 ` [PATCH v2 3/5] scsi: elx: efct: free the request tag when the send frame WQE fails Ali Ahmet Memis
2026-08-06 20:41   ` sashiko-bot
2026-08-06 20:22 ` [PATCH v2 4/5] scsi: elx: efct: free the RQ buffers already allocated when one fails Ali Ahmet Memis
2026-08-06 20:38   ` sashiko-bot [this message]
2026-08-06 20:22 ` [PATCH v2 5/5] scsi: elx: efct: destroy the mailbox pools when setup fails Ali Ahmet Memis
2026-08-06 20:57   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260806203811.2BF171F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=ali@iusegentoo.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.