Repository navigation
Conversation
Owner
|
only the first commit is relevant here right? |
Author
Hi @diabl0w, thanks for reviewing! Actually, all 7 commits are relevant and intentionally included here. While the first commit (the SELinux enforcement fix in lkm/dfroot.c) is the core change, the remaining six commits are targeted fixes for other reliability issues found in the native code, assembly macros, app resource management, and the Makefile. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR collects seven fixes for the LKM and the exploit code. The main change corrects the SELinux enforcement detection in
lkm/dfroot.c: the existingselinux_statereadback can make the module treat an enforcing system as permissive, which skips theavc_has_permfallback patches exactly on the kernels that need them. The remaining commits harden error handling in the native code, fix two assembly macros, close an IpSec resource leak in the app, and make the LKM Makefile tolerate an unsetOBJCOPY.Changes
SELinux enforcement detection (
lkm/dfroot.c)The module writes
falseto the first member ofstruct selinux_stateand reads the value back to decide whether theavc_has_permpatches can be skipped. That member isenforcingonly whenCONFIG_SECURITY_SELINUX_DEVELOPis enabled. On kernels built without it the write lands on an unrelated bool such ascheckreqprotand changes nothing, while the readback still returnsfalse, so the module concludes SELinux is permissive and skips the patches even though the system is still enforcing. On such devices the rooting flow then fails through plain AVC denials.The module now verifies the real state through the selinuxfs node
/sys/fs/selinux/enforce, read withfilp_open,kernel_read, andfilp_closeresolved through kallsyms. The patches are skipped only when that node reads back0. If any of the symbols is missing or the read fails, the module assumes enforcing and keeps the fallback patches, so the failure mode stays conservative. This keeps the intent of #172 — do not leaveavc_has_permpatched while the system enforces (for example after a SU manager restores enforce=1) — but bases the decision on the state SELinux actually reports instead of a struct layout assumption.XFRM sender port validation (
app/src/main/jni/exp.c)patch_file_cbc()only logged a failedbind()of the sender socket and kept going. The xfrm state matches on that source port, so with the bind missing every encapsulated write was silently dropped and the CBC patching failed without a meaningful error, which could be mistaken for a device that is not vulnerable. A failed bind now closes the socket and aborts that path with an error.setup()also rejects out-of-range port arguments up front.Process handling and property parsing (
app/src/main/jni/exp.c)spawn_crash_dump()now checks thewaitpid()result; on failure it returns an error instead of reporting an exit status of 0.getpropfallback inread_device_versions()checks thepopen()andfgets()results, strips a trailing newline from the property value, and rejects empty values instead of parsing them into a bogus release string. The release string is assembled withsnprintf()into an adequately sized buffer instead ofsprintf()concatenation on a fixed 15-byte buffer.ELF parser reliability (
app/src/main/jni/elf_parser.c)Adds the missing
<stdint.h>include and keeps theread()return value when fetching section and symbol names. The name buffers are terminated at the number of bytes actually read (name[n] = 0) instead of at the last byte of the buffer, so a short read no longer leaves uninitialized stack bytes between the data and the terminator.Assembly stack macros (
app/src/main/jni/include.inc)pushusedstr \Rn, [sp, -16], which stores below the stack pointer without moving it, so consecutive pushes overwrite the same slot. It now uses the pre-indexed writeback formstr \Rn, [sp, #-16]!.popreferenced\Rnalthough the macro parameter is namedR, and the post-index offset was missing the#prefix. It is nowldr \R, [sp], #16, which pairs correctly with the fixedpush.IpSec resource management (
app/src/main/java/df/root/ExploitRunner.java)If
buildTransportModeTransform()failed, the already allocatedSecurityParameterIndexand the UDP encapsulation socket leaked: they were only released around the native call, never around the setup that could throw in between. Every resource is now released in its ownfinallyblock, so a transform setup failure still closes the SPI and the encapsulation socket.LKM Makefile (
lkm/Makefile)The
objcopyinvocation is now wrapped inifdef OBJCOPY. WithOBJCOPYempty the recipe previously produced a command line starting with--strip-unneeded, which the shell cannot execute, aborting the build with Error 127. WithOBJCOPYconfigured the behavior is unchanged; without it the strip step is simply skipped instead of failing the build.Testing
GitHub Actions
The
Buildworkflow ran on7886c19, the exact head of this branch:https://github.com/hexlo404/DFRoot/actions/runs/41679234552
Result: success. All eight KMI variants built (
android12-5.10,android13-5.10,android13-5.15,android14-5.15,android14-6.1,android15-6.6,android16-6.12,android17-6.18), and the APK job completed its 14-step sequence (the GitHub Release step only runs on tag pushes and was skipped as designed), producing the signed release APK. The run generated nine artifacts in total: the eightdfroot.kovariants and the APK.Device test
I manually tested this on a physical Samsung Galaxy S23 running Android 14 (kernel
5.15.94,android13-5.15KMI): the tool ran through, reported success, and completed its expected operation. This is a single-device manual test on real hardware, not a CI result, and I am not generalizing it to other Samsung models.Impact
struct selinux_statelayout; it reflects what selinuxfs reports.getpropvalues are handled.OBJCOPYis unset.