{"record":{"id":"4cbf762478ef677e","repo":"egametang/ET","slug":"mprotect-with-prot-prot-fail","errorCode":null,"errorMessage":"mprotect with prot:{prot} fail!","messagePattern":"mprotect with prot:(.+?) fail!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/HookUtils.cs","lineNumber":266,"sourceCode":"        public enum MmapProts : int {\n            PROT_READ       = 0x1,\n            PROT_WRITE      = 0x2,\n            PROT_EXEC       = 0x4,\n            PROT_NONE       = 0x0,\n            PROT_GROWSDOWN  = 0x01000000,\n            PROT_GROWSUP    = 0x02000000,\n        }\n\n        [DllImport(\"libc\", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]\n        private static extern int mprotect(IntPtr start, IntPtr len, MmapProts prot);\n    \n        public static unsafe void SetMemPerms(IntPtr start, ulong len, MmapProts prot) {\n            var requiredAddr = GetPageAlignedAddr(start.ToInt64(), (int)len);\n            long startPage = requiredAddr.Key;\n            long endPage = requiredAddr.Value;\n\n            if (mprotect((IntPtr) startPage, (IntPtr) (endPage - startPage), prot) != 0)\n                throw new Exception($\"mprotect with prot:{prot} fail!\");\n        }\n#endif\n    }\n}\n\n#endif","sourceCodeStart":248,"sourceCodeEnd":272,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/3rds/UnityHook/HookUtils.cs#L248-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (mprotect((IntPtr)startPage, (IntPtr)(endPage - startPage), prot) != 0)\n    throw new Exception($\"mprotect with prot:{prot} fail!\");\n\n// after — capture errno for diagnostics\nif (mprotect((IntPtr)startPage, (IntPtr)(endPage - startPage), prot) != 0)\n{\n    int err = Marshal.GetLastWin32Error();\n    throw new Exception($\"mprotect with prot:{prot} failed, errno={err} at addr=0x{startPage:X}\");\n}","handlingStrategy":"try-catch","validationCode":"// Validate the address is in a mapped, page-aligned executable region before calling mprotect\n// (limited in pure C#; the best pre-check is to verify IntPtr is non-zero and aligned)\nif (start == IntPtr.Zero)\n    throw new ArgumentException(\"Cannot mprotect a null address.\");\nlong pageSize = Environment.SystemPageSize;\nif ((start.ToInt64() & (pageSize - 1)) != 0)\n    Debug.LogWarning($\"Address 0x{start.ToInt64():X} is not page-aligned; GetPageAlignedAddr should handle this.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    HookUtils.SetMemPerms(ptr, (ulong)size, MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC);\n}\ncatch (Exception ex) when (ex.Message.Contains(\"mprotect\"))\n{\n    int errno = Marshal.GetLastWin32Error();\n    Debug.LogError($\"mprotect failed (errno={errno}). The device may enforce W^X or SELinux. \" +\n        $\"Address=0x{ptr.ToInt64():X}, size={size}. Hooking may not be possible on this platform.\");\n}","preventionTips":["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."],"tags":["unityhook","mprotect","memory-permission","linux","security-module","posix"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}