1/* 2 * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// slcrep - DiskRep representing the Mac OS Shared Library Cache 26// 27#include "slcrep.h" 28 29 30namespace Security { 31namespace CodeSigning { 32 33using namespace UnixPlusPlus; 34 35 36// 37// Object management. 38// We open the file lazily, so nothing much happens on constructions. 39// We can construct directly from a file path, or from an architecture 40// (represented by Context), which will find the file in its usual 41// location on disk. 42// 43DYLDCacheRep::DYLDCacheRep(const char *path) 44 : SingleDiskRep(path), mCache(path) 45{ 46 this->setup(); 47} 48 49DYLDCacheRep::DYLDCacheRep(const Context *ctx) 50 : SingleDiskRep(DYLDCache::pathFor(((ctx && ctx->arch) ? ctx->arch : Architecture::local()))), 51 mCache(this->path()) 52{ 53 this->setup(); 54} 55 56void DYLDCacheRep::setup() 57{ 58 mSigningData = NULL; 59 if (mCache.totalSize() >= mCache.mapSize() + sizeof(BlobCore)) { 60 const EmbeddedSignatureBlob *blob = mCache.at<const EmbeddedSignatureBlob>((uint32_t)mCache.mapSize()); 61 if (mCache.totalSize() >= mCache.mapSize() + blob->length()) // entire blob fits in file 62 mSigningData = blob; 63 } 64 CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str()); 65} 66 67 68// 69// Sniffer function for "plausible shared library cache file". 70// 71bool DYLDCacheRep::candidate(FileDesc &fd) 72{ 73 return DYLDCache::validate(fd); 74} 75 76 77// 78// Default to system page size for segmented (paged) signatures 79// 80size_t DYLDCacheRep::pageSize(const SigningContext &) 81{ 82 return segmentedPageSize; 83} 84 85 86// 87// Signing limit is the start of the (trailing) signature 88// 89size_t DYLDCacheRep::signingLimit() 90{ 91 return mCache.mapSize(); 92} 93 94 95// 96// Retrieve a component from the executable. 97// Our mCache has mapped the entire file, so we just fish the contents out of 98// the mapped area as needed. 99// 100CFDataRef DYLDCacheRep::component(CodeDirectory::SpecialSlot slot) 101{ 102 return mSigningData ? mSigningData->component(slot) : NULL; 103} 104 105 106// 107// Provide a (vaguely) human readable characterization of this code 108// 109string DYLDCacheRep::format() 110{ 111 if (const char *name = mCache.architecture().name()) { 112 char result[100]; 113 snprintf(result, sizeof(result), "OS X Shared Library Cache (%s @ 0x%llx)", 114 name, mCache.baseAddress()); 115 return result; 116 } else 117 return "OS X Shared Library Cache (unknown type)"; 118} 119 120 121// 122// DYLDCacheRep::Writers 123// 124DiskRep::Writer *DYLDCacheRep::writer() 125{ 126 return new Writer(this); 127} 128 129 130// 131// Write a component. 132// 133void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) 134{ 135 EmbeddedSignatureBlob::Maker::component(slot, data); 136} 137 138 139// 140// Append the superblob we built to the cache file. 141// 142void DYLDCacheRep::Writer::flush() 143{ 144 delete mSigningData; // ditch previous blob just in case 145 mSigningData = Maker::make(); // assemble new signature SuperBlob 146 fd().seek(rep->mCache.mapSize()); // end of impage proper 147 fd().writeAll(*mSigningData); 148} 149 150 151// 152// The discretionary additions insert a Scatter vector describing the file's mapping table. 153// 154void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder) 155{ 156 unsigned count = rep->mCache.mappingCount(); 157 builder.scatter(count); 158 for (unsigned n = 0; n < count; n++) { 159 const DYLDCache::Mapping dmap = rep->mCache.mapping(n); 160 CodeDirectory::Scatter *scatter = builder.scatter() + n; 161 scatter->targetOffset = dmap.address(); 162 scatter->base = (uint32_t)(dmap.offset() / segmentedPageSize); 163 assert(dmap.offset() % segmentedPageSize == 0); 164 scatter->count = (uint32_t)(dmap.size() / segmentedPageSize); 165 assert(dmap.size() % segmentedPageSize == 0); 166 } 167} 168 169 170} // end namespace CodeSigning 171} // end namespace Security 172