[PATCH AUTOSEL 6.18-5.15] host1x: bus: Fix missing ops null check in error teardown
From: Sasha Levin
Date: Mon Aug 31 2026 - 10:51:40 EST
From: shayderrr <darknessshayder@xxxxxxxxx>
[ Upstream commit 71d25f668bc5c0f36ea843462e12307dea45aaa3 ]
In host1x_device_init(), the error teardown paths do not check
client->ops before dereferencing it, unlike the forward init paths
which correctly guard with 'client->ops &&'. This can result in a
NULL pointer dereference if client->ops is NULL.
Fix by adding the missing client->ops check in both the teardown
and teardown_late labels.
Signed-off-by: shayderrr <darknessshayder@xxxxxxxxx>
Signed-off-by: Thierry Reding <treding@xxxxxxxxxx>
Link: https://patch.msgid.link/20260517170456.84927-1-darknessshayder@xxxxxxxxx
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
LLM Generated explanations, may be completely bogus:
## Phase 1: Commit Message Forensics
### Step 1.1: Subject Line
**Record:** `[host1x: bus]` `[Fix]` — Add missing `client->ops` NULL
checks in `host1x_device_init()` error teardown paths.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** shayderrr \<darknessshayder@xxxxxxxxx\> (author)
- **Signed-off-by:** Thierry Reding \<treding@xxxxxxxxxx\> (host1x/Tegra
maintainer)
- **Link:** https://patch.msgid.link/20260517170456.84927-1-
darknessshayder@xxxxxxxxx
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, or Cc:
stable tags
- Notable: maintainer sign-off is a strong quality signal; no
syzbot/user bug report
### Step 1.3: Body Analysis
**Record:**
- **Bug:** `host1x_device_init()` teardown (`teardown`, `teardown_late`)
dereferences `client->ops` without a NULL guard; forward init paths
already use `client->ops &&`.
- **Symptom:** NULL pointer dereference during error recovery when
initialization fails.
- **Root cause:** Oversight when teardown was added (2017) and when
`teardown_late` was added (2021); `host1x_device_exit()` and other
paths in the same file already guard correctly.
### Step 1.4: Hidden Bug Fix?
**Record:** No — this is an explicit NULL-deref fix on an error path,
not disguised cleanup.
---
## Phase 2: Diff Analysis
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/gpu/host1x/bus.c` (+2 / -2 lines)
- **Function:** `host1x_device_init()`
- **Scope:** Single-file, surgical (2-line change)
### Step 2.2: Code Flow Change
**Record:**
- **Hunk 1 (`teardown`):** `if (client->ops->exit)` → `if (client->ops
&& client->ops->exit)`
- **Hunk 2 (`teardown_late`):** `if (client->ops->late_exit)` → `if
(client->ops && client->ops->late_exit)`
- **Before:** Error teardown could dereference NULL `client->ops`.
- **After:** Clients without `ops` are skipped, matching forward init
and `host1x_device_exit()`.
### Step 2.3: Bug Mechanism
**Record:** **Category:** NULL pointer dereference (memory safety).
**Mechanism:** On `early_init`/`init` failure, reverse iteration calls
`client->ops->exit` / `client->ops->late_exit` even when `client->ops`
is NULL — a client skipped in the forward path can still be visited in
teardown.
### Step 2.4: Fix Quality
**Record:** Obviously correct; mirrors existing patterns at lines
196–207, 257–271, and 815–836 in the same file. Minimal regression risk.
---
## Phase 3: Git History Investigation
### Step 3.1: Blame
**Record:**
- `teardown` without NULL check: introduced in `8f7da1578e90b` (Thierry
Reding, 2017-11-08) — "gpu: host1x: Cleanup on initialization failure"
- `teardown_late` without NULL check: introduced in `933deb8c7b8e3f`
(Thierry Reding, 2021-03-26) — "gpu: host1x: Add early init and late
exit callbacks"
- Forward paths have had `client->ops &&` since original
`host1x_device_init()` (2013)
### Step 3.2: Fixes: Tag
**Record:** N/A — no Fixes: tag.
### Step 3.3: Related File History
**Record:** Recent host1x stable-style fixes in this tree include UAF
(`5f4de3c717d34`), reference leak (`c4d6442ac3ed0`), and syncpt race
(`79197c6007f2a`). Standalone fix; not part of a series.
### Step 3.4: Author Context
**Record:** shayderrr is a contributor; Thierry Reding (maintainer)
signed off. Author is not the subsystem maintainer but patch was
accepted by one.
### Step 3.5: Dependencies
**Record:** No prerequisites. Applies to code present since 2017/2021.
Self-contained.
---
## Phase 4: Mailing List and External Research
### Step 4.1–4.5
**Record:**
- `b4 dig` by commit hash and subject: no match (commit not in this
checkout)
- Lore/patch.msgid.link: blocked by Anubis bot protection — could not
read thread
- **UNVERIFIED:** Reviewer feedback, stable nominations, series
revisions
---
## Phase 5: Code Semantic Analysis
### Step 5.1: Key Functions
**Record:** `host1x_device_init()` — only function modified.
### Step 5.2: Callers
**Record:** `host1x_device_init()` is called from:
- `drivers/gpu/drm/tegra/drm.c` (Tegra DRM probe)
- `drivers/crypto/tegra/tegra-se-main.c` (Tegra SE)
- `drivers/staging/media/tegra-video/video.c` (staging Tegra video)
All are device-probe initialization paths on Tegra (or COMPILE_TEST).
### Step 5.3: Callees
**Record:** `client->ops->exit`, `client->ops->late_exit`,
`mutex_lock/unlock`, list iteration macros.
### Step 5.4: Reachability
**Record:**
1. Tegra clients register via `host1x_client_register()` /
`__host1x_client_register()`.
2. `host1x_device_init()` runs when the composite host1x device driver
probes.
3. If any client's `init`/`early_init` fails, teardown runs.
4. Forward path skips clients with `client->ops == NULL`; teardown does
not — inconsistent and unsafe.
5. In-tree drivers set `ops` before register, but the API explicitly
allows NULL `ops` (forward guards prove intent). A client with NULL
`ops` on `device->clients` plus a later init failure triggers the
bug.
**Userspace trigger:** Indirect — probe failure during boot/driver load
on Tegra systems with `CONFIG_TEGRA_HOST1X` and dependent drivers.
### Step 5.5: Similar Patterns
**Record:** Same `client->ops &&` pattern used in
`host1x_device_exit()`, `host1x_client_suspend()`, and
`host1x_client_resume()` in the same file. Teardown paths are the
outlier.
---
## Phase 6: Cross-Reference Against Local Tree
### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Local tree is **v6.18.44** (Makefile: 6.18.44).
Buggy code at lines 224 and 232 in `drivers/gpu/host1x/bus.c` — fix not
yet applied.
### Step 6.2: Backport Complications
**Record:** **Clean apply expected** — two identical one-line changes.
No conflicting recent churn in this function.
### Step 6.3: Related Fixes Already Present?
**Record:** No existing fix for this issue in this tree.
---
## Phase 7: Subsystem and Maintainer Context
### Step 7.1: Subsystem
**Record:** `drivers/gpu/host1x/` — Tegra display/multimedia bus
infrastructure. **Criticality:** IMPORTANT for Tegra/embedded;
PERIPHERAL globally (requires `CONFIG_TEGRA_HOST1X`, `ARCH_TEGRA` or
`COMPILE_TEST`).
### Step 7.2: Activity
**Record:** Actively maintained; multiple bugfix commits in recent
history on this subsystem.
---
## Phase 8: Impact and Risk Assessment
### Step 8.1: Who Is Affected
**Record:** Tegra platform users with host1x clients (DRM, crypto,
staging video). Not universal x86/ARM server impact.
### Step 8.2: Trigger Conditions
**Record:**
- `host1x_device_init()` called during probe
- A client `init`/`early_init` fails
- Teardown visits a client with `client->ops == NULL` (skipped during
forward init)
- **Likelihood:** Low-to-medium on error paths; requires init failure
plus NULL-ops client on the list
### Step 8.3: Failure Mode Severity
**Record:** Kernel oops (NULL dereference) during error recovery instead
of clean `-errno` return. **Severity: HIGH** for affected path (turns
recoverable probe failure into crash).
### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** Prevents crash on init-failure teardown; makes error
recovery robust
- **Risk:** Very low — 2-line change matching established pattern
- **Ratio:** Favorable for Tegra stable users
---
## Phase 9: Final Synthesis
### Step 9.1: Evidence Summary
**FOR backport:**
- Real NULL-deref bug on error path
- Trivial, obviously correct 2-line fix
- Matches existing code in same function/file
- Maintainer (Thierry Reding) signed off
- Bug present since 2017/2021; affects this v6.18.44 tree
- Error-path crash is worse than the original init failure
**AGAINST backport:**
- Platform-specific (Tegra only)
- Requires init failure (uncommon)
- No user/syzbot report documented
- In-tree drivers appear to always set `ops` before register (trigger
may be rare in practice)
**UNRESOLVED:**
- Mailing list review thread (Anubis blocked)
- No confirmed in-tree reproduction with current drivers
The unresolved items do not outweigh the clear correctness fix: forward
paths already treat NULL `ops` as valid; teardown must match.
### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — mirrors existing guards;
maintainer SOB; no logic change beyond NULL safety
2. Fixes a real bug? **PASS** — NULL deref on error teardown
3. Important issue? **PASS** — kernel oops on probe error recovery (HIGH
for affected users)
4. Small and contained? **PASS** — 2 lines, 1 file
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — buggy code confirmed in v6.18.44
### Step 9.3: Exception Categories
**Record:** None (standard bug fix).
### Step 9.4: Decision Rationale
This is a conservative, surgical fix for an inconsistent NULL check that
can kernel-oops during `host1x_device_init()` error recovery on Tegra
systems. The fix aligns teardown with forward init and
`host1x_device_exit()`, carries negligible regression risk, and the
buggy code is present in this v6.18.44 tree.
---
## Verification
- **[Phase 1]** Parsed commit message and tags from user query
- **[Phase 2]** Confirmed diff: 2 lines in `host1x_device_init()`
teardown paths
- **[Phase 3]** `git describe HEAD`: v6.18.44; Makefile confirms 6.18.44
- **[Phase 3]** `git blame -L 222,236`: teardown from 2017
(`8f7da1578e90b`), teardown_late from 2021 (`933deb8c7b8e3f`)
- **[Phase 3]** `git show 8f7da1578e90bf`: original teardown added
without NULL check while forward path had one
- **[Phase 3]** `git log -p -S 'if (client->ops->exit)'`: confirmed 2017
introduction of unguarded teardown
- **[Phase 3]** `git log --oneline -15 -- drivers/gpu/host1x/bus.c`:
recent related fixes; no duplicate fix
- **[Phase 4]** `b4 dig`: no results (commit not in tree)
- **[Phase 4]** WebFetch lore/patch.msgid.link: blocked by Anubis —
**UNVERIFIED** review discussion
- **[Phase 5]** `grep host1x_device_init`: callers in tegra drm, tegra-
se, tegra-video
- **[Phase 5]** Read `host1x_device_init()`, `host1x_device_exit()`,
suspend/resume: confirmed `client->ops &&` pattern elsewhere
- **[Phase 5]** Read tegra driver probes (dc.c, gr3d.c, sor.c, tegra-
se): ops set before register
- **[Phase 6]** Read current `bus.c` lines 224, 232: buggy code present
(no NULL check)
- **[Phase 6]** Kconfig: `CONFIG_TEGRA_HOST1X` depends on `ARCH_TEGRA ||
COMPILE_TEST`
- **[Phase 8]** Failure mode: NULL deref → oops on init-failure teardown
**YES**The backport analysis is done.
**Commit:** `host1x: bus: Fix missing ops null check in error teardown`
**Tree:** v6.18.44 — the bug is still present (unguarded `client->ops`
derefs at lines 224 and 232 in `drivers/gpu/host1x/bus.c`).
**Summary:** On Tegra, if `host1x_device_init()` fails partway through,
the teardown paths can NULL-deref `client->ops` while forward init and
`host1x_device_exit()` already guard against that. The fix is two lines,
matches existing patterns, and is signed off by host1x maintainer
Thierry Reding.
**Verdict: YES** — backport to this tree.
A background `git log --grep` search timed out; it wasn’t needed for the
decision since the buggy code and history were already confirmed
directly.
drivers/gpu/host1x/bus.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 3313ead8bfcc2..06aa7fcd367e1 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -221,7 +221,7 @@ int host1x_device_init(struct host1x_device *device)
teardown:
list_for_each_entry_continue_reverse(client, &device->clients, list)
- if (client->ops->exit)
+ if (client->ops && client->ops->exit)
client->ops->exit(client);
/* reset client to end of list for late teardown */
@@ -229,7 +229,7 @@ int host1x_device_init(struct host1x_device *device)
teardown_late:
list_for_each_entry_continue_reverse(client, &device->clients, list)
- if (client->ops->late_exit)
+ if (client->ops && client->ops->late_exit)
client->ops->late_exit(client);
mutex_unlock(&device->clients_lock);
--
2.53.0