egametang/ET · critical · Exception
mprotect with prot:{prot} fail!
Error message
mprotect with prot:{prot} fail! What it means
Thrown by HookUtils.SetMemPerms when the libc mprotect call returns non-zero after attempting to change memory protection flags on a page-aligned address range. mprotect is used to make executable code pages writable (RWX) before writing jump instructions for method hooks. A non-zero return means the kernel refused the protection change.
Source
Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/HookUtils.cs:266
public enum MmapProts : int {
PROT_READ = 0x1,
PROT_WRITE = 0x2,
PROT_EXEC = 0x4,
PROT_NONE = 0x0,
PROT_GROWSDOWN = 0x01000000,
PROT_GROWSUP = 0x02000000,
}
[DllImport("libc", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int mprotect(IntPtr start, IntPtr len, MmapProts prot);
public static unsafe void SetMemPerms(IntPtr start, ulong len, MmapProts prot) {
var requiredAddr = GetPageAlignedAddr(start.ToInt64(), (int)len);
long startPage = requiredAddr.Key;
long endPage = requiredAddr.Value;
if (mprotect((IntPtr) startPage, (IntPtr) (endPage - startPage), prot) != 0)
throw new Exception($"mprotect with prot:{prot} fail!");
}
#endif
}
}
#endifView on GitHub (pinned to 5cab01f7a8)
Solutions
- Check Marshal.GetLastWin32Error() after the failed mprotect to get the errno (EACCES = permission denied, ENOMEM = invalid address).
- If SELinux/PaX is blocking RWX, consider whether the hook is feasible on this device — you may need a different hooking strategy or a rooted/test device with relaxed security.
- Verify the target address is valid and within a mapped executable region before calling SetMemPerms.
- On iOS, note that code signing and W^X enforcement make runtime patching infeasible without a jailbreak — use compile-time or build-time alternatives.
Example fix
// before
if (mprotect((IntPtr)startPage, (IntPtr)(endPage - startPage), prot) != 0)
throw new Exception($"mprotect with prot:{prot} fail!");
// after — capture errno for diagnostics
if (mprotect((IntPtr)startPage, (IntPtr)(endPage - startPage), prot) != 0)
{
int err = Marshal.GetLastWin32Error();
throw new Exception($"mprotect with prot:{prot} failed, errno={err} at addr=0x{startPage:X}");
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the address is in a mapped, page-aligned executable region before calling mprotect
// (limited in pure C#; the best pre-check is to verify IntPtr is non-zero and aligned)
if (start == IntPtr.Zero)
throw new ArgumentException("Cannot mprotect a null address.");
long pageSize = Environment.SystemPageSize;
if ((start.ToInt64() & (pageSize - 1)) != 0)
Debug.LogWarning($"Address 0x{start.ToInt64():X} is not page-aligned; GetPageAlignedAddr should handle this."); Try / catch
try
{
HookUtils.SetMemPerms(ptr, (ulong)size, MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC);
}
catch (Exception ex) when (ex.Message.Contains("mprotect"))
{
int errno = Marshal.GetLastWin32Error();
Debug.LogError($"mprotect failed (errno={errno}). The device may enforce W^X or SELinux. " +
$"Address=0x{ptr.ToInt64():X}, size={size}. Hooking may not be possible on this platform.");
} Prevention
- Test hooking on target devices early to detect security-module restrictions (SELinux, PaX).
- On iOS or hardened Android, consider that runtime code patching may be fundamentally infeasible.
- Capture and log errno via Marshal.GetLastWin32Error() to diagnose the specific mprotect failure.
- Verify the target address is valid and mapped before attempting to change its permissions.
When it happens
Trigger: SetMemPerms (or SetAddrFlagsToRWX on non-Windows) is called during hook installation to make the target method's code page writable. mprotect fails when the address is not page-aligned (though GetPageAlignedAddr should handle this), the range spans invalid memory, the process lacks privileges, or a security module (SELinux, PaX, hardened grsecurity) blocks RWX mappings.
Common situations: Running on a hardened Android kernel with SELinux or PaX enforcing that blocks W^X violations; attempting to hook code in a read-only memory-mapped segment; the target address is invalid or already freed; running on iOS where code signing prevents memory protection changes; device manufacturer custom kernel restrictions.
Related errors
- address offset of target and replace must less than ((1 << 2
- address offset of target and replace must larger than ((1 <<
- address offset of target and replace must less than (1 << 26
- Unsupported runtime
- Unsupported runtime
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/4cbf762478ef677e.
Report an issue: GitHub.