]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/mach_fat.c
   2  * Copyright (c) 1991-2015 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 #include <sys/param.h> 
  29 #include <sys/types.h> 
  31 #include <sys/vnode.h> 
  32 #include <vm/vm_kern.h> 
  33 #include <mach/kern_return.h> 
  34 #include <mach/vm_param.h> 
  35 #include <kern/cpu_number.h> 
  36 #include <mach-o/fat.h> 
  37 #include <kern/mach_loader.h> 
  38 #include <kern/mach_fat.h> 
  39 #include <libkern/OSByteOrder.h> 
  40 #include <machine/exec.h> 
  42 /********************************************************************** 
  43 * Routine:      fatfile_getarch() 
  45 * Function:     Locate the architecture-dependant contents of a fat 
  46 *               file that match this CPU. 
  48 * Args: header:         A pointer to the fat file header. 
  49 *               size:                   How large the fat file header is (including fat_arch array) 
  50 *               req_cpu_type:   The required cpu type. 
  51 *               mask_bits:      Bits to mask from the sub-image type when 
  52 *                               grading it vs. the req_cpu_type 
  54 *               archret (out):  Pointer to fat_arch structure to hold 
  57 * Returns:      KERN_SUCCESS:   Valid architecture found. 
  58 *               KERN_FAILURE:   No valid architecture found. 
  59 **********************************************************************/ 
  64         cpu_type_t               req_cpu_type
, 
  66         struct image_params      
*imgp
, 
  67         struct fat_arch          
*archret
) 
  70         struct fat_arch         
*arch
; 
  71         struct fat_arch         
*best_arch
; 
  74         uint32_t                nfat_arch
, max_nfat_arch
; 
  76         cpu_type_t              testsubtype
; 
  77         struct fat_header       
*header
; 
  79         if (sizeof(struct fat_header
) > data_size
) { 
  83         header 
= (struct fat_header 
*)data_ptr
; 
  84         nfat_arch 
= OSSwapBigToHostInt32(header
->nfat_arch
); 
  86         max_nfat_arch 
= (data_size 
- sizeof(struct fat_header
)) / sizeof(struct fat_arch
); 
  87         if (nfat_arch 
> max_nfat_arch
) { 
  88                 /* nfat_arch would cause us to read off end of buffer */ 
  93          * Scan the fat_arch's looking for the best one.  */ 
  96         arch 
= (struct fat_arch 
*) (data_ptr 
+ sizeof(struct fat_header
)); 
  97         for (; nfat_arch
-- > 0; arch
++) { 
  98                 testtype 
= OSSwapBigToHostInt32(arch
->cputype
); 
  99                 testsubtype 
= OSSwapBigToHostInt32(arch
->cpusubtype
) & ~CPU_SUBTYPE_MASK
; 
 102                  *      Check to see if right cpu type. 
 104                 if ((testtype 
& ~mask_bits
) != (req_cpu_type 
& ~mask_bits
)) { 
 109                  *      Get the grade of the cpu subtype (without feature flags) 
 111                 grade 
= grade_binary(testtype
, testsubtype
, TRUE
); 
 114                  *      Remember it if it's the best we've seen. 
 116                 if (grade 
> best_grade
) { 
 122         /* On X86_64, allow 32 bit exec only for simulator binaries. 
 123          * Failing here without re-running the grading algorithm is safe because i386 
 124          * has the lowest possible grade value (so there can't be a lower best grade 
 125          * that would be allowed if this check denied the i386 slice). */ 
 126         if (best_arch 
!= NULL 
&& 
 127             validate_potential_simulator_binary(OSSwapBigToHostInt32(best_arch
->cputype
), 
 128             imgp
, OSSwapBigToHostInt32(best_arch
->offset
), 
 129             OSSwapBigToHostInt32(best_arch
->size
)) != LOAD_SUCCESS
) { 
 135          *      Return our results. 
 137         if (best_arch 
== NULL
) { 
 141                     OSSwapBigToHostInt32(best_arch
->cputype
); 
 142                 archret
->cpusubtype     
= 
 143                     OSSwapBigToHostInt32(best_arch
->cpusubtype
); 
 145                     OSSwapBigToHostInt32(best_arch
->offset
); 
 147                     OSSwapBigToHostInt32(best_arch
->size
); 
 149                     OSSwapBigToHostInt32(best_arch
->align
); 
 155          * Free the memory we allocated and return. 
 162         vm_offset_t             data_ptr
, 
 164         struct image_params     
*imgp
, 
 165         struct fat_arch 
*archret
) 
 168          * Ignore all architectural bits when determining if an image 
 169          * in a fat file should be skipped or graded. 
 171         return fatfile_getarch(data_ptr
, data_size
, cpu_type(), CPU_ARCH_MASK
, imgp
, archret
); 
 175 fatfile_getbestarch_for_cputype( 
 177         vm_offset_t data_ptr
, 
 179         struct image_params 
*imgp
, 
 180         struct fat_arch 
*archret
) 
 183          * Scan the fat_arch array for exact matches for this cpu_type_t only 
 185         return fatfile_getarch(data_ptr
, data_size
, cputype
, 0, imgp
, archret
); 
 188 /********************************************************************** 
 189 * Routine:      fatfile_getarch_with_bits() 
 191 * Function:     Locate the architecture-dependant contents of a fat 
 192 *               file that match this CPU. 
 194 * Args: vp:             The vnode for the fat file. 
 195 *               archbits:       Architecture specific feature bits 
 196 *               header:         A pointer to the fat file header. 
 197 *               archret (out):  Pointer to fat_arch structure to hold 
 200 * Returns:      KERN_SUCCESS:   Valid architecture found. 
 201 *               KERN_FAILURE:   No valid architecture found. 
 202 **********************************************************************/ 
 204 fatfile_getarch_with_bits( 
 206         vm_offset_t             data_ptr
, 
 208         struct fat_arch         
*archret
) 
 211          * Scan the fat_arch array for matches with the requested 
 212          * architectural bits set, and for the current hardware cpu CPU. 
 214         return fatfile_getarch(data_ptr
, data_size
, (archbits 
& CPU_ARCH_MASK
) | (cpu_type() & ~CPU_ARCH_MASK
), 0, NULL
, archret
); 
 218  * Validate the fat_header and fat_arch array in memory. We check that: 
 220  * 1) arch count would not exceed the data buffer 
 221  * 2) arch list does not contain duplicate cputype/cpusubtype tuples 
 222  * 3) arch list does not have two overlapping slices. The area 
 223  *    at the front of the file containing the fat headers is implicitly 
 224  *    a range that a slice should also not try to cover 
 227 fatfile_validate_fatarches(vm_offset_t data_ptr
, vm_size_t data_size
) 
 229         uint32_t magic
, nfat_arch
; 
 230         uint32_t max_nfat_arch
, i
, j
; 
 231         uint32_t fat_header_size
; 
 233         struct fat_arch         
*arches
; 
 234         struct fat_header       
*header
; 
 236         if (sizeof(struct fat_header
) > data_size
) { 
 240         header 
= (struct fat_header 
*)data_ptr
; 
 241         magic 
= OSSwapBigToHostInt32(header
->magic
); 
 242         nfat_arch 
= OSSwapBigToHostInt32(header
->nfat_arch
); 
 244         if (magic 
!= FAT_MAGIC
) { 
 245                 /* must be FAT_MAGIC big endian */ 
 249         max_nfat_arch 
= (data_size 
- sizeof(struct fat_header
)) / sizeof(struct fat_arch
); 
 250         if (nfat_arch 
> max_nfat_arch
) { 
 251                 /* nfat_arch would cause us to read off end of buffer */ 
 252                 return LOAD_BADMACHO
; 
 255         /* now that we know the fat_arch list fits in the buffer, how much does it use? */ 
 256         fat_header_size 
= sizeof(struct fat_header
) + nfat_arch 
* sizeof(struct fat_arch
); 
 257         arches 
= (struct fat_arch 
*)(data_ptr 
+ sizeof(struct fat_header
)); 
 259         for (i 
= 0; i 
< nfat_arch
; i
++) { 
 260                 uint32_t i_begin 
= OSSwapBigToHostInt32(arches
[i
].offset
); 
 261                 uint32_t i_size 
= OSSwapBigToHostInt32(arches
[i
].size
); 
 262                 uint32_t i_cputype 
= OSSwapBigToHostInt32(arches
[i
].cputype
); 
 263                 uint32_t i_cpusubtype 
= OSSwapBigToHostInt32(arches
[i
].cpusubtype
); 
 265                 if (i_begin 
< fat_header_size
) { 
 266                         /* slice is trying to claim part of the file used by fat headers themselves */ 
 267                         return LOAD_BADMACHO
; 
 270                 if ((UINT32_MAX 
- i_size
) < i_begin
) { 
 271                         /* start + size would overflow */ 
 272                         return LOAD_BADMACHO
; 
 274                 uint32_t i_end 
= i_begin 
+ i_size
; 
 276                 for (j 
= i 
+ 1; j 
< nfat_arch
; j
++) { 
 277                         uint32_t j_begin 
= OSSwapBigToHostInt32(arches
[j
].offset
); 
 278                         uint32_t j_size 
= OSSwapBigToHostInt32(arches
[j
].size
); 
 279                         uint32_t j_cputype 
= OSSwapBigToHostInt32(arches
[j
].cputype
); 
 280                         uint32_t j_cpusubtype 
= OSSwapBigToHostInt32(arches
[j
].cpusubtype
); 
 282                         if ((i_cputype 
== j_cputype
) && (i_cpusubtype 
== j_cpusubtype
)) { 
 283                                 /* duplicate cputype/cpusubtype, results in ambiguous references */ 
 284                                 return LOAD_BADMACHO
; 
 287                         if ((UINT32_MAX 
- j_size
) < j_begin
) { 
 288                                 /* start + size would overflow */ 
 289                                 return LOAD_BADMACHO
; 
 291                         uint32_t j_end 
= j_begin 
+ j_size
; 
 293                         if (i_begin 
<= j_begin
) { 
 294                                 if (i_end 
<= j_begin
) { 
 295                                         /* I completely precedes J */ 
 297                                         /* I started before J, but ends somewhere in or after J */ 
 298                                         return LOAD_BADMACHO
; 
 301                                 if (i_begin 
>= j_end
) { 
 302                                         /* I started after J started but also after J ended */ 
 304                                         /* I started after J started but before it ended, so there is overlap */ 
 305                                         return LOAD_BADMACHO
;