All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Bogdan Codres (Wind River)" <bogdan.codres@windriver.com>
To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: vkoul@kernel.org, dave.jiang@intel.com, vinicius.gomes@intel.com,
	xueshuai@linux.alibaba.com, yi.sun@intel.com,
	fenghuay@nvidia.com, dan.carpenter@linaro.org,
	gregkh@linuxfoundation.org, stable@vger.kernel.org
Subject: [PATCH] dmaengine: idxd: fix use-after-free in idxd_free() and idxd_alloc() error paths
Date: Mon, 15 Jun 2026 13:39:31 +0300	[thread overview]
Message-ID: <20260615103932.61828-1-bogdan.codres@windriver.com> (raw)

To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Vinod Koul <vkoul@kernel.org>,
    Dave Jiang <dave.jiang@intel.com>,
    Vinicius Costa Gomes <vinicius.gomes@intel.com>,
    Shuai Xue <xueshuai@linux.alibaba.com>,
    Yi Sun <yi.sun@intel.com>,
    Fenghua Yu <fenghuay@nvidia.com>,
    Dan Carpenter <dan.carpenter@linaro.org>,
    Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
    stable@vger.kernel.org

Hi,

This patch fixes a double-free / use-after-free bug in the IDXD driver's
probe error path that corrupts the slab allocator and crashes the kernel.
The bug was introduced by commit 90022b3a6981 ("dmaengine: idxd: fix memory
leak in error handling path of idxd_pci_probe") which added the idxd_free()
helper.

Root Cause
----------

idxd_free() performs:

  static void idxd_free(struct idxd_device *idxd)
  {
      if (!idxd)
          return;
      put_device(idxd_confdev(idxd));   // (1) triggers release callback
      bitmap_free(idxd->opcap_bmap);    // (2) USE AFTER FREE
      ida_free(&idxd_ida, idxd->id);    // (3) DOUBLE ida_free
      kfree(idxd);                      // (4) DOUBLE kfree
  }

Since device_initialize() was called in idxd_alloc(), conf_dev has
refcount=1. Step (1) drops it to 0 and synchronously triggers:

  put_device() -> kobject_put() -> kobject_release() -> kobject_cleanup()
    -> device_release() -> dev->type->release -> idxd_conf_device_release()

idxd_conf_device_release() (in sysfs.c) already does:

  static void idxd_conf_device_release(struct device *dev)
  {
      struct idxd_device *idxd = confdev_to_idxd(dev);
      kfree(idxd->groups);
      bitmap_free(idxd->wq_enable_map);
      kfree(idxd->wqs);
      kfree(idxd->engines);
      kfree(idxd->evl);
      kmem_cache_destroy(idxd->evl_cache);
      ida_free(&idxd_ida, idxd->id);    // <- FIRST ida_free
      bitmap_free(idxd->opcap_bmap);    // <- FIRST bitmap_free
      kfree(idxd);                      // <- FIRST kfree
  }

So after put_device() returns in idxd_free():
  - idxd pointer is dangling (memory freed)
  - idxd->opcap_bmap is dangling
  - idxd->id has already been freed from the IDA

Steps 2-4 then operate on freed memory, corrupting the slab allocator.

The same pattern exists in idxd_alloc() at the err_name label.

How to Reproduce
----------------

This occurs during kdump (crash dump collection) on systems with
Intel IDXD hardware:

  1. System has Intel IDXD (DSA/IAX) -- e.g., Granite Rapids / Sapphire
     Rapids platforms
  2. Original kernel panics (any reason)
  3. Kdump kernel boots with: reset_devices nr_cpus=1
  4. IDXD device is in HALTED state due to reset_devices
  5. IDXD driver probes the device -> probe fails -> idxd_free() ->
     double-free -> slab corruption
  6. systemd-udevd loads next module -> module signature verification
     allocates memory -> hits corrupted slab -> kernel oops

Console Output (kdump kernel)
-----------------------------

  [   18.628791] idxd 0000:00:01.0: Device is HALTED!
  [   18.631447] idxd 0000:00:01.0: Intel(R) IDXD DMA Engine init failed
  [   18.631450] ------------[ cut here ]------------
  [   18.631451] ida_free called for id=0 which is not allocated.
  [   18.631462] WARNING: CPU: 0 PID: 11 at lib/idr.c:525 ida_free+0xd3/0x130
  [   18.631502]  idxd_pci_probe+0x1b0/0x1860 [idxd]
    ...
  [   18.898798] BUG: unable to handle page fault for address: ff2c9dd300000010
  [   18.931865] RIP: 0010:___slab_alloc+0x168/0xa10
    ...
  [   19.097220]  __kmalloc_cache_noprof+0x82/0x230
  [   19.102683]  mpi_alloc+0x20/0x80
  [   19.106676]  rsa_enc+0x2f/0x120
  [   19.110549]  pkcs1pad_verify+0x13b/0x1a0
    ...
  [   19.161968]  module_sig_check+0x87/0xe0
  [   19.166709]  load_module+0x3c/0x1e80

Affected Versions
-----------------

  - Mainline: present at HEAD (introduced Apr 2025)
  - Stable: v6.12.30+ (backport commit 017d4012dc05)
  - Also present in other stable branches that received the backport

Test Platform
-------------

  - Dell PowerEdge XR8720t
  - Intel Xeon 6716P-B (Granite Rapids)
  - Kernel: 6.12.0-1-rt-amd64 (StarlingX 6.12.40-1.stx.140)
  - RT: PREEMPT_RT

Why This Was Not Caught Earlier
-------------------------------

  1. The error path only triggers when IDXD device is HALTED -- this
     only happens with reset_devices (kdump) or hardware error
  2. On normal boot, IDXD probe always succeeds
  3. Most kdump configurations blacklist IDXD via module_blacklist=
  4. Systems without IDXD hardware are unaffected
  5. The ida_free WARNING alone doesn't crash -- it's the subsequent
     slab corruption that causes the fatal oops, which may appear as
     an unrelated bug

Workaround
----------

Add idxd to module_blacklist in the kdump kernel command line:

  module_blacklist=idxd,idxd_bus

Fix
---

Remove the duplicate bitmap_free/ida_free/kfree from idxd_free()
since idxd_conf_device_release() (triggered by put_device()) already
handles all resource deallocation. Similarly fix idxd_alloc() err_name
path.

Related Commits
---------------

  - 90022b3a6981 ("dmaengine: idxd: fix memory leak in error handling
    path of idxd_pci_probe") -- introduces the bug
  - 46a5cca76c76 ("dmaengine: idxd: fix memory leak in error handling
    path of idxd_alloc") -- same pattern in idxd_alloc
  - f41c538881ee ("dmaengine: idxd: Remove improper idxd_free") -- fixes
    the same function but only in idxd_remove(), not probe error path
  - c311f5e9248471 ("dmaengine: idxd: Fix freeing the allocated ida too
    late") -- establishes the correct pattern for cdev (ida_free before
    put_device, not in .release())

Thanks,
Bogdan

Bogdan Codres (1):
  dmaengine: idxd: fix use-after-free in idxd_free() and idxd_alloc()
    error paths

 drivers/dma/idxd/init.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

-- 
2.43.0

             reply	other threads:[~2026-06-15 10:40 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-15 10:39 Bogdan Codres (Wind River) [this message]
2026-06-15 10:39 ` [PATCH] dmaengine: idxd: fix use-after-free in idxd_free() and idxd_alloc() error paths Bogdan Codres (Wind River)
2026-06-15 11:02   ` 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=20260615103932.61828-1-bogdan.codres@windriver.com \
    --to=bogdan.codres@windriver.com \
    --cc=dan.carpenter@linaro.org \
    --cc=dave.jiang@intel.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=fenghuay@nvidia.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=vinicius.gomes@intel.com \
    --cc=vkoul@kernel.org \
    --cc=xueshuai@linux.alibaba.com \
    --cc=yi.sun@intel.com \
    /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.