2 * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
21 * @APPLE_LICENSE_HEADER_END@
25 // slcrep - DiskRep representing the Mac OS Shared Library Cache
31 namespace CodeSigning
{
33 using namespace UnixPlusPlus
;
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
43 DYLDCacheRep::DYLDCacheRep(const char *path
)
44 : SingleDiskRep(path
), mCache(path
)
49 DYLDCacheRep::DYLDCacheRep(const Context
*ctx
)
50 : SingleDiskRep(DYLDCache::pathFor(((ctx
&& ctx
->arch
) ? ctx
->arch
: Architecture::local()))),
56 void DYLDCacheRep::setup()
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
64 CODESIGN_DISKREP_CREATE_SLC(this, (char*)this->mainExecutablePath().c_str());
69 // Sniffer function for "plausible shared library cache file".
71 bool DYLDCacheRep::candidate(FileDesc
&fd
)
73 return DYLDCache::validate(fd
);
78 // Default to system page size for segmented (paged) signatures
80 size_t DYLDCacheRep::pageSize(const SigningContext
&)
82 return segmentedPageSize
;
87 // Signing limit is the start of the (trailing) signature
89 size_t DYLDCacheRep::signingLimit()
91 return mCache
.mapSize();
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.
100 CFDataRef
DYLDCacheRep::component(CodeDirectory::SpecialSlot slot
)
102 return mSigningData
? mSigningData
->component(slot
) : NULL
;
107 // Provide a (vaguely) human readable characterization of this code
109 string
DYLDCacheRep::format()
111 if (const char *name
= mCache
.architecture().name()) {
113 snprintf(result
, sizeof(result
), "OS X Shared Library Cache (%s @ 0x%llx)",
114 name
, mCache
.baseAddress());
117 return "OS X Shared Library Cache (unknown type)";
122 // DYLDCacheRep::Writers
124 DiskRep::Writer
*DYLDCacheRep::writer()
126 return new Writer(this);
131 // Write a component.
133 void DYLDCacheRep::Writer::component(CodeDirectory::SpecialSlot slot
, CFDataRef data
)
135 EmbeddedSignatureBlob::Maker::component(slot
, data
);
140 // Append the superblob we built to the cache file.
142 void DYLDCacheRep::Writer::flush()
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
);
152 // The discretionary additions insert a Scatter vector describing the file's mapping table,
153 // and fills out the executable segment.
155 void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder
&builder
)
157 bool execSegmentProcessed
= false;
159 unsigned count
= rep
->mCache
.mappingCount();
160 builder
.scatter(count
);
161 for (unsigned n
= 0; n
< count
; n
++) {
162 const DYLDCache::Mapping dmap
= rep
->mCache
.mapping(n
);
163 CodeDirectory::Scatter
*scatter
= builder
.scatter() + n
;
164 scatter
->targetOffset
= dmap
.address();
165 scatter
->base
= (uint32_t)(dmap
.offset() / segmentedPageSize
);
166 assert(dmap
.offset() % segmentedPageSize
== 0);
167 scatter
->count
= (uint32_t)(dmap
.size() / segmentedPageSize
);
168 assert(dmap
.size() % segmentedPageSize
== 0);
170 if (dmap
.maxProt() & VM_PROT_EXECUTE
) {
171 if (execSegmentProcessed
) {
172 CSError::throwMe(errSecMultipleExecSegments
);
175 builder
.execSeg(dmap
.offset(), dmap
.limit()-dmap
.address(), 0);
181 } // end namespace CodeSigning
182 } // end namespace Security