+#if 3936456
+ if (prot & (VM_PROT_EXECUTE | VM_PROT_WRITE)) {
+ prot |= VM_PROT_READ;
+ }
+#endif /* 3936456 */
+
+#if defined(__arm64__)
+ if (prot & VM_PROT_STRIP_READ) {
+ prot &= ~(VM_PROT_READ | VM_PROT_STRIP_READ);
+ }
+#endif
+
+#if CONFIG_MACF
+ /*
+ * The MAC check for mprotect is of limited use for 2 reasons:
+ * Without mmap revocation, the caller could have asked for the max
+ * protections initially instead of a reduced set, so a mprotect
+ * check would offer no new security.
+ * It is not possible to extract the vnode from the pager object(s)
+ * of the target memory range.
+ * However, the MAC check may be used to prevent a process from,
+ * e.g., making the stack executable.
+ */
+ error = mac_proc_check_mprotect(p, user_addr,
+ user_size, prot);
+ if (error) {
+ return error;
+ }
+#endif
+
+ if (prot & VM_PROT_TRUSTED) {
+#if CONFIG_DYNAMIC_CODE_SIGNING
+ /* CODE SIGNING ENFORCEMENT - JIT support */
+ /* The special protection value VM_PROT_TRUSTED requests that we treat
+ * this page as if it had a valid code signature.
+ * If this is enabled, there MUST be a MAC policy implementing the
+ * mac_proc_check_mprotect() hook above. Otherwise, Codesigning will be
+ * compromised because the check would always succeed and thusly any
+ * process could sign dynamically. */
+ result = vm_map_sign(
+ user_map,
+ vm_map_trunc_page(user_addr,
+ vm_map_page_mask(user_map)),
+ vm_map_round_page(user_addr + user_size,
+ vm_map_page_mask(user_map)));
+ switch (result) {
+ case KERN_SUCCESS:
+ break;
+ case KERN_INVALID_ADDRESS:
+ /* UNIX SPEC: for an invalid address range, return ENOMEM */
+ return ENOMEM;
+ default:
+ return EINVAL;
+ }
+#else
+ return ENOTSUP;
+#endif
+ }
+ prot &= ~VM_PROT_TRUSTED;