Skip to content

Fix build #53: Replace umount() with sys_umount() for kernel 4.9 - #31

Closed
Crybyte wants to merge 3 commits into
mainfrom
fix/build-53-sys-umount-fix
Closed

Fix build #53: Replace umount() with sys_umount() for kernel 4.9#31
Crybyte wants to merge 3 commits into
mainfrom
fix/build-53-sys-umount-fix

Conversation

@Crybyte

@Crybyte Crybyte commented Mar 28, 2026

Copy link
Copy Markdown
Owner

Automated fix for crDroid++ kernel build failure.

Issue: Build #52 failed with linker error:

aarch64-linux-gnu-ld: drivers/built-in.o: in function `ksu_umount_mnt':
.../core_hook.c:566: undefined reference to `umount'

Root Cause:

  • The ksu_umount_mnt() function in KernelSU-Next calls umount(pathname)
  • Kernel 4.9 doesn't have the umount() wrapper function - it uses sys_umount(path, flags)
  • The pre-patched core_hook.c.patched and existing fix scripts missed this replacement

Fix:

  1. Fixed core_hook.c.patched: Changed umount(pathname) to sys_umount(pathname, 0)
  2. Created fix_kernelsu_49_v38.py: Python script to replace umount() with sys_umount()
  3. Created fix_kernelsu_49_v39.py: Comprehensive fix with line-by-line analysis
  4. Updated workflow: Added v38 and v39 fix steps to the KernelSU-Next setup

Technical Details:

  • sys_umount() is the actual syscall in kernel 4.9 (not umount())
  • The flags parameter is set to 0 for standard umount behavior
  • Both Python scripts and sed fallback provide multiple fix paths

Related: Build #52 failed with undefined reference to umount

cc: @coderabbitai

Summary by CodeRabbit

  • Chores
    • Enhanced build workflow with additional kernel 4.9 compatibility fixes for KernelSU integration.
    • Added automated patching stages to address system call compatibility issues during the build process.
    • Improved fallback mechanisms to handle various kernel source configurations.

Oracle Public Cloud User added 3 commits March 28, 2026 13:25
Issue: The KernelSU Makefile unconditionally adds -DKSU_UMOUNT which forces

the code to use path_umount() that doesn't exist in kernel 4.9.

Previous fixes tried to replace path_umount with umount, but umount also

doesn't exist in kernel 4.9 (it's sys_umount, not exported for modules).

Fix: Remove -DKSU_UMOUNT from the Makefile so the code falls through to

the #else branch which returns -ENOSYS. This allows successful compilation.

The umount functionality won't work, but KernelSU root management will still

function correctly.

Build #51 failed with: undefined reference to 'umount'
…atibility

**Issue:** Build #52 failed with undefined reference to 'umount' in core_hook.c:566

**Root Cause:**
- The ksu_umount_mnt() function calls umount(pathname) which doesn't exist in kernel 4.9
- Kernel 4.9 uses sys_umount(path, flags) for the umount syscall
- The pre-patched core_hook.c.patched file and fix scripts were missing this replacement

**Fix Applied:**
1. Fixed core_hook.c.patched: Changed umount(pathname) to sys_umount(pathname, 0)
2. Created fix_kernelsu_49_v38.py: Python script to replace umount() with sys_umount()
3. Created fix_kernelsu_49_v39.py: Comprehensive fix for ksu_umount_mnt function
4. Updated workflow: Added v38 and v39 fix steps to the KernelSU-Next setup

**Testing:**
- The fix targets the exact line (566) that caused the linker error
- Uses sys_umount(pathname, 0) which is the correct syscall for kernel 4.9
- Both Python scripts and sed fallback are provided for robustness

Related: Build #52 failed with linker error - undefined reference to umount
cc: @coderabbitai
@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds three progressive KernelSU kernel 4.9 compatibility fix stages (v37–v39) to the build workflow and corresponding Python scripts. The stages remove the -DKSU_UMOUNT compiler flag, rewrite umount() calls to sys_umount(), and manage extern declarations for older kernels. A pre-patched core_hook.c serves as a reference implementation.

Changes

Cohort / File(s) Summary
Workflow Stages
.github/workflows/crdroid-plus-kernel-build.yml
Added three conditional KernelSU 4.9 fix stages (v37–v39) with script execution and inline sed fallbacks. Each stage includes file existence detection, location fallback logic (preferring build-scripts/, then repo root), and warning/verification steps. Inserted before existing verification checks.
Reference Patch
build-scripts/core_hook.c.patched
Updated ksu_umount_mnt() to call sys_umount(pathname, 0) instead of umount(pathname) when pathname is valid; error handling and cleanup logic unchanged.
Python Fixer Scripts
build-scripts/fix_kernelsu_49_v37.py, build-scripts/fix_kernelsu_49_v38.py, build-scripts/fix_kernelsu_49_v39.py
Three standalone Python scripts that programmatically apply KernelSU 4.9 compatibility patches. v37 removes -DKSU_UMOUNT from Makefiles and verifies core_hook.c structure. v38 replaces umount(...) calls with sys_umount(..., 0) via regex-based rewriting. v39 performs targeted umount replacement with conditional extern declaration insertion for kernels <4.10.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through kernel lands so wide,
Three fix scripts leap with skillful parse and pride,
We chase umount ghosts and flags they leave,
Rewriting calls that make the kernel breathe,
Patched and true, version four-point-nine believes! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and accurately summarizes the main technical change: replacing umount() with sys_umount() for kernel 4.9 compatibility, which is the core issue addressed across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/build-53-sys-umount-fix
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/build-53-sys-umount-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
build-scripts/core_hook.c.patched (1)

48-48: ⚠️ Potential issue | 🟡 Minor

Duplicate include: throne_tracker.h is included twice.

Lines 47 and 48 both include "throne_tracker.h". Remove the duplicate.

Proposed fix
 `#include` "throne_tracker.h"
-#include "throne_tracker.h"
 `#include` "kernel_compat.h"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/core_hook.c.patched` at line 48, Remove the duplicate include
of "throne_tracker.h": locate the two `#include` "throne_tracker.h" entries in the
file and delete one so the header is only included once (no other changes to
surrounding includes or functions such as any references to
ThroneTracker-related symbols).
.github/workflows/crdroid-plus-kernel-build.yml (1)

454-466: 🧹 Nitpick | 🔵 Trivial

Duplicate verification block.

Lines 454-466 and 475-489 both verify core_hook.c line 591. The second block (475-489) appears to be a duplicate with slightly different messaging. Consider consolidating into a single verification step.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/crdroid-plus-kernel-build.yml around lines 454 - 466,
There are two nearly identical verification blocks that inspect core_hook.c
using CORE_HOOK_FILE, sed and grep (the "Verifying core_hook.c" echo + sed/grep
logic); remove the duplicate block and consolidate into a single verification
step that performs the same checks and emits a single clear success/warning
message (keep the CORE_HOOK_FILE detection, sed/grep check for the incorrect
'flags' call site, and a single OK/WARNING echo).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/crdroid-plus-kernel-build.yml:
- Around line 428-438: The sed fallback replacing umount(...) when
fix_kernelsu_49_v38.py is absent is brittle: update the fallback around
CORE_HOOK_FILE and the two sed invocations so it (1) searches multiple candidate
locations (not just readlink -f drivers/kernelsu/core_hook.c) and warns if no
valid file is found, and (2) avoids replacing occurrences inside comments by
filtering out commented lines (e.g., skip lines starting with // or inside /*
*/) before applying the replacement; reference the fix_kernelsu_49_v38.py check,
CORE_HOOK_FILE variable, and the sed replacement invocations to locate and
harden this logic.

In `@build-scripts/fix_kernelsu_49_v37.py`:
- Around line 54-60: The current replace_flag inserts a "# ..." comment in the
middle of the ccflags-y line (pattern2), producing invalid Makefile syntax;
change replace_flag to remove the '-DKSU_UMOUNT' token entirely and preserve
spacing between the remaining parts (use match.group(1) and match.group(3) but
normalize/trim whitespace so there are no double spaces or a leading/trailing
space), then perform the re.sub as before and keep the same changes.append
message; update any logic around pattern2/re.sub to ensure the resultant
ccflags-y line remains a valid Makefile flags list.
- Around line 96-107: The current verification is too global; narrow the check
to ensure the fallback lives inside the ksu_umount_mnt preprocessor block by
locating the ksu_umount_mnt function/block first (search for the symbol
"ksu_umount_mnt" or its function signature) and then searching only within that
region for the '#else' token and either 'path_umount' or the 'TODO: umount for
non GKI kernel' string; implement this using a targeted regex or simple region
extraction (find start of the ksu_umount_mnt block and its matching end/closing
brace or preprocessor conditional) and only return True if the fallback markers
are present inside that region.
- Line 120: The print call uses an unnecessary f-string literal ("print(f\"===
KernelSU-Next 4.9 Compatibility Fix v37 ===\")"); remove the leading "f" so it
becomes a normal string literal or, if you intended to include dynamic data, add
the appropriate placeholder(s) and variables. Locate the print statement and
either drop the "f" prefix or replace it with formatted content referencing the
intended variables.

In `@build-scripts/fix_kernelsu_49_v38.py`:
- Line 74: The print statement using an unnecessary f-string should be changed
to a normal string literal: locate the print call that outputs "=== CRITICAL FIX
v38: Replacing umount() with sys_umount() ===" (in the top-level script code of
fix_kernelsu_49_v38.py) and remove the leading f prefix so it becomes a regular
print("=== CRITICAL FIX v38: Replacing umount() with sys_umount() ===").
- Around line 56-61: The current write-back uses f.write('\n'.join(lines)) which
can drop a trailing newline from the original file; before splitting into lines
capture whether the original content ended with a newline (e.g., record
original_content.endswith('\n')), and when writing back in the block that
handles fixed_count > 0 (around variables fixed_count, core_hook_file, lines)
append a single '\n' if the original ended with one so the file's ending newline
is preserved.
- Around line 46-54: The current loop only skips lines starting with '//' so
occurrences of umount(...) inside block comments (/* ... */) still get replaced;
modify the loop that processes lines (the code using re.search(...),
'sys_umount', lines[i], fixed_count) to track whether the current line is inside
a block comment by introducing a boolean flag (e.g., in_block_comment) that is
set when a '/*' is seen and cleared when a '*/' is seen, and skip the
replacement when in_block_comment is true; also handle single-line inline block
comments by checking if both '/*' and '*/' appear on the same line (do not set
the flag in that case) so replacements only run for code outside block comments.

In `@build-scripts/fix_kernelsu_49_v39.py`:
- Around line 47-52: The simple regex in func_pattern cannot handle nested
braces; instead of using r'(static int ksu_umount_mnt\(struct path
\*path\)\s*\{[^}]+\})' and relying on match, locate the function header with a
lightweight regex for "static int ksu_umount_mnt(struct path *path)\s*\{" then
from the header start iterate through content character-by-character counting
'{' and '}' until the brace count returns to zero to extract the full function
body (replace the current re.search + match path); update references that used
match to use the extracted function text so nested blocks are handled correctly.
- Line 115: The print call currently uses an unnecessary f-string: change
print(f"=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9
===") to a regular string by removing the leading 'f' (i.e., print("=== CRITICAL
FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")), so the literal
message is printed without misleading f-string usage.
- Around line 78-81: The loop overwrites the loop variable "line" with
"new_line" which is confusing and linter-unfriendly; instead, rename the
assigned variable (e.g., use "updated_line" or "output_line") and append that to
the output list rather than reusing "line", leaving the original "line" intact;
update occurrences near the brace_count check and the in_ksu_umount_mnt toggle
so they operate on the renamed variable ("new_line" -> "updated_line") when
appending while still using "line" for loop iteration, and ensure any later
logic referencing the appended value reads the renamed variable.
- Around line 80-81: Pre-split the input once (e.g., lines =
content.split('\n')) and iterate over lines by index to avoid repeated splitting
and O(n²) behavior; update brace_count by counting '{' and '}' in the current
line (not by inspecting lines[i-1]) and set in_ksu_umount_mnt = False when
brace_count reaches 0 after having been >0 (this reliably detects the end of the
function and avoids IndexError), and replace references to
content.split('\n')[i-1] with lines[i-1] when you legitimately need the previous
line.
- Around line 96-99: The declaration string uses "extern int sys_umount(...)"
but Linux 4.9 declares sys_umount as returning long; update the declaration
assembled in the variable named declaration to use "extern long sys_umount(const
char __user *name, int flags);" (so it matches the earlier search for
"asmlinkage long sys_umount" and the kernel headers) while keeping the
surrounding compatibility `#if/`#endif lines intact.

---

Outside diff comments:
In @.github/workflows/crdroid-plus-kernel-build.yml:
- Around line 454-466: There are two nearly identical verification blocks that
inspect core_hook.c using CORE_HOOK_FILE, sed and grep (the "Verifying
core_hook.c" echo + sed/grep logic); remove the duplicate block and consolidate
into a single verification step that performs the same checks and emits a single
clear success/warning message (keep the CORE_HOOK_FILE detection, sed/grep check
for the incorrect 'flags' call site, and a single OK/WARNING echo).

In `@build-scripts/core_hook.c.patched`:
- Line 48: Remove the duplicate include of "throne_tracker.h": locate the two
`#include` "throne_tracker.h" entries in the file and delete one so the header is
only included once (no other changes to surrounding includes or functions such
as any references to ThroneTracker-related symbols).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 42118065-6344-4d25-a253-d6787e58aa97

📥 Commits

Reviewing files that changed from the base of the PR and between c2c389e and 30d3de7.

📒 Files selected for processing (5)
  • .github/workflows/crdroid-plus-kernel-build.yml
  • build-scripts/core_hook.c.patched
  • build-scripts/fix_kernelsu_49_v37.py
  • build-scripts/fix_kernelsu_49_v38.py
  • build-scripts/fix_kernelsu_49_v39.py
📜 Review details
🧰 Additional context used
🪛 Ruff (0.15.7)
build-scripts/fix_kernelsu_49_v38.py

[warning] 35-35: Unnecessary mode argument

Remove mode argument

(UP015)


[warning] 46-48: Use a single if statement instead of nested if statements

(SIM102)


[warning] 65-65: Unnecessary else after return statement

Remove unnecessary else

(RET505)


[error] 74-74: f-string without any placeholders

Remove extraneous f prefix

(F541)

build-scripts/fix_kernelsu_49_v39.py

[warning] 18-18: Too many statements (51 > 50)

(PLR0915)


[warning] 40-40: Unnecessary mode argument

Remove mode argument

(UP015)


[warning] 78-78: for loop variable line overwritten by assignment target

(PLW2901)


[error] 115-115: f-string without any placeholders

Remove extraneous f prefix

(F541)

build-scripts/fix_kernelsu_49_v37.py

[warning] 37-37: Unnecessary mode argument

Remove mode argument

(UP015)


[warning] 55-55: Missing return type annotation for private function replace_flag

Add return type annotation: str

(ANN202)


[warning] 79-79: Unnecessary else after return statement

Remove unnecessary else

(RET505)


[warning] 93-93: Unnecessary mode argument

Remove mode argument

(UP015)


[error] 120-120: f-string without any placeholders

Remove extraneous f prefix

(F541)

🔇 Additional comments (1)
build-scripts/core_hook.c.patched (1)

583-584: sys_umount() expects a user-space pointer, but pathname is kernel-space.

sys_umount(const char __user *name, int flags) is the syscall entry point expecting user-space addresses. Calling it with pathname (a kernel-space pointer from dentry_path_raw) will likely fail address validation or cause undefined behavior.

For kernel 4.9 internal unmounting, consider using kern_path() + mnt_want_write() + do_umount() pattern, or verify if ksys_umount() is available which handles set_fs/get_fs internally.
[raise_critical_issue, request_verification]

#!/bin/bash
# Verify sys_umount signature and whether it can accept kernel-space pointers
# Check if ksys_umount or other alternatives exist in kernel 4.9

# Search for sys_umount declaration
rg -n "sys_umount" --type=c -C3 | head -50

# Check for ksys_umount availability  
ast-grep --pattern 'ksys_umount($$$)'

# Look for umount implementations in kernel headers
rg -n "^(asmlinkage|extern).*umount" --type=c --type-add 'c:*.h' | head -30

Comment on lines +428 to +438
else
echo "WARNING: fix_kernelsu_49_v38.py not found - applying direct sed fix..."
# Direct fix: replace umount(pathname) with sys_umount(pathname, 0)
CORE_HOOK_FILE=$(readlink -f drivers/kernelsu/core_hook.c 2>/dev/null || echo "")
if [ -n "$CORE_HOOK_FILE" ] && [ -f "$CORE_HOOK_FILE" ]; then
echo "Applying direct sed fix to $CORE_HOOK_FILE"
sed -i 's/\bumount(pathname)/sys_umount(pathname, 0)/g' "$CORE_HOOK_FILE"
sed -i 's/\bumount(mnt)/sys_umount(mnt, 0)/g' "$CORE_HOOK_FILE"
echo "Direct sed fix applied"
fi
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

sed fallback is less robust than the Python script it replaces.

When fix_kernelsu_49_v38.py is missing, the sed fallback has two limitations compared to the Python script:

  1. No comment filtering: sed blindly replaces umount(pathname) even in comments like // umount(pathname), while the Python script explicitly skips commented lines.

  2. Single path only: sed uses readlink -f drivers/kernelsu/core_hook.c which fails silently if the symlink doesn't exist or resolves incorrectly. The Python script searches multiple candidate paths.

Consider adding a warning or using a more robust fallback that checks multiple paths.

Suggested improvement for sed fallback
           else
             echo "WARNING: fix_kernelsu_49_v38.py not found - applying direct sed fix..."
-            # Direct fix: replace umount(pathname) with sys_umount(pathname, 0)
-            CORE_HOOK_FILE=$(readlink -f drivers/kernelsu/core_hook.c 2>/dev/null || echo "")
+            # Try multiple paths like the Python script does
+            CORE_HOOK_FILE=""
+            for p in "drivers/kernelsu/core_hook.c" "KernelSU/kernel/core_hook.c" "KernelSU-Next/kernel/core_hook.c"; do
+              if [ -f "$p" ]; then
+                CORE_HOOK_FILE="$p"
+                break
+              fi
+            done
             if [ -n "$CORE_HOOK_FILE" ] && [ -f "$CORE_HOOK_FILE" ]; then
               echo "Applying direct sed fix to $CORE_HOOK_FILE"
+              # Note: This doesn't skip comments unlike the Python script
               sed -i 's/\bumount(pathname)/sys_umount(pathname, 0)/g' "$CORE_HOOK_FILE"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/crdroid-plus-kernel-build.yml around lines 428 - 438, The
sed fallback replacing umount(...) when fix_kernelsu_49_v38.py is absent is
brittle: update the fallback around CORE_HOOK_FILE and the two sed invocations
so it (1) searches multiple candidate locations (not just readlink -f
drivers/kernelsu/core_hook.c) and warns if no valid file is found, and (2)
avoids replacing occurrences inside comments by filtering out commented lines
(e.g., skip lines starting with // or inside /* */) before applying the
replacement; reference the fix_kernelsu_49_v38.py check, CORE_HOOK_FILE
variable, and the sed replacement invocations to locate and harden this logic.

Comment on lines +54 to +60
pattern2 = r'^(ccflags-y\s*\+?=\s.*)(-DKSU_UMOUNT)(.*)$'
def replace_flag(match):
return f'{match.group(1)}# {match.group(2)} removed for kernel 4.9{match.group(3)}'

if re.search(pattern2, content, re.MULTILINE):
content = re.sub(pattern2, replace_flag, content, flags=re.MULTILINE)
changes.append("Removed -DKSU_UMOUNT from multi-flag ccflags-y line")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Pattern 2 replacement produces invalid Makefile syntax.

The replace_flag function at lines 55-56 produces malformed output. For input like:

ccflags-y += -DKSU_UMOUNT -Wsomething

The replacement would produce:

ccflags-y += # -DKSU_UMOUNT removed for kernel 4.9 -Wsomething

This places # comment mid-line before other flags, which is syntactically broken in Makefiles. The remaining -Wsomething becomes part of the comment.

Proposed fix: Remove the flag entirely instead of commenting
     # Pattern 2: Handle multiple flags on same line
     # ccflags-y += -DKSU_UMOUNT -Wsomething
-    pattern2 = r'^(ccflags-y\s*\+?=\s.*)(-DKSU_UMOUNT)(.*)$'
-    def replace_flag(match):
-        return f'{match.group(1)}# {match.group(2)} removed for kernel 4.9{match.group(3)}'
+    pattern2 = r'-DKSU_UMOUNT\s*'
 
-    if re.search(pattern2, content, re.MULTILINE):
-        content = re.sub(pattern2, replace_flag, content, flags=re.MULTILINE)
+    if re.search(pattern2, content):
+        content = re.sub(pattern2, '', content)
         changes.append("Removed -DKSU_UMOUNT from multi-flag ccflags-y line")
🧰 Tools
🪛 Ruff (0.15.7)

[warning] 55-55: Missing return type annotation for private function replace_flag

Add return type annotation: str

(ANN202)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v37.py` around lines 54 - 60, The current
replace_flag inserts a "# ..." comment in the middle of the ccflags-y line
(pattern2), producing invalid Makefile syntax; change replace_flag to remove the
'-DKSU_UMOUNT' token entirely and preserve spacing between the remaining parts
(use match.group(1) and match.group(3) but normalize/trim whitespace so there
are no double spaces or a leading/trailing space), then perform the re.sub as
before and keep the same changes.append message; update any logic around
pattern2/re.sub to ensure the resultant ccflags-y line remains a valid Makefile
flags list.

Comment on lines +96 to +107
# Check if there's a fallback implementation for non-KSU_UMOUNT case
if '#else' in content and 'path_umount' in content:
print("INFO: core_hook.c has both KSU_UMOUNT and fallback paths - good")
return True

# Check for the TODO comment which indicates the fallback
if 'TODO: umount for non GKI kernel' in content:
print("INFO: core_hook.c has the TODO fallback comment - will use -ENOSYS")
return True

print("WARNING: core_hook.c structure unknown - may still fail")
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Verification logic may produce false positives.

The check at lines 97-107 looks for '#else' in content and 'path_umount' in content independently. These strings could appear anywhere in the file (in comments, different functions, etc.) and don't guarantee a proper fallback exists for the specific ksu_umount_mnt code path.

Consider a more targeted check that verifies the #else is specifically within the ksu_umount_mnt function's preprocessor block.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v37.py` around lines 96 - 107, The current
verification is too global; narrow the check to ensure the fallback lives inside
the ksu_umount_mnt preprocessor block by locating the ksu_umount_mnt
function/block first (search for the symbol "ksu_umount_mnt" or its function
signature) and then searching only within that region for the '#else' token and
either 'path_umount' or the 'TODO: umount for non GKI kernel' string; implement
this using a targeted regex or simple region extraction (find start of the
ksu_umount_mnt block and its matching end/closing brace or preprocessor
conditional) and only return True if the fallback markers are present inside
that region.

print("Usage: KERNEL_DIR=/path/to/kernel python3 fix_kernelsu_49_v37.py [kernel_dir]")
sys.exit(1)

print(f"=== KernelSU-Next 4.9 Compatibility Fix v37 ===")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

f-string without placeholders.

Line 120 uses an f-string but contains no placeholders.

Proposed fix
-    print(f"=== KernelSU-Next 4.9 Compatibility Fix v37 ===")
+    print("=== KernelSU-Next 4.9 Compatibility Fix v37 ===")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(f"=== KernelSU-Next 4.9 Compatibility Fix v37 ===")
print("=== KernelSU-Next 4.9 Compatibility Fix v37 ===")
🧰 Tools
🪛 Ruff (0.15.7)

[error] 120-120: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v37.py` at line 120, The print call uses an
unnecessary f-string literal ("print(f\"=== KernelSU-Next 4.9 Compatibility Fix
v37 ===\")"); remove the leading "f" so it becomes a normal string literal or,
if you intended to include dynamic data, add the appropriate placeholder(s) and
variables. Locate the print statement and either drop the "f" prefix or replace
it with formatted content referencing the intended variables.

Comment on lines +46 to +54
if re.search(r'\bumount\s*\([^)]+\)', line) and not line.strip().startswith('//'):
# Check if it's already sys_umount
if 'sys_umount' not in line:
print(f"Line {i+1} BEFORE: {line.strip()}")
# Replace umount(arg) with sys_umount(arg, 0)
new_line = re.sub(r'\bumount\s*\(\s*([^)]+)\s*\)', r'sys_umount(\1, 0)', line)
lines[i] = new_line
fixed_count += 1
print(f"Line {i+1} AFTER: {new_line.strip()}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Block comments (/* ... */) are not handled; only // comments are skipped.

The check not line.strip().startswith('//') only catches single-line comments. If umount(...) appears inside a /* ... */ block comment spanning multiple lines, it will still be replaced, potentially corrupting comment content.

Proposed enhancement to track block comments
     fixed_count = 0
+    in_block_comment = False
     for i, line in enumerate(lines):
+        # Track block comment state
+        if '/*' in line and '*/' not in line:
+            in_block_comment = True
+        if '*/' in line:
+            in_block_comment = False
+            
         # Match umount(pathname) or umount(mnt) or umount(any_variable)
         # but NOT comments or string literals
-        if re.search(r'\bumount\s*\([^)]+\)', line) and not line.strip().startswith('//'):
+        if re.search(r'\bumount\s*\([^)]+\)', line) and not line.strip().startswith('//') and not in_block_comment:
             # Check if it's already sys_umount
             if 'sys_umount' not in line:
🧰 Tools
🪛 Ruff (0.15.7)

[warning] 46-48: Use a single if statement instead of nested if statements

(SIM102)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v38.py` around lines 46 - 54, The current loop
only skips lines starting with '//' so occurrences of umount(...) inside block
comments (/* ... */) still get replaced; modify the loop that processes lines
(the code using re.search(...), 'sys_umount', lines[i], fixed_count) to track
whether the current line is inside a block comment by introducing a boolean flag
(e.g., in_block_comment) that is set when a '/*' is seen and cleared when a '*/'
is seen, and skip the replacement when in_block_comment is true; also handle
single-line inline block comments by checking if both '/*' and '*/' appear on
the same line (do not set the flag in that case) so replacements only run for
code outside block comments.

Comment on lines +47 to +52
func_pattern = r'(static int ksu_umount_mnt\(struct path \*path\)\s*\{[^}]+\})'

match = re.search(func_pattern, content, re.DOTALL)
if not match:
print("WARNING: Could not find ksu_umount_mnt function with simple pattern")
print("Trying alternative approach...")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Regex pattern [^}]+ cannot match functions with nested braces.

The pattern r'(static int ksu_umount_mnt\(struct path \*path\)\s*\{[^}]+\})' uses [^}]+ which stops at the first }. If ksu_umount_mnt contains any if/for/while blocks (which it does), the regex won't capture the full function body.

The fallback at lines 54-85 handles this, but the regex match path would produce incorrect results if it ever matched.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v39.py` around lines 47 - 52, The simple regex
in func_pattern cannot handle nested braces; instead of using r'(static int
ksu_umount_mnt\(struct path \*path\)\s*\{[^}]+\})' and relying on match, locate
the function header with a lightweight regex for "static int
ksu_umount_mnt(struct path *path)\s*\{" then from the header start iterate
through content character-by-character counting '{' and '}' until the brace
count returns to zero to extract the full function body (replace the current
re.search + match path); update references that used match to use the extracted
function text so nested blocks are handled correctly.

Comment on lines +78 to +81
line = new_line

if brace_count == 0 and '{' in content.split('\n')[i-1] if i > 0 else False:
in_ksu_umount_mnt = False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Loop variable line is overwritten, causing confusion.

At line 78, line = new_line overwrites the loop variable. While functionally correct here (since it's immediately appended), this is flagged by linters as error-prone. Use a different variable name.

Proposed fix
                 if new_line != line:
                     print(f"  -> {new_line.strip()}")
-                    line = new_line
+                    fixed_line = new_line
+                else:
+                    fixed_line = line
 
-            fixed_lines.append(line)
+            fixed_lines.append(fixed_line if 'fixed_line' in dir() else line)

Or more simply:

-                if new_line != line:
-                    print(f"  -> {new_line.strip()}")
-                    line = new_line
-
-            fixed_lines.append(line)
+                if new_line != line:
+                    print(f"  -> {new_line.strip()}")
+                    fixed_lines.append(new_line)
+                else:
+                    fixed_lines.append(line)
+            else:
+                fixed_lines.append(line)
🧰 Tools
🪛 Ruff (0.15.7)

[warning] 78-78: for loop variable line overwritten by assignment target

(PLW2901)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v39.py` around lines 78 - 81, The loop
overwrites the loop variable "line" with "new_line" which is confusing and
linter-unfriendly; instead, rename the assigned variable (e.g., use
"updated_line" or "output_line") and append that to the output list rather than
reusing "line", leaving the original "line" intact; update occurrences near the
brace_count check and the in_ksu_umount_mnt toggle so they operate on the
renamed variable ("new_line" -> "updated_line") when appending while still using
"line" for loop iteration, and ensure any later logic referencing the appended
value reads the renamed variable.

Comment on lines +80 to +81
if brace_count == 0 and '{' in content.split('\n')[i-1] if i > 0 else False:
in_ksu_umount_mnt = False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inefficient and confusing brace-tracking logic with potential IndexError.

Line 80 calls content.split('\n')[i-1] inside the loop, which re-splits the entire content on every iteration (O(n²) complexity). Also, when i == 0, the condition evaluates to False but the access content.split('\n')[-1] would still occur in some Python evaluation orders (though the ternary prevents it here).

The logic for detecting function end is also unclear—checking for { in the previous line doesn't reliably indicate function boundaries.

Suggested fix: track function scope properly
-            if brace_count == 0 and '{' in content.split('\n')[i-1] if i > 0 else False:
-                in_ksu_umount_mnt = False
+            # End function tracking when brace count returns to 0 after entering
+            if in_ksu_umount_mnt and brace_count == 0 and i > 0:
+                in_ksu_umount_mnt = False
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v39.py` around lines 80 - 81, Pre-split the
input once (e.g., lines = content.split('\n')) and iterate over lines by index
to avoid repeated splitting and O(n²) behavior; update brace_count by counting
'{' and '}' in the current line (not by inspecting lines[i-1]) and set
in_ksu_umount_mnt = False when brace_count reaches 0 after having been >0 (this
reliably detects the end of the function and avoids IndexError), and replace
references to content.split('\n')[i-1] with lines[i-1] when you legitimately
need the previous line.

Comment on lines +96 to +99
declaration = '\n/* Kernel 4.9 compatibility: sys_umount declaration */\n'
declaration += '#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)\n'
declaration += 'extern int sys_umount(const char __user *name, int flags);\n'
declaration += '#endif\n'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check sys_umount signature in kernel sources
rg -n "sys_umount" --type=c --type-add 'c:*.h' -C2 | grep -E "(asmlinkage|extern|long|int).*sys_umount" | head -20

Repository: Crybyte/droidspaces-build

Length of output: 217


🏁 Script executed:

cat -n build-scripts/fix_kernelsu_49_v39.py | head -110 | tail -30

Repository: Crybyte/droidspaces-build

Length of output: 1436


🌐 Web query:

Linux 4.9 sys_umount syscall return type signature

💡 Result:

The sys_umount syscall in Linux 4.9 has the return type signature asmlinkage long sys_umount(char user *name, int flags);. This is the kernel-internal prototype declared in include/linux/syscalls.h and implemented in fs/namespace.c. The return type is long, which is the standard for syscall return values in Linux (negative values indicate errors). This signature has been consistent since at least Linux 2.6 and remains the same in modern kernels.

Citations:


🌐 Web query:

sys_umount asmlinkage long int kernel 4.9

💡 Result:

In Linux kernel 4.9, sys_umount is the system call handler for the umount(2) syscall. It is declared as 'asmlinkage long sys_umount(char user *name, int flags);' in include/linux/syscalls.h. The implementation is in fs/namespace.c, where it calls the internal do_umount function to perform the unmount operation on the specified mountpoint. The 'asmlinkage' attribute ensures arguments are passed via the stack for compatibility with the kernel's system call entry mechanism, particularly important on architectures like x86-32. For 32-bit x86 in kernel 4.9, syscall number 52 corresponds to sys_umount (umount2). The function handles flags like MNT_FORCE and MNT_DETACH for forced and lazy unmounts.

Citations:


Use long return type for sys_umount declaration, not int.

The declaration on line 98 uses extern int sys_umount(...) but Linux 4.9's sys_umount syscall is declared as asmlinkage long sys_umount(...) in kernel headers. Change line 98 to:

extern long sys_umount(const char __user *name, int flags);

This is inconsistent with the check on line 88 which searches for 'asmlinkage long sys_umount'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v39.py` around lines 96 - 99, The declaration
string uses "extern int sys_umount(...)" but Linux 4.9 declares sys_umount as
returning long; update the declaration assembled in the variable named
declaration to use "extern long sys_umount(const char __user *name, int flags);"
(so it matches the earlier search for "asmlinkage long sys_umount" and the
kernel headers) while keeping the surrounding compatibility `#if/`#endif lines
intact.

if len(sys.argv) > 1:
kernel_dir = sys.argv[1]

print(f"=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

f-string without placeholders.

Line 115 uses an f-string but contains no placeholders.

Proposed fix
-    print(f"=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")
+    print("=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
print(f"=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")
print("=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix for kernel 4.9 ===")
🧰 Tools
🪛 Ruff (0.15.7)

[error] 115-115: f-string without any placeholders

Remove extraneous f prefix

(F541)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@build-scripts/fix_kernelsu_49_v39.py` at line 115, The print call currently
uses an unnecessary f-string: change print(f"=== CRITICAL FIX v39: Comprehensive
ksu_umount_mnt fix for kernel 4.9 ===") to a regular string by removing the
leading 'f' (i.e., print("=== CRITICAL FIX v39: Comprehensive ksu_umount_mnt fix
for kernel 4.9 ===")), so the literal message is printed without misleading
f-string usage.

@Crybyte

Crybyte commented Mar 30, 2026

Copy link
Copy Markdown
Owner Author

Closing - cleaning up failed automated build experiment. Will retry with cleaner approach.

@Crybyte Crybyte closed this Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant