1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "SandboxExtension.h" 28 29#if ENABLE(WEB_PROCESS_SANDBOX) 30 31#import "ArgumentDecoder.h" 32#import "ArgumentEncoder.h" 33#import "DataReference.h" 34#import "WebKitSystemInterface.h" 35#import <WebCore/FileSystem.h> 36#import <sys/stat.h> 37#import <wtf/text/CString.h> 38 39using namespace WebCore; 40 41namespace WebKit { 42 43SandboxExtension::Handle::Handle() 44 : m_sandboxExtension(0) 45{ 46} 47 48SandboxExtension::Handle::~Handle() 49{ 50 if (m_sandboxExtension) { 51 WKSandboxExtensionInvalidate(m_sandboxExtension); 52 WKSandboxExtensionDestroy(m_sandboxExtension); 53 } 54} 55 56void SandboxExtension::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const 57{ 58 if (!m_sandboxExtension) { 59 encoder->encodeBytes(0, 0); 60 return; 61 } 62 63 size_t length = 0; 64 const char *serializedFormat = WKSandboxExtensionGetSerializedFormat(m_sandboxExtension, &length); 65 ASSERT(serializedFormat); 66 67 encoder->encodeBytes(reinterpret_cast<const uint8_t*>(serializedFormat), length); 68 69 // Encoding will destroy the sandbox extension locally. 70 WKSandboxExtensionDestroy(m_sandboxExtension); 71 m_sandboxExtension = 0; 72} 73 74bool SandboxExtension::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& result) 75{ 76 ASSERT(!result.m_sandboxExtension); 77 78 CoreIPC::DataReference dataReference; 79 if (!decoder->decodeBytes(dataReference)) 80 return false; 81 82 if (dataReference.isEmpty()) 83 return true; 84 85 result.m_sandboxExtension = WKSandboxExtensionCreateFromSerializedFormat(reinterpret_cast<const char*>(dataReference.data()), dataReference.size()); 86 return true; 87} 88 89PassRefPtr<SandboxExtension> SandboxExtension::create(const Handle& handle) 90{ 91 if (!handle.m_sandboxExtension) 92 return 0; 93 94 return adoptRef(new SandboxExtension(handle)); 95} 96 97static WKSandboxExtensionType wkSandboxExtensionType(SandboxExtension::Type type) 98{ 99 switch (type) { 100 case SandboxExtension::ReadOnly: 101 return WKSandboxExtensionTypeReadOnly; 102 case SandboxExtension::WriteOnly: 103 return WKSandboxExtensionTypeWriteOnly; 104 case SandboxExtension::ReadWrite: 105 return WKSandboxExtensionTypeReadWrite; 106 } 107 108 ASSERT_NOT_REACHED(); 109 return WKSandboxExtensionTypeReadOnly; 110} 111 112static CString resolveSymlinksInPath(const CString& path) 113{ 114 struct stat statBuf; 115 116 // Check if this file exists. 117 if (!stat(path.data(), &statBuf)) { 118 char resolvedName[PATH_MAX]; 119 120 return realpath(path.data(), resolvedName); 121 } 122 123 char* slashPtr = strrchr(path.data(), '/'); 124 if (slashPtr == path.data()) 125 return path; 126 127 size_t parentDirectoryLength = slashPtr - path.data(); 128 if (parentDirectoryLength >= PATH_MAX) 129 return CString(); 130 131 // Get the parent directory. 132 char parentDirectory[PATH_MAX]; 133 memcpy(parentDirectory, path.data(), parentDirectoryLength); 134 parentDirectory[parentDirectoryLength] = '\0'; 135 136 // Resolve it. 137 CString resolvedParentDirectory = resolveSymlinksInPath(CString(parentDirectory)); 138 if (resolvedParentDirectory.isNull()) 139 return CString(); 140 141 size_t lastPathComponentLength = path.length() - parentDirectoryLength; 142 size_t resolvedPathLength = resolvedParentDirectory.length() + lastPathComponentLength; 143 if (resolvedPathLength >= PATH_MAX) 144 return CString(); 145 146 // Combine the resolved parent directory with the last path component. 147 char* resolvedPathBuffer; 148 CString resolvedPath = CString::newUninitialized(resolvedPathLength, resolvedPathBuffer); 149 memcpy(resolvedPathBuffer, resolvedParentDirectory.data(), resolvedParentDirectory.length()); 150 memcpy(resolvedPathBuffer + resolvedParentDirectory.length(), slashPtr, lastPathComponentLength); 151 152 return resolvedPath; 153} 154 155void SandboxExtension::createHandle(const String& path, Type type, Handle& handle) 156{ 157 ASSERT(!handle.m_sandboxExtension); 158 159 CString standardizedPath = resolveSymlinksInPath([[(NSString *)path stringByStandardizingPath] fileSystemRepresentation]); 160 handle.m_sandboxExtension = WKSandboxExtensionCreate(standardizedPath.data(), wkSandboxExtensionType(type)); 161} 162 163String SandboxExtension::createHandleForTemporaryFile(const String& prefix, Type type, Handle& handle) 164{ 165 ASSERT(!handle.m_sandboxExtension); 166 167 Vector<char> path(PATH_MAX); 168 if (!confstr(_CS_DARWIN_USER_TEMP_DIR, path.data(), path.size())) 169 return String(); 170 171 // Shrink the vector. 172 path.shrink(strlen(path.data())); 173 ASSERT(path.last() == '/'); 174 175 // Append the file name. 176 path.append(prefix.utf8().data(), prefix.length()); 177 path.append('\0'); 178 179 handle.m_sandboxExtension = WKSandboxExtensionCreate(fileSystemRepresentation(path.data()).data(), wkSandboxExtensionType(type)); 180 181 if (!handle.m_sandboxExtension) { 182 return String(); 183 } 184 return String(path.data()); 185} 186 187SandboxExtension::SandboxExtension(const Handle& handle) 188 : m_sandboxExtension(handle.m_sandboxExtension) 189{ 190 handle.m_sandboxExtension = 0; 191} 192 193SandboxExtension::~SandboxExtension() 194{ 195 if (!m_sandboxExtension) 196 return; 197 198 WKSandboxExtensionInvalidate(m_sandboxExtension); 199 WKSandboxExtensionDestroy(m_sandboxExtension); 200} 201 202bool SandboxExtension::invalidate() 203{ 204 ASSERT(m_sandboxExtension); 205 206 bool result = WKSandboxExtensionInvalidate(m_sandboxExtension); 207 WKSandboxExtensionDestroy(m_sandboxExtension); 208 m_sandboxExtension = 0; 209 210 return result; 211} 212 213bool SandboxExtension::consume() 214{ 215 ASSERT(m_sandboxExtension); 216 217 return WKSandboxExtensionConsume(m_sandboxExtension); 218} 219 220bool SandboxExtension::consumePermanently() 221{ 222 ASSERT(m_sandboxExtension); 223 224 bool result = WKSandboxExtensionConsume(m_sandboxExtension); 225 226 // Destroy the extension without invalidating it. 227 WKSandboxExtensionDestroy(m_sandboxExtension); 228 m_sandboxExtension = 0; 229 230 return result; 231} 232 233} // namespace WebKit 234 235#endif // ENABLE(WEB_PROCESS_SANDBOX) 236