live-patching.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Song Liu <song@kernel.org>, Josh Poimboeuf <jpoimboe@kernel.org>,
	Petr Mladek <pmladek@suse.com>, Sasha Levin <sashal@kernel.org>,
	jikos@kernel.org, mbenes@suse.cz, live-patching@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18-5.10] livepatch: Match old_sympos 0 and 1 in klp_find_func()
Date: Thu,  4 Dec 2025 23:33:44 -0500	[thread overview]
Message-ID: <20251205043401.528993-3-sashal@kernel.org> (raw)
In-Reply-To: <20251205043401.528993-1-sashal@kernel.org>

From: Song Liu <song@kernel.org>

[ Upstream commit 139560e8b973402140cafeb68c656c1374bd4c20 ]

When there is only one function of the same name, old_sympos of 0 and 1
are logically identical. Match them in klp_find_func().

This is to avoid a corner case with different toolchain behavior.

In this specific issue, two versions of kpatch-build were used to
build livepatch for the same kernel. One assigns old_sympos == 0 for
unique local functions, the other assigns old_sympos == 1 for unique
local functions. Both versions work fine by themselves. (PS: This
behavior change was introduced in a downstream version of kpatch-build.
This change does not exist in upstream kpatch-build.)

However, during livepatch upgrade (with the replace flag set) from a
patch built with one version of kpatch-build to the same fix built with
the other version of kpatch-build, livepatching fails with errors like:

[   14.218706] sysfs: cannot create duplicate filename 'xxx/somefunc,1'
...
[   14.219466] Call Trace:
[   14.219468]  <TASK>
[   14.219469]  dump_stack_lvl+0x47/0x60
[   14.219474]  sysfs_warn_dup.cold+0x17/0x27
[   14.219476]  sysfs_create_dir_ns+0x95/0xb0
[   14.219479]  kobject_add_internal+0x9e/0x260
[   14.219483]  kobject_add+0x68/0x80
[   14.219485]  ? kstrdup+0x3c/0xa0
[   14.219486]  klp_enable_patch+0x320/0x830
[   14.219488]  patch_init+0x443/0x1000 [ccc_0_6]
[   14.219491]  ? 0xffffffffa05eb000
[   14.219492]  do_one_initcall+0x2e/0x190
[   14.219494]  do_init_module+0x67/0x270
[   14.219496]  init_module_from_file+0x75/0xa0
[   14.219499]  idempotent_init_module+0x15a/0x240
[   14.219501]  __x64_sys_finit_module+0x61/0xc0
[   14.219503]  do_syscall_64+0x5b/0x160
[   14.219505]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[   14.219507] RIP: 0033:0x7f545a4bd96d
...
[   14.219516] kobject: kobject_add_internal failed for somefunc,1 with
    -EEXIST, don't try to register things with the same name ...

This happens because klp_find_func() thinks somefunc with old_sympos==0
is not the same as somefunc with old_sympos==1, and klp_add_object_nops
adds another xxx/func,1 to the list of functions to patch.

Signed-off-by: Song Liu <song@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
[pmladek@suse.com: Fixed some typos.]
Reviewed-by: Petr Mladek <pmladek@suse.com>
Tested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Analysis

### 1. COMMIT MESSAGE ANALYSIS

**Subject:** `livepatch: Match old_sympos 0 and 1 in klp_find_func()`

**Key indicators:**
- Fixes a bug: livepatch upgrade failures with replace flag
- Real-world impact: sysfs duplicate filename error causing patch
  enablement to fail
- Clear problem description with error logs
- Tested-by: Petr Mladek
- Reviewed-by: Petr Mladek, Josh Poimboeuf

**Root cause:** Different versions of kpatch-build assign `old_sympos` 0
vs 1 for unique functions. During livepatch upgrade with replace,
`klp_find_func()` doesn't match them, leading to duplicate sysfs
entries.

### 2. CODE CHANGE ANALYSIS

**Files changed:** 1 file (`kernel/livepatch/core.c`)
**Lines changed:** 7 lines added, 1 line modified

**Change:**
```c
// Before:
if ((strcmp(old_func->old_name, func->old_name) == 0) &&
    (old_func->old_sympos == func->old_sympos)) {

// After:
if ((strcmp(old_func->old_name, func->old_name) == 0) &&
    ((old_func->old_sympos == func->old_sympos) ||
     (old_func->old_sympos == 0 && func->old_sympos == 1) ||
     (old_func->old_sympos == 1 && func->old_sympos == 0))) {
```

**Technical explanation:**
- For unique symbols, `old_sympos` 0 and 1 both refer to the first
  occurrence
- `klp_find_object_symbol()` treats `sympos == 0` as "unique symbol"
  (see lines 170-175)
- Sysfs displays `old_sympos == 0` as `1` (line 820: `func->old_sympos ?
  func->old_sympos : 1`)
- The fix makes `klp_find_func()` treat 0 and 1 as equivalent for
  matching

**Why this fixes the bug:**
- During replace upgrade, `klp_add_object_nops()` calls
  `klp_find_func()` to check if a function already exists
- Without the fix, `old_sympos==0` and `old_sympos==1` don't match
- This causes duplicate sysfs entries, leading to `-EEXIST` and patch
  enablement failure

### 3. CLASSIFICATION

**Type:** Bug fix (not a feature)

**Exception categories:** None needed — this is a bug fix

**Security:** No security impact, but prevents a reliability issue

### 4. SCOPE AND RISK ASSESSMENT

**Scope:**
- Single function (`klp_find_func()`)
- Localized change
- No architectural changes

**Risk:** Low
- Small, targeted change
- Clear logic
- No new code paths
- Only affects matching logic for unique symbols

**Potential issues:**
- None identified
- Change is conservative (adds equivalence, doesn't remove checks)

### 5. USER IMPACT

**Severity:** High for affected users
- Prevents livepatch upgrades with replace flag
- Causes kernel errors and patch enablement failure
- Affects users upgrading between different kpatch-build versions

**Affected users:**
- Users performing livepatch upgrades with replace
- Users mixing kpatch-build versions
- Enterprise users relying on livepatch for updates

**Impact assessment:**
- Core livepatch functionality (upgrade path)
- Real-world scenario (different toolchain versions)
- User-visible failure (error messages, failed upgrades)

### 6. STABILITY INDICATORS

**Testing:**
- Tested-by: Petr Mladek
- Reviewed-by: Petr Mladek, Josh Poimboeuf
- Real-world scenario documented

**Code maturity:**
- Function exists since atomic replace (Jan 2019)
- Present in stable trees (5.1+)
- Mature code path

### 7. DEPENDENCY CHECK

**Dependencies:**
1. `klp_find_func()` — introduced with atomic replace (commit
   e1452b607c48c, Jan 2019)
2. `klp_add_object_nops()` — same commit
3. Replace functionality — present since ~5.1

**Backport compatibility:**
- Applies cleanly to any stable tree with atomic replace
- No other commits required
- Self-contained fix

**Affected stable versions:**
- Any stable tree with atomic replace (~5.1+)
- All current LTS trees (6.1.y, 6.6.y, etc.)

### 8. STABLE KERNEL RULES COMPLIANCE

**Meets criteria:**
1. Obviously correct: Yes — clear equivalence for unique symbols
2. Fixes real bug: Yes — documented failure case
3. Important issue: Yes — breaks livepatch upgrades
4. Small and contained: Yes — 7 lines, 1 function
5. No new features: Yes — bug fix only
6. Applies cleanly: Yes — no conflicts expected

**No violations:**
- No new features
- No API changes
- No architectural changes
- No new dependencies

### 9. RISK VS BENEFIT TRADE-OFF

**Benefit:**
- Fixes upgrade failures
- Low risk, high value
- Addresses real user issue

**Risk:**
- Minimal — localized change
- Conservative logic
- Well-tested

**Conclusion:** Strong benefit, minimal risk

### 10. FINAL ASSESSMENT

This commit should be backported to stable kernel trees.

**Reasons:**
1. Fixes a real bug that breaks livepatch upgrades
2. Small, localized change (7 lines)
3. Low risk, clear logic
4. Well-tested and reviewed
5. No new features or dependencies
6. Applies cleanly to stable trees with atomic replace
7. High user impact for affected users

**Recommendation:** Backport to all stable trees that include atomic
replace functionality (approximately 5.1.y and later).

**YES**

 kernel/livepatch/core.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 0e73fac55f8eb..4e7a5cbc40a91 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -88,8 +88,14 @@ static struct klp_func *klp_find_func(struct klp_object *obj,
 	struct klp_func *func;
 
 	klp_for_each_func(obj, func) {
+		/*
+		 * Besides identical old_sympos, also consider old_sympos
+		 * of 0 and 1 are identical.
+		 */
 		if ((strcmp(old_func->old_name, func->old_name) == 0) &&
-		    (old_func->old_sympos == func->old_sympos)) {
+		    ((old_func->old_sympos == func->old_sympos) ||
+		     (old_func->old_sympos == 0 && func->old_sympos == 1) ||
+		     (old_func->old_sympos == 1 && func->old_sympos == 0))) {
 			return func;
 		}
 	}
-- 
2.51.0


           reply	other threads:[~2025-12-05  4:34 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <20251205043401.528993-1-sashal@kernel.org>]

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=20251205043401.528993-3-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=jikos@kernel.org \
    --cc=jpoimboe@kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=patches@lists.linux.dev \
    --cc=pmladek@suse.com \
    --cc=song@kernel.org \
    --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;
as well as URLs for NNTP newsgroup(s).