void NaClReplaceDescIfValidationCacheAssertsMappable( struct NaClDesc **desc_in_out, struct NaClValidationCache *validation_cache) { struct NaClDesc *desc = *desc_in_out; struct NaClDesc *replacement; struct NaClFileToken file_token; if (NACL_FI("validation_cache_replacement_bypass", 0, 1)) { NaClDescMarkSafeForMmap(desc); } else if (!NaClDescGetFileToken(desc, &file_token)) { NaClLog(4, "NaClReplaceDescIfValidationCacheAssertsMappable: no valid" " file token\n"); } else { replacement = NaClExchangeFileTokenForMappableDesc(&file_token, validation_cache); if (NULL != replacement) { NaClDescUnref(desc); *desc_in_out = replacement; } } }
NaClErrorCode NaClElfImageLoad(struct NaClElfImage *image, struct NaClDesc *ndp, struct NaClApp *nap) { int segnum; uintptr_t vaddr; uintptr_t paddr; uintptr_t end_vaddr; ssize_t read_ret; int safe_for_mmap; for (segnum = 0; segnum < image->ehdr.e_phnum; ++segnum) { const Elf_Phdr *php = &image->phdrs[segnum]; Elf_Off offset = (Elf_Off) NaClTruncAllocPage(php->p_offset); Elf_Off filesz = php->p_offset + php->p_filesz - offset; /* did we decide that we will load this segment earlier? */ if (!image->loadable[segnum]) { continue; } NaClLog(2, "loading segment %d\n", segnum); if (0 == php->p_filesz) { NaClLog(4, "zero-sized segment. ignoring...\n"); continue; } end_vaddr = php->p_vaddr + php->p_filesz; /* integer overflow? */ if (end_vaddr < php->p_vaddr) { NaClLog(LOG_FATAL, "parameter error should have been detected already\n"); } /* * is the end virtual address within the NaCl application's * address space? if it is, it implies that the start virtual * address is also. */ if (end_vaddr >= ((uintptr_t) 1U << nap->addr_bits)) { NaClLog(LOG_FATAL, "parameter error should have been detected already\n"); } vaddr = NaClTruncAllocPage(php->p_vaddr); paddr = NaClUserToSysAddr(nap, vaddr); CHECK(kNaClBadAddress != paddr); /* * Check NaClDescIsSafeForMmap(ndp) to see if it might be okay to * mmap. */ NaClLog(4, "NaClElfImageLoad: checking descriptor mmap safety\n"); safe_for_mmap = NaClDescIsSafeForMmap(ndp); if (safe_for_mmap) { NaClLog(4, "NaClElfImageLoad: safe-for-mmap\n"); } if (!safe_for_mmap && NACL_FI("ELF_LOAD_BYPASS_DESCRIPTOR_SAFETY_CHECK", 0, 1)) { NaClLog(LOG_WARNING, "WARNING: BYPASSING DESCRIPTOR SAFETY CHECK\n"); safe_for_mmap = 1; } if (safe_for_mmap) { NaClErrorCode map_status; NaClLog(4, "NaClElfImageLoad: safe-for-mmap\n"); map_status = NaClElfFileMapSegment(nap, ndp, php->p_flags, offset, filesz, vaddr, paddr); /* * NB: -Werror=switch-enum forces us to not use a switch. */ if (LOAD_OK == map_status) { /* Segment has been handled -- proceed to next segment */ continue; } else if (LOAD_STATUS_UNKNOWN != map_status) { /* * A real error! Return it so that this can be reported to * the embedding code (via start_module status). */ return map_status; } /* Fall through: pread-based fallback requested */ } NaClLog(4, "PReading %"NACL_PRIdElf_Xword" (0x%"NACL_PRIxElf_Xword") bytes to" " address 0x%"NACL_PRIxPTR", position %" NACL_PRIdElf_Off" (0x%"NACL_PRIxElf_Off")\n", filesz, filesz, paddr, offset, offset); /* * Tell valgrind that this memory is accessible and undefined. For more * details see * http://code.google.com/p/nativeclient/wiki/ValgrindMemcheck#Implementation_details */ NACL_MAKE_MEM_UNDEFINED((void *) paddr, filesz); read_ret = (*NACL_VTBL(NaClDesc, ndp)-> PRead)(ndp, (void *) paddr, filesz, (nacl_off64_t) offset); if (NaClSSizeIsNegErrno(&read_ret) || (size_t) read_ret != filesz) { NaClLog(LOG_ERROR, "load failure segment %d", segnum); return LOAD_SEGMENT_BAD_PARAM; } /* region from p_filesz to p_memsz should already be zero filled */ /* Tell Valgrind that we've mapped a segment of nacl_file. */ NaClFileMappingForValgrind(paddr, filesz, offset); } return LOAD_OK; }