+#endif
+ return LOAD_SUCCESS;
+}
+
+#if __x86_64__
+static boolean_t
+check_if_simulator_binary(
+ struct image_params *imgp,
+ off_t file_offset,
+ off_t macho_size)
+{
+ struct mach_header *header;
+ char *ip_vdata = NULL;
+ kauth_cred_t cred = NULL;
+ uint32_t ncmds;
+ struct load_command *lcp;
+ boolean_t simulator_binary = FALSE;
+ void * addr = NULL;
+ vm_size_t alloc_size, cmds_size;
+ size_t offset;
+ proc_t p = current_proc(); /* XXXX */
+ int error;
+ int resid = 0;
+ size_t mach_header_sz = sizeof(struct mach_header);
+
+
+ cred = kauth_cred_proc_ref(p);
+
+ /* Allocate page to copyin mach header */
+ ip_vdata = kalloc(PAGE_SIZE);
+ if (ip_vdata == NULL) {
+ goto bad;
+ }
+
+ /* Read the Mach-O header */
+ error = vn_rdwr(UIO_READ, imgp->ip_vp, ip_vdata,
+ PAGE_SIZE, file_offset,
+ UIO_SYSSPACE, (IO_UNIT | IO_NODELOCKED),
+ cred, &resid, p);
+ if (error) {
+ goto bad;
+ }
+
+ header = (struct mach_header *)ip_vdata;
+
+ if (header->magic == MH_MAGIC_64 ||
+ header->magic == MH_CIGAM_64) {
+ mach_header_sz = sizeof(struct mach_header_64);
+ }
+
+ /* ensure header + sizeofcmds falls within the file */
+ if (os_add_overflow(mach_header_sz, header->sizeofcmds, &cmds_size) ||
+ (off_t)cmds_size > macho_size ||
+ round_page_overflow(cmds_size, &alloc_size)) {
+ goto bad;
+ }
+
+ /*
+ * Map the load commands into kernel memory.
+ */
+ addr = kalloc(alloc_size);
+ if (addr == NULL) {
+ goto bad;
+ }
+
+ error = vn_rdwr(UIO_READ, imgp->ip_vp, addr, alloc_size, file_offset,
+ UIO_SYSSPACE, IO_NODELOCKED, cred, &resid, p);
+ if (error) {
+ goto bad;
+ }
+
+ if (resid) {
+ /* We must be able to read in as much as the mach_header indicated */
+ goto bad;
+ }
+
+ /*
+ * Loop through each of the load_commands indicated by the
+ * Mach-O header; if an absurd value is provided, we just
+ * run off the end of the reserved section by incrementing
+ * the offset too far, so we are implicitly fail-safe.
+ */
+ offset = mach_header_sz;
+ ncmds = header->ncmds;
+
+ while (ncmds--) {
+ /* ensure enough space for a minimal load command */
+ if (offset + sizeof(struct load_command) > cmds_size) {
+ break;
+ }
+
+ /*
+ * Get a pointer to the command.
+ */
+ lcp = (struct load_command *)(addr + offset);
+
+ /*
+ * Perform prevalidation of the struct load_command
+ * before we attempt to use its contents. Invalid
+ * values are ones which result in an overflow, or
+ * which can not possibly be valid commands, or which
+ * straddle or exist past the reserved section at the
+ * start of the image.
+ */
+ if (os_add_overflow(offset, lcp->cmdsize, &offset) ||
+ lcp->cmdsize < sizeof(struct load_command) ||
+ offset > cmds_size) {
+ break;
+ }
+
+ /* Check if its a simulator binary. */
+ switch (lcp->cmd) {
+ case LC_VERSION_MIN_WATCHOS:
+ simulator_binary = TRUE;
+ break;
+
+ case LC_BUILD_VERSION: {
+ struct build_version_command *bvc;
+
+ bvc = (struct build_version_command *) lcp;
+ if (bvc->cmdsize < sizeof(*bvc)) {
+ /* unsafe to use this command struct if cmdsize
+ * validated above is too small for it to fit */
+ break;
+ }
+ if (bvc->platform == PLATFORM_IOSSIMULATOR ||
+ bvc->platform == PLATFORM_WATCHOSSIMULATOR) {
+ simulator_binary = TRUE;
+ }
+
+ break;
+ }