Allow zygote to receive memfds under the new memfd_file class - #157
Conversation
The Android 17 QPR1 Beta 4 kernel labels memfds through security_inode_init_security_anon() instead of the tmpfs superblock. The inode now carries the creating task's own SID under the new memfd_file class, so the module library zygiskd hands to zygote is no longer u:object_r:tmpfs:s0 with class file, but the daemon's own domain with class memfd_file. Neither `allow zygote tmpfs file *` nor its appdomain_tmpfs counterpart matches that, so security_file_receive() denies the transfer, scm_detach_fds() installs nothing, and every forked process reads the four dummy bytes of send_fd() with msg_controllen 0. ReadModules() then dlopens fd -1 and no Zygisk module loads anywhere, while descriptor-free actions such as GetProcessFlags keep working. Grant zygote the receive and mapping permissions on memfd_file for the domains zygiskd runs in: magisk under Magisk, su under KernelSU and APatch. Magisk carries an equivalent rule since 1b9f69b4 but only in builds newer than v30.7, and it does not cover the other root implementations. On kernels without the class magiskpolicy warns and skips the statement.
recv_fds() logged an empty control buffer identically whether the peer never attached a descriptor or the kernel discarded the one it was handed. The two have opposite causes, and the log left no way to tell which had happened while diagnosing the memfd_file labelling change on Android 17. Read msg_flags and name the case: MSG_CTRUNC means scm_detach_fds() gave up part way, so the peer did send descriptors and the receiving domain lacks the permissions to take them. Its absence means the stream carried none.
|
@asdfmonster261 @JakeDHS07 — this should be the fix for JingMatrix/Vector#928, if you are willing to test it. Builds from this branch are attached to this CI run. Please take The short version of the cause, since you asked: the kernel on these phones labels memfds under a new SELinux class, so zygote was no longer allowed to accept the module library the daemon passes it over the socket, and no Zygisk module loaded at all. That is also why your Pixel 7 Pro on the same Android 17 was fine — it is the kernel that changed, not the Android version. If it still does not work, please attach the verbose log again. |
|
I can confirm that Vector is now loading on my end as well, thanks a ton! |


The Android 17 QPR1 Beta 4 kernel labels memfds through
security_inode_init_security_anon()rather than the tmpfs superblock. The inode now carries the creating task's own SID under the newmemfd_fileclass, so the module libraryzygiskdhands to zygote is no longeru:object_r:tmpfs:s0with classfile, but the daemon's own domain with classmemfd_file.Neither
allow zygote tmpfs file *nor itsappdomain_tmpfscounterpart matches that.security_file_receive()denies the transfer,scm_detach_fds()installs nothing, and every forked process reads the four dummy bytes ofsend_fd()withmsg_controllen0.ReadModules()then dlopens fd -1, so no Zygisk module loads anywhere, while descriptor-free actions such asGetProcessFlagskeep working. Reported as JingMatrix/Vector#928.Grant zygote the receive and mapping permissions on
memfd_filefor the domainszygiskdruns in:magiskunder Magisk,suunder KernelSU and APatch. Magisk carries an equivalent rule, but only in builds newer than v30.7, and it does not cover the other root implementations. On older kernelsmagiskpolicywarns and skips the statement.recv_fds()also now reports whetherMSG_CTRUNCwas set, which distinguishes a refused descriptor from one never sent.