]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_codesigning/lib/slcrep.cpp
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / slcrep.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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)) {
427c49bc 60 const EmbeddedSignatureBlob *blob = mCache.at<const EmbeddedSignatureBlob>((uint32_t)mCache.mapSize());
b1ab9ed8
A
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
c2a06e24
A
86//
87// Signing limit is the start of the (trailing) signature
88//
89size_t DYLDCacheRep::signingLimit()
90{
91 return mCache.mapSize();
92}
93
94
b1ab9ed8
A
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//
866f8763
A
152// The discretionary additions insert a Scatter vector describing the file's mapping table,
153// and fills out the executable segment.
b1ab9ed8
A
154//
155void DYLDCacheRep::Writer::addDiscretionary(CodeDirectory::Builder &builder)
156{
866f8763
A
157 bool execSegmentProcessed = false;
158
b1ab9ed8
A
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();
427c49bc 165 scatter->base = (uint32_t)(dmap.offset() / segmentedPageSize);
b1ab9ed8 166 assert(dmap.offset() % segmentedPageSize == 0);
427c49bc 167 scatter->count = (uint32_t)(dmap.size() / segmentedPageSize);
b1ab9ed8 168 assert(dmap.size() % segmentedPageSize == 0);
866f8763
A
169
170 if (dmap.maxProt() & VM_PROT_EXECUTE) {
171 if (execSegmentProcessed) {
172 CSError::throwMe(errSecMultipleExecSegments);
173 }
174
175 builder.execSeg(dmap.offset(), dmap.limit()-dmap.address(), 0);
176 }
b1ab9ed8
A
177 }
178}
179
180
181} // end namespace CodeSigning
182} // end namespace Security