From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jason Gunthorpe <jgg@nvidia.com>, Sasha Levin <sashal@kernel.org>,
linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18] RDMA/umem: Make ib_umem_is_contiguous() safe on 32 bit
Date: Mon, 31 Aug 2026 09:21:25 -0400 [thread overview]
Message-ID: <20260831133314.4125787-57-sashal@kernel.org> (raw)
In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org>
From: Jason Gunthorpe <jgg@nvidia.com>
[ Upstream commit 55d984dae65262fbb0a673cff7cc9824a5e19bdb ]
Sashiko points out the roundup_pow_of_two() only uses unsigned long but
dma_addr_t can be u64.
Change this algorithm to be simpler, compute the page size, if any page
size is found and it results in a single block then it is contiguous.
Link: https://patch.msgid.link/r/3-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[RDMA/umem]` `[Make/safe]` — Make `ib_umem_is_contiguous()`
safe on 32-bit by fixing type truncation in page-size computation.
### Step 1.2: Tags
**Record:**
- **Link:** https://patch.msgid.link/r/3-v1-88303e9e509f+f7-
ib_umem_types_jgg@nvidia.com
- **Signed-off-by:** Jason Gunthorpe \<jgg@nvidia.com\>
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, or Cc: stable in
the commit message itself
- **Notable:** Patch is **[PATCH 3/3]** in series "Fix typing issues in
the umem code"; cover letter and patch 1 CC `stable@vger.kernel.org`.
Author is RDMA subsystem maintainer.
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `roundup_pow_of_two()` operates on `unsigned long`, but its
input involves `dma_addr_t` which can be `u64` on 32-bit kernels with
`CONFIG_ARCH_DMA_ADDR_T_64BIT`.
- **Symptom:** Incorrect page-size computation in
`ib_umem_is_contiguous()`, yielding wrong contiguous/non-contiguous
results.
- **Root cause:** Silent truncation of a 64-bit DMA-address expression
to 32-bit `unsigned long` before `roundup_pow_of_two()`.
- **Fix approach:** Replace XOR/roundup algorithm with
`ib_umem_find_best_pgsz()` + `ib_umem_num_dma_blocks() == 1` check.
### Step 1.4: Hidden Bug Fix?
**Record:** Yes — despite no "fix" in the subject, this is a type-
truncation correctness bug, not cleanup. Reported by Sashiko per commit
message.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory
**Record:**
- **Files:** `include/rdma/ib_umem.h` only (+3 / -8 lines)
- **Functions:** `ib_umem_is_contiguous()`
- **Scope:** Single-file, surgical inline-helper fix
### Step 2.2: Code Flow Change
**Record:**
- **Before:** Compute `pgsz = roundup_pow_of_two((dma_addr ^
(umem->length - 1 + dma_addr)) + 1)`, then call
`ib_umem_find_best_pgoff(umem, pgsz, U64_MAX)`.
- **After:** `pgsz = ib_umem_find_best_pgsz(umem, ULONG_MAX,
ib_umem_start_dma_addr(umem))`, return true iff `pgsz &&
ib_umem_num_dma_blocks(umem, pgsz) == 1`.
- **Path affected:** Any caller checking umem contiguity (EFA CQ
external-memory creation).
### Step 2.3: Bug Mechanism
**Record:**
- **Category:** Type/size truncation (endianness/type bug family)
- **Mechanism:** On 32-bit with 64-bit `dma_addr_t`, `(dma_addr ^
(umem->length - 1 + dma_addr)) + 1` is computed in 64-bit arithmetic
but implicitly truncated when passed to `roundup_pow_of_two(unsigned
long)`, producing wrong `pgsz` and wrong contiguity result.
### Step 2.4: Fix Quality
**Record:** Obviously correct and simpler. Uses existing helpers that
already handle `dma_addr_t` internally for SG traversal. Low regression
risk. **Caveat:** Full correctness on 32-bit also requires patch 2/3 of
the same series (changing `ib_umem_find_best_pgsz()`'s `virt` parameter
from `unsigned long` to `u64`), which is not yet in this tree.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:** Buggy `ib_umem_is_contiguous()` introduced in
`c897c2c8b8e82` ("RDMA/core: Add umem is_contiguous and start_dma_addr
helpers", 2025-07-08). Present in this 6.18.y tree.
### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag on this commit.
### Step 3.3: Related File History
**Record:**
- Part of 3-patch series by Jason Gunthorpe (2026-06-01):
1. `15fe76e23615f` — Fix truncation for block sizes >= 4G (`iter.c`) —
**already backported** as `afd35fec92971`
2. `09ea6837a0434` — Boundary conditions in `ib_umem_find_best_pgsz()`
— **NOT in tree**
3. `55d984dae6526` — This commit — **NOT in tree**
- `ib_umem_is_contiguous()` caller added in `9fb3dd85197f5` (EFA CQ
external memory support), also in tree.
### Step 3.4: Author Context
**Record:** Jason Gunthorpe is core RDMA maintainer. Recent related work
includes `ib_umem_find_best_pgsz()` improvements and umem typing fixes.
### Step 3.5: Dependencies
**Record:** Patch 2 (`09ea6837a0434`) changes `ib_umem_find_best_pgsz()`
to accept `u64 virt` instead of `unsigned long virt`. This commit passes
`ib_umem_start_dma_addr(umem)` (`dma_addr_t`) as that argument. **For a
complete 32-bit fix, patch 2 should accompany this commit.** Patch 3
compiles and applies standalone but retains `virt` truncation without
patch 2.
---
## Phase 4: Mailing List and External Research
### Step 4.1: Original Discussion
**Record:**
- **URL:** https://patch.msgid.link/3-v1-88303e9e509f+f7-
ib_umem_types_jgg@nvidia.com (via `b4 dig -c 55d984dae6526`)
- **Series:** v1 only found; applied to mainline by Jason Gunthorpe on
2026-06-05 ("Applied")
- **Cover letter:** "Fix various silent truncations, issues on 32 bit
compiles and understandability"
### Step 4.2: Reviewers
**Record:** To: Leon Romanovsky, linux-rdma; Cc:
patches@lists.linux.dev, Shiraz Saleem, **stable@vger.kernel.org**
### Step 4.3: Bug Report
**Record:** No formal bugzilla/syzbot report. Issue raised by Sashiko
during review (per commit message). No stack traces or crash reports.
### Step 4.4: Related Patches
**Record:** 3-patch series; patch 1 already backported to 6.18.y.
Patches 2+3 remain.
### Step 4.5: Stable List History
**Record:** Author CC'd stable on cover letter and patch 1 (which was
backported). Explicit stable nomination signal.
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `ib_umem_is_contiguous()`, `ib_umem_find_best_pgsz()`,
`ib_umem_num_dma_blocks()`, `ib_umem_start_dma_addr()`
### Step 5.2: Callers
**Record:** Single caller in this tree:
- `drivers/infiniband/hw/efa/efa_verbs.c` — EFA CQ creation with
external memory; rejects non-contiguous buffers with `-EINVAL`.
### Step 5.3: Callees
**Record:** `ib_umem_find_best_pgsz()` walks SG table using
`dma_addr_t`; `ib_umem_num_dma_blocks()` counts blocks from `umem->iova`
and `umem->length`.
### Step 5.4: Reachability
**Record:** Reachable from userspace via RDMA uverbs CQ creation ioctl
(EFA driver, `CONFIG_INFINIBAND_EFA`). Requires
`CONFIG_INFINIBAND_USER_MEM`.
### Step 5.5: Similar Patterns
**Record:** Same series addresses related truncation in `iter.c`
(already backported) and `ib_umem_find_best_pgsz()` (patch 2, not yet
backported).
---
## Phase 6: Cross-Reference Against Local Tree
### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Tree is **v6.18.44** (`linux-6.18.y`). Buggy
`roundup_pow_of_two()` code is at lines 122–134 of
`include/rdma/ib_umem.h`. Introduced July 2025, well within 6.18's
lifetime.
### Step 6.2: Backport Complications
**Record:** Clean apply expected — single hunk in one header. No
conflicting changes found. **Recommend backporting patch 2 alongside for
complete fix.**
### Step 6.3: Related Fixes Already Present?
**Record:** Patch 1 of series (`afd35fec92971`) already backported.
Patches 2 and 3 are not. No alternative fix for this specific bug.
---
## Phase 7: Subsystem Context
### Step 7.1: Subsystem
**Record:** RDMA core (`include/rdma/ib_umem.h`) — **IMPORTANT**
(affects RDMA memory registration path, used by multiple drivers via
shared helpers).
### Step 7.2: Activity
**Record:** Actively developed; `ib_umem_is_contiguous()` is relatively
new (2025).
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Users of RDMA with `CONFIG_INFINIBAND_USER_MEM` on **32-bit
architectures with 64-bit DMA addresses** (e.g., ARM with
`CONFIG_ARCH_DMA_ADDR_T_64BIT`). Currently impacts EFA external-memory
CQ path directly; helper is available for other drivers.
### Step 8.2: Trigger Conditions
**Record:** Creating an RDMA memory region where DMA addresses or span
computations exceed 32-bit when truncated. Requires EFA (currently) +
external memory CQ. Not every boot, but reachable from userspace RDMA
operations.
### Step 8.3: Failure Mode Severity
**Record:**
- **False negative** (contiguous reported as non-contiguous): `-EINVAL`,
CQ creation fails — **MEDIUM**
- **False positive** (non-contiguous reported as contiguous): device
programmed with wrong memory layout — potential **data corruption /
hardware malfunction** — **HIGH**
- Not a typical kernel oops/panic, but correctness bug with corruption
potential.
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** MEDIUM-HIGH — fixes real type bug in shared RDMA helper;
author nominated for stable; series already partially backported
- **Risk:** LOW — 3-line net change, uses existing well-tested helpers
- **Ratio:** Favorable
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR:**
- Real type-truncation bug on 32-bit with 64-bit `dma_addr_t`
- Small, surgical, obviously correct fix from RDMA maintainer
- Author CC'd stable; patch 1 of same series already in 6.18.y
- False-positive contiguity could cause serious RDMA misprogramming
- Buggy code confirmed present in v6.18.44
**AGAINST:**
- Niche platform config (32-bit + 64-bit DMA + RDMA)
- Only one direct caller today (EFA)
- Complete fix requires patch 2 (`09ea6837a0434`) not yet in tree
- No crash report or syzbot reproduction
**Unresolved:** No runtime test results in mailing list thread.
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — logic is sound; applied to
mainline; no objections in review
2. Fixes a real bug? **PASS** — confirmed type truncation in existing
code
3. Important issue? **PASS** — correctness bug with potential data
corruption (false positive path)
4. Small and contained? **PASS** — 3 lines net, one file
5. No new features/APIs? **PASS** — same function signature and
semantics
6. Can apply to local tree? **PASS** — applies cleanly; patch 2 should
accompany for completeness
### Step 9.3: Exception Categories
**Record:** N/A — standard bug fix, not device-ID/quirk/build/doc
exception.
### Step 9.4: Decision Rationale
This commit fixes a real, verifiable type-truncation bug in
`ib_umem_is_contiguous()` that exists in the 6.18.44 tree. The buggy
code was introduced in July 2025 and can cause incorrect contiguity
detection on 32-bit kernels where `dma_addr_t` is 64-bit. While the
immediate caller is the EFA driver's external-memory CQ path, the helper
is shared RDMA infrastructure.
The fix is minimal, low-risk, and from the RDMA maintainer who
explicitly CC'd stable. Patch 1 of the same 3-patch series is already
backported to this tree (`afd35fec92971`), establishing precedent.
**Patch 2 (`09ea6837a0434`) should be backported together with this
commit** for a complete 32-bit fix, since this commit passes a
`dma_addr_t` to `ib_umem_find_best_pgsz()` which still takes `unsigned
long virt` in 6.18.y. Even standalone, removing the broken
`roundup_pow_of_two()` path is a meaningful improvement.
---
## Verification
- **[Phase 1]** Parsed commit message: subsystem RDMA/umem, Link tag,
Jason Gunthorpe SOB, Sashiko attribution
- **[Phase 2]** Diff analysis: 3 insertions, 8 deletions in
`ib_umem_is_contiguous()`; removes `roundup_pow_of_two()` call
- **[Phase 3]** `git blame`: buggy code from `c897c2c8b8e82`
(2025-07-08), present in tree
- **[Phase 3]** `git merge-base --is-ancestor c897c2c8b8e82 HEAD`: intro
commit IS in tree
- **[Phase 3]** Series check: patch 1 (`afd35fec92971`) IN tree; patches
2 (`09ea6837a0434`) and 3 (`55d984dae6526`) NOT in tree
- **[Phase 3]** `git log --oneline -20 -- include/rdma/ib_umem.h`:
confirmed recent umem history
- **[Phase 4]** `b4 dig -c 55d984dae6526`: found thread at
patch.msgid.link
- **[Phase 4]** `b4 dig -c 55d984dae6526 -a`: v1 series, 3 patches
- **[Phase 4]** `b4 dig -c 55d984dae6526 -w`: stable@vger.kernel.org
CC'd
- **[Phase 4]** `b4 dig -m /tmp/umem_thread.mbox`: cover letter
describes 32-bit truncation fixes; "Applied" reply from author
- **[Phase 5]** `grep ib_umem_is_contiguous`: one caller in
`efa_verbs.c:1222`
- **[Phase 5]** Read `efa_verbs.c:1215-1230`: rejects non-contiguous
with `-EINVAL`
- **[Phase 5]** Read `ib_umem_find_best_pgsz()` in `umem.c`: uses
`dma_addr_t` internally for SG traversal
- **[Phase 6]** `git describe HEAD`: v6.18.44; `make kernelversion`:
6.18.44
- **[Phase 6]** Read current `ib_umem.h:122-134`: confirmed buggy code
still present
- **[Phase 6]** `include/linux/types.h:157-161`: `dma_addr_t` is `u64`
when `CONFIG_ARCH_DMA_ADDR_T_64BIT`
- **[Phase 6]** `include/linux/log2.h:174-181`: `roundup_pow_of_two()`
uses `unsigned long` / `1UL`
- **[Phase 8]** Failure mode: wrong contiguity → EINVAL or potential
RDMA misprogramming
**YES**The analysis is complete: **this commit should be backported to
the 6.18.y tree (v6.18.44).**
**Why:** `ib_umem_is_contiguous()` truncates 64-bit `dma_addr_t` values
through `roundup_pow_of_two()` on 32-bit kernels with 64-bit DMA
addresses. That can mis-detect memory contiguity and break EFA external-
memory CQ creation (or worse, accept non-contiguous memory).
**Scope:** Small, low-risk change in `include/rdma/ib_umem.h` (3 lines
net). The buggy code from July 2025 is present in this tree; the fix is
not.
**Follow-up for stable maintainers:** Backport patch 2 of the same
series (`09ea6837a0434` — changes `ib_umem_find_best_pgsz()` to take
`u64 virt`) together with this commit for a complete 32-bit fix. Patch 1
of the series is already in 6.18.y as `afd35fec92971`.
include/rdma/ib_umem.h | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 0cda3e6425d2e..8a74153332577 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -121,16 +121,11 @@ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
static inline bool ib_umem_is_contiguous(struct ib_umem *umem)
{
- dma_addr_t dma_addr;
unsigned long pgsz;
- /*
- * Select the smallest aligned page that can contain the whole umem if
- * it was contiguous.
- */
- dma_addr = ib_umem_start_dma_addr(umem);
- pgsz = roundup_pow_of_two((dma_addr ^ (umem->length - 1 + dma_addr)) + 1);
- return !!ib_umem_find_best_pgoff(umem, pgsz, U64_MAX);
+ pgsz = ib_umem_find_best_pgsz(umem, ULONG_MAX,
+ ib_umem_start_dma_addr(umem));
+ return pgsz && ib_umem_num_dma_blocks(umem, pgsz) == 1;
}
struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device,
--
2.53.0
next prev parent reply other threads:[~2026-08-31 13:34 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:21 ` [PATCH AUTOSEL 6.18-6.1] eth: mlx5: fix macsec dependency Sasha Levin
2026-08-31 13:21 ` Sasha Levin [this message]
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18-5.15] RDMA/rtrs-srv: Fix integer underflow in process_read and process_write Sasha Levin
2026-08-31 13:22 ` [PATCH AUTOSEL 6.18-6.6] net/mlx5: E-Switch, align disable sequence with switchdev-to-legacy transition Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] RDMA/mlx5: Fix state and counter desync on loopback enable failure Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18] RDMA/counter: Fix num_counters leak on bind_qp failure in alloc_and_bind() Sasha Levin
2026-08-31 13:24 ` [PATCH AUTOSEL 6.18-5.10] rds: annotate data-race around rs_seen_congestion Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18-6.12] net/mlx5e: Verify unique vhca_id count instead of range Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18-6.12] net/mlx5: HWS, Handle destroying table that has a miss table Sasha Levin
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18-5.10] rds: filter RDS_INFO_* getsockopt by caller's netns Sasha Levin
2026-08-31 13:27 ` [PATCH AUTOSEL 6.18] net/mlx5: HWS, Check if device is down while polling for completion Sasha Levin
2026-08-31 13:28 ` [PATCH AUTOSEL 6.18] net/mlx5: Relax capability check for eswitch query paths Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-5.10] net/rds: Don't sleep inside rds_ib_conn_path_shutdown Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18-5.10] RDMA/mlx5: Use QP port when decoding responder CQEs Sasha Levin
2026-08-31 13:29 ` [PATCH AUTOSEL 6.18] net/mlx5: Switch vport HCA cap helpers to kvzalloc Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-6.12] RDMA/mlx5: Create ODP EQ for non-pinned dmabuf MRs Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-6.1] RDMA/irdma: Fix typo in SQ completions generation Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-5.15] RDMA/umem: Be careful about boundary conditions in ib_umem_find_best_pgsz() Sasha Levin
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=20260831133314.4125787-57-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=jgg@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox