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
    }
}

#endif

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Check Marshal.GetLastWin32Error() after the failed mprotect to get the errno (EACCES = permission denied, ENOMEM = invalid address).
  2. 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.
  3. Verify the target address is valid and within a mapped executable region before calling SetMemPerms.
  4. 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

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


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/4cbf762478ef677e. Report an issue: GitHub.