You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
No injection after a KernelSU emulated soft reboot spawns a duplicate daemon #878
changed the title [-]The latest version (v2.2-3080-88f8e1fa) cannot be injected in the HyperOS (Redmi K80 Pro) + Zygisk Next environment; both the parasite manager and Hook functions are disabled (v2.1 works normally).[/-][+] No injection under exploit-gained KernelSU jailbreak root[/+]on Aug 6, 2026
I tried reinstalling the latest version of Vector and performing a soft reboot four times to reproduce the original problem. Each of these four tests yielded different results. The first two times, Vector crashed and failed to inject into the system framework. The third time, the DEX optimizer wrapper failed to mount. The fourth time, the problem reappeared after the reboot; Vector could not be opened. The logs should contain most of the logs from my tests from this morning to this afternoon.
Let us enable only (Neo)Zygisk and Vector, do a full reboot, trigger Vector Action button, and then upload the whole folder /data/adb/lspd/log as logs (you have pack it in .zip by your own.)
Let us enable only (Neo)Zygisk and Vector, do a full reboot, trigger Vector Action button, and then upload the whole folder /data/adb/lspd/log as logs (you have pack it in .zip by your own.)
I understand, but I can only perform the following steps:
Uninstall the existing Vector
Perform a hardware reboot
Re-execute the vulnerability to jailbreak
Install Vector
Perform a soft reboot to make Vector effective
If I don't do this, a hardware reboot will cause the KSU jailbreak to disappear.
Can this solution find the problem?
Yes, please do as you suggest. And remember to pack the logs for uploading.
I have followed the procedure. The current situation is:
After a hardware reboot, reinstalling Vector and Vector runs normally.
However, a subsequent soft reboot causes the aforementioned problem.
The logs are attached; they should contain details of my two reboot attempts. The first reboot was normal, but the subsequent soft reboot caused the problem.
changed the title [-] No injection under exploit-gained KernelSU jailbreak root[/-][+]No injection after a KernelSU emulated soft reboot spawns a duplicate daemon[/+]on Aug 6, 2026
Thanks, these logs are exactly what was needed. Root cause is clear now.
The trigger is KernelSU's emulated soft reboot. It doesn't reboot the kernel — it runs stop, replays post-fs-data and services, then start. That tears down and respawns zygote (which is why NeoZygisk re-injects correctly), but it also re-runs every module's service.sh, including Vector's. The existing Vector daemon is a detached process, so stop doesn't kill it, and it has no idea a second service.sh was just fired. The result is two daemons: the survivor from the previous boot and a fresh one. Both claim the same rendezvous service, forward transactions to each other, and one crashes on a stack overflow. No framework gets injected, so the manager opens into the shell warning.
This also matches what you saw: the first soft reboot after installing works because there's no prior daemon; every soft reboot after that collides with the one already running.
It is hard to find a solution, you will have to wait.
Currently, the only workaround for you, is to avoid soft-reboot from KernelSU
Why did some previous versions seem to have no problem? But overall, the issue isn't serious. Now that we know the cause, we can use the following temporary solution: disable vector in ksu, then perform a soft reboot, and then enable vector again and perform another soft reboot. This only requires an extra soft reboot.
@RMDycz If you have some working version, please share the link and the logs generated by that build, it will help us to solve this in new versions of Vector.
@RMDycz If you have some working version, please share the link and the logs generated by that build, it will help us to solve this in new versions of Vector.
Okay, the Vector v2.1 (3076-1e595f3c-HSSkyBoy) version I mentioned before also has the same problem. However, I can confirm that Vector 2.0 Mar 23 version does not have this issue because I have been using this version for a considerable period of time.
@RMDycz If you have some working version, please share the link and the logs generated by that build, it will help us to solve this in new versions of Vector.
This could also be an issue with the KSU update, because the KSU version I was using before was an older one, probably the May version of Vector and the May version of KSU. It might take some time to test the versions to find out exactly where the problem lies.
Based on our discussion, I made a KSU module as a temporary workaround until PR #914 is merged, for those who want to use Vector with a late-loaded KSU. It uses the emulated-soft-reboot hook to kill the previous vectord process whenever a soft reboot is performed.
After a soft reboot, the global dex2oat bind mount remains in place. The new vectord then treats the already-wrapped path as the stock dex2oat, so once dexopt is triggered, the wrapper ends up recursively execing itself.
Based on our discussion, I made a KSU module as a temporary workaround until PR #914 is merged, for those who want to use Vector with a late-loaded KSU. It uses the emulated-soft-reboot hook to kill the previous vectord process whenever a soft reboot is performed.
Based on our discussion, I made a KSU module as a temporary workaround until PR #914 is merged, for those who want to use Vector with a late-loaded KSU. It uses the emulated-soft-reboot hook to kill the previous vectord process whenever a soft reboot is performed. vector-soft-reboot-guard-v0.1.0.zip
I rebuilt vector with 914 applied, and it didn't work for me. Any info can provide? (Pixel 10, Root My Pixel)
I think the implementation in #914 is still not quite correct. As I mentioned above, stale dex2oat bind mounts can still remain after a soft reboot.
I've added some additional cleanup logic to the KSU module. You can use an official Vector build without #914 together with this updated module to verify whether the issue is fixed.
Note: The first soft reboot after installing this module only activates it. You'll need to perform one more soft reboot to clean up the stale state and verify whether vectord restarts normally.
I think the implementation in #914 is still not quite correct. As I mentioned above, stale dex2oat bind mounts can still remain after a soft reboot.
I've added some additional cleanup logic to the KSU module. You can use an official Vector build without #914 together with this updated module to verify whether the issue is fixed.
Note: The first soft reboot after installing this module only activates it. You'll need to perform one more soft reboot to clean up the stale state and verify whether vectord restarts normally.
Hi! I used the soft reboot guard you've attached, but sadly it doesn't really do anything
@H3XDaemon your solution works fine on samsung, i had to include small change., after soft reboot trying to install any app causes system crash.
1789994679.653 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
1789994679.643 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
1789994679.634 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
setenforce 0 , makes vectord to umount dex2oat [https://github.com/JingMatrix/Vector/blob/master/daemon/src/main/kotlin/org/matrix/vector/daemon/env/Dex2OatServer.kt#L86] , fixing the crash
emulated-soft-reboot.sh
pids=$(pgrep -f '^vectord')
if [ -n "$pids" ]; then
setenforce 0
sleep 1
kill -9 $pids
setenforce 1
fi
I opened #1012, building on H3XDaemon's pre-stop hook and ManiaciaChao's stale compiler-mount diagnosis. It handles both the surviving daemon and its mounts, including first-update post-fs-data cleanup, without relying on the process name or toggling SELinux.
It includes the complete script-level lifecycle change, applies directly to master, and does not depend on #914 or #1008. It overlaps #914; the separate compiler recursion guards from #1008 are not included.
It includes 24 Linux integration tests (passing with dash, BusyBox and mksh). The same four production scripts were observed through one successful Android 12 cycle; validation details and limits are in the PR.
The stage does run here — our emulated-soft-reboot.sh writes a line to a file, and the timestamps line up with a real ksud soft-reboot. (/dev/kmsg is useless for this: the soft reboot's own burst rotates the ring buffer within seconds.)
Three things I did not see above:
KernelSU applies module mounts once per load, not per soft reboot. A module installed while late-loaded is not mounted by a later ksud soft-reboot: the scripts are replayed, the overlay is not re-created. We watched this with a module of ours that ships a permission XML and an overlay library — after ksud post-fs-data (and after a soft reboot) the files were still absent from /system, /proc/1/mountinfo had no matching entry, and that module's own post-fs-data.sh had clearly run. So the "the first soft reboot after installing only activates it" note above is not a quirk of that particular module — it is how the mount stage behaves. Anything that has to be live sooner must be brought in by hand (mount --bind), which is how we ended up testing it.
On this firmware ksud soft-reboot is not a safe way to get Vector back up, even with the duplicate handled. Our last attempt had system_server come up before the APEX-provided android.ext.services package was resolvable (Required services extension package is missing ... android.ext.services), crash-loop, and Rescue Party reboot the device — losing root, since a late-loaded LKM does not survive a real reboot. What we do instead: start vectord first (it claims the serial proxy name early), then start Zygisk Next and let its zygote restart hand the new system_server to the waiting daemon. That is KernelSU-side rather than Vector-side, but it is why "just avoid the soft reboot" is a cheap workaround on a normal device and an expensive one here.
A three-line guard for the case where the KernelSU stage does not exist (Magisk, APatch) or does not run. Starting a second daemon is what creates the collision, and service.sh can notice that one is already alive: if pgrep -f '^vectord' >/dev/null 2>&1; then exit 0; fi. Anchored, because app_process sets the nice name in argv only — comm stays main, so pkill vectord matches nothing, while an unanchored pattern matches any shell whose command line happens to contain the word.
What a daemon restart leaves behind when system_server is already running — a permanently false "not injected" state with no repair path — is filed separately: #1015.
I opened #1017 for the daemon-restart gap described here and in #1015. It re-registers an already injected system_server through the existing bridge, restores loaded modern modules’ IPC/preferences and hot-reload targets, and derives manager status from the live registration. It does not rerun module entry points or reinstall hooks. Native startup also waits for a successful registration handshake rather than accepting an unrelated binder at the proxy name.
This complements #1012’s daemon/compiler-mount cleanup and applies directly to master. #1018 separately releases consumed hot-reload resources and retired callbacks. The three changes also compile and pass their regression suites together.
An Android 12/NeoZygisk local validation build passed daemon replacements with unchanged system_server/zygote PID and start times, then a KernelSU emulated soft reboot followed by application and hot-reload tests. Clean PR sources were compiled separately. I have not reproduced the locked-bootloader LKM setup; these changes do not restore external overlays or fix the reported APEX/extension-package failure.
Could you guys try latest CI builds of NeoZygisk and Vector ? In the local device tests, the late-load mode (jailbreak) and soft reboot are well supported by them now.
Tried 3114 (eaffc81) on SM-S9280, KernelSU 3.2.5 LKM late-load, Zygisk Next 1.5.1 (not NeoZygisk).
Release build: from the second soft reboot on, service.sh still starts a second daemon that gets past tryLock(), ping-pongs with the old one and dies with StackOverflowError. No injection in all 5 of those rounds. The Debug build of the same commit works: the new daemon exits at the lock check and the old one re-injects, 3 of 3.
R8 drops the stores to FileSystem.lockChannel and fileLock in release. tryLock() is inlined into main and there is no sput-object for either field, while the debug dex has both. The channel only lives in a register, gets collected, its fd is closed and the lock goes with it. A running release daemon has nothing in /proc/locks; the debug one held the lock for the 30+ minutes I watched.
The template asks for the debug build, which is probably why it looks fixed in local tests.
Reading the fields somewhere is enough to keep them, e.g. a releaseLock() called from a shutdown hook. I can change #914 to do that.
Activity
JingMatrix commentedon Aug 6, 2026
Please upload the log folder as indicated in #123.
[-]The latest version (v2.2-3080-88f8e1fa) cannot be injected in the HyperOS (Redmi K80 Pro) + Zygisk Next environment; both the parasite manager and Hook functions are disabled (v2.1 works normally).[/-][+] No injection under exploit-gained KernelSU jailbreak root[/+]RMDycz commentedon Aug 6, 2026
@JingMatrix
JingMatrix commentedon Aug 6, 2026
Let us enable only (Neo)Zygisk and Vector, do a full reboot, trigger Vector Action button, and then upload the whole folder
/data/adb/lspd/logas logs (you have pack it in.zipby your own.)RMDycz commentedon Aug 6, 2026
I understand, but I can only perform the following steps:
Uninstall the existing Vector
Perform a hardware reboot
Re-execute the vulnerability to jailbreak
Install Vector
Perform a soft reboot to make Vector effective
If I don't do this, a hardware reboot will cause the KSU jailbreak to disappear.
Can this solution find the problem?
JingMatrix commentedon Aug 6, 2026
Yes, please do as you suggest. And remember to pack the logs for uploading.
RMDycz commentedon Aug 6, 2026
I have followed the procedure. The current situation is:
After a hardware reboot, reinstalling Vector and Vector runs normally.
However, a subsequent soft reboot causes the aforementioned problem.
The logs are attached; they should contain details of my two reboot attempts. The first reboot was normal, but the subsequent soft reboot caused the problem.
vector_logs.zip
[-] No injection under exploit-gained KernelSU jailbreak root[/-][+]No injection after a KernelSU emulated soft reboot spawns a duplicate daemon[/+]JingMatrix commentedon Aug 6, 2026
Thanks, these logs are exactly what was needed. Root cause is clear now.
The trigger is KernelSU's emulated soft reboot. It doesn't reboot the kernel — it runs
stop, replayspost-fs-dataandservices, thenstart. That tears down and respawns zygote (which is why NeoZygisk re-injects correctly), but it also re-runs every module'sservice.sh, including Vector's. The existing Vector daemon is a detached process, sostopdoesn't kill it, and it has no idea a secondservice.shwas just fired. The result is two daemons: the survivor from the previous boot and a fresh one. Both claim the same rendezvous service, forward transactions to each other, and one crashes on a stack overflow. No framework gets injected, so the manager opens into the shell warning.This also matches what you saw: the first soft reboot after installing works because there's no prior daemon; every soft reboot after that collides with the one already running.
JingMatrix commentedon Aug 6, 2026
It is hard to find a solution, you will have to wait.
Currently, the only workaround for you, is to avoid soft-reboot from KernelSU
RMDycz commentedon Aug 7, 2026
Why did some previous versions seem to have no problem? But overall, the issue isn't serious. Now that we know the cause, we can use the following temporary solution: disable vector in ksu, then perform a soft reboot, and then enable vector again and perform another soft reboot. This only requires an extra soft reboot.
JingMatrix commentedon Aug 7, 2026
@RMDycz If you have some working version, please share the link and the logs generated by that build, it will help us to solve this in new versions of Vector.
RMDycz commentedon Aug 7, 2026
Okay, the Vector v2.1 (3076-1e595f3c-HSSkyBoy) version I mentioned before also has the same problem. However, I can confirm that Vector 2.0 Mar 23 version does not have this issue because I have been using this version for a considerable period of time.
RMDycz commentedon Aug 10, 2026
This could also be an issue with the KSU update, because the KSU version I was using before was an older one, probably the May version of Vector and the May version of KSU. It might take some time to test the versions to find out exactly where the problem lies.
4 remaining items
JingMatrix commentedon Aug 13, 2026
@astr64 I will review the PR once it iterates till a mature stage.
No worries, quality of merged code is always guaranteed.
astr64 commentedon Aug 13, 2026
@JingMatrix What sort of logs can I provide to benefit development and fixing this bug?
I enter a double soft loop with basically any version of Vector (tried 2.0, 2.1, 2.2, and the latest 2.2 betas)
JingMatrix commentedon Aug 13, 2026
@astr64 I have not an implementation plan yet, let us be patient. I am currently busy with
TEESimulator.The support is broken now for sure. I will ask for your test once I start to inspect a solution. Thanks
astr64 commentedon Aug 13, 2026
Thank you for your service and work on TEE, and hit me up when you tackle this issue! Godspeed
ManiaciaChao commentedon Aug 24, 2026
Based on our discussion, I made a KSU module as a temporary workaround until PR #914 is merged, for those who want to use Vector with a late-loaded KSU. It uses the
emulated-soft-reboothook to kill the previousvectordprocess whenever a soft reboot is performed.vector-soft-reboot-guard-v0.1.0.zipIt still has a problem:
astr64 commentedon Aug 24, 2026
I rebuilt vector with 914 applied, and it didn't work for me. Any info can provide? (Pixel 10, Root My Pixel)
ManiaciaChao commentedon Aug 24, 2026
I think the implementation in #914 is still not quite correct. As I mentioned above, stale dex2oat bind mounts can still remain after a soft reboot.
I've added some additional cleanup logic to the KSU module. You can use an official Vector build without #914 together with this updated module to verify whether the issue is fixed.
vector-soft-reboot-guard-v0.2.0.zip
Note: The first soft reboot after installing this module only activates it. You'll need to perform one more soft reboot to clean up the stale state and verify whether
vectordrestarts normally.ezariago commentedon Sep 9, 2026
Hi! I used the soft reboot guard you've attached, but sadly it doesn't really do anything
grischuk-c commentedon Sep 21, 2026
@H3XDaemon your solution works fine on samsung, i had to include small change., after soft reboot trying to install any app causes system crash.
1789994679.653 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
1789994679.643 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
1789994679.634 artd 980 980 W LSPlt : symbol _ZNK3art9OatHeader16GetKeyValueStoreEv not found in PLT table
setenforce 0 , makes vectord to umount dex2oat [https://github.com/JingMatrix/Vector/blob/master/daemon/src/main/kotlin/org/matrix/vector/daemon/env/Dex2OatServer.kt#L86] , fixing the crash
emulated-soft-reboot.sh
pids=$(pgrep -f '^vectord')
if [ -n "$pids" ]; then
setenforce 0
sleep 1
kill -9 $pids
setenforce 1
fi
exit 0
Edit:- i think we can directly call umount
bartasc4 commentedon Oct 17, 2026
I opened #1012, building on H3XDaemon's pre-stop hook and ManiaciaChao's stale compiler-mount diagnosis. It handles both the surviving daemon and its mounts, including first-update
post-fs-datacleanup, without relying on the process name or toggling SELinux.It includes the complete script-level lifecycle change, applies directly to master, and does not depend on #914 or #1008. It overlaps #914; the separate compiler recursion guards from #1008 are not included.
It includes 24 Linux integration tests (passing with dash, BusyBox and mksh). The same four production scripts were observed through one successful Android 12 cycle; validation details and limits are in the PR.
kinghe2023 commentedon Oct 18, 2026
Confirming this on a second device, plus one KernelSU behaviour worth knowing while testing the hooks above.
Device: Samsung Galaxy S25 (SM-S931U1), Android 16 / One UI 8, KernelSU v3.2.5 LKM late-load (locked bootloader), Vector v2.2 (3080), Zygisk Next 1.5.2.
The stage does run here — our
emulated-soft-reboot.shwrites a line to a file, and the timestamps line up with a realksud soft-reboot. (/dev/kmsgis useless for this: the soft reboot's own burst rotates the ring buffer within seconds.)Three things I did not see above:
KernelSU applies module mounts once per load, not per soft reboot. A module installed while late-loaded is not mounted by a later
ksud soft-reboot: the scripts are replayed, the overlay is not re-created. We watched this with a module of ours that ships a permission XML and an overlay library — afterksud post-fs-data(and after a soft reboot) the files were still absent from/system,/proc/1/mountinfohad no matching entry, and that module's ownpost-fs-data.shhad clearly run. So the "the first soft reboot after installing only activates it" note above is not a quirk of that particular module — it is how the mount stage behaves. Anything that has to be live sooner must be brought in by hand (mount --bind), which is how we ended up testing it.On this firmware
ksud soft-rebootis not a safe way to get Vector back up, even with the duplicate handled. Our last attempt had system_server come up before the APEX-providedandroid.ext.servicespackage was resolvable (Required services extension package is missing ... android.ext.services), crash-loop, and Rescue Party reboot the device — losing root, since a late-loaded LKM does not survive a real reboot. What we do instead: startvectordfirst (it claims theserialproxy name early), then start Zygisk Next and let its zygote restart hand the new system_server to the waiting daemon. That is KernelSU-side rather than Vector-side, but it is why "just avoid the soft reboot" is a cheap workaround on a normal device and an expensive one here.A three-line guard for the case where the KernelSU stage does not exist (Magisk, APatch) or does not run. Starting a second daemon is what creates the collision, and
service.shcan notice that one is already alive:if pgrep -f '^vectord' >/dev/null 2>&1; then exit 0; fi. Anchored, becauseapp_processsets the nice name inargvonly —commstaysmain, sopkill vectordmatches nothing, while an unanchored pattern matches any shell whose command line happens to contain the word.What a daemon restart leaves behind when system_server is already running — a permanently false "not injected" state with no repair path — is filed separately: #1015.
bartasc4 commentedon Oct 18, 2026
I opened #1017 for the daemon-restart gap described here and in #1015. It re-registers an already injected
system_serverthrough the existing bridge, restores loaded modern modules’ IPC/preferences and hot-reload targets, and derives manager status from the live registration. It does not rerun module entry points or reinstall hooks. Native startup also waits for a successful registration handshake rather than accepting an unrelated binder at the proxy name.This complements #1012’s daemon/compiler-mount cleanup and applies directly to master. #1018 separately releases consumed hot-reload resources and retired callbacks. The three changes also compile and pass their regression suites together.
An Android 12/NeoZygisk local validation build passed daemon replacements with unchanged
system_server/zygote PID and start times, then a KernelSU emulated soft reboot followed by application and hot-reload tests. Clean PR sources were compiled separately. I have not reproduced the locked-bootloader LKM setup; these changes do not restore external overlays or fix the reported APEX/extension-package failure.Keep the daemon's tmpfs out of the host, and start it only once
JingMatrix commentedon Oct 30, 2026
Hello everyone, sorry for the delay.
Could you guys try latest CI builds of NeoZygisk and Vector ? In the local device tests, the
late-loadmode (jailbreak) and soft reboot are well supported by them now.H3XDaemon commentedon Oct 30, 2026
Tried 3114 (eaffc81) on SM-S9280, KernelSU 3.2.5 LKM late-load, Zygisk Next 1.5.1 (not NeoZygisk).
Release build: from the second soft reboot on,
service.shstill starts a second daemon that gets pasttryLock(), ping-pongs with the old one and dies with StackOverflowError. No injection in all 5 of those rounds. The Debug build of the same commit works: the new daemon exits at the lock check and the old one re-injects, 3 of 3.R8 drops the stores to
FileSystem.lockChannelandfileLockin release.tryLock()is inlined intomainand there is nosput-objectfor either field, while the debug dex has both. The channel only lives in a register, gets collected, its fd is closed and the lock goes with it. A running release daemon has nothing in/proc/locks; the debug one held the lock for the 30+ minutes I watched.The template asks for the debug build, which is probably why it looks fixed in local tests.
Reading the fields somewhere is enough to keep them, e.g. a
releaseLock()called from a shutdown hook. I can change #914 to do that.