Home | History | Annotate | Download | only in mac
      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 
     39 using namespace WebCore;
     40 
     41 namespace WebKit {
     42 
     43 SandboxExtension::Handle::Handle()
     44     : m_sandboxExtension(0)
     45 {
     46 }
     47 
     48 SandboxExtension::Handle::~Handle()
     49 {
     50     if (m_sandboxExtension) {
     51         WKSandboxExtensionInvalidate(m_sandboxExtension);
     52         WKSandboxExtensionDestroy(m_sandboxExtension);
     53     }
     54 }
     55 
     56 void 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 
     74 bool 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 
     89 PassRefPtr<SandboxExtension> SandboxExtension::create(const Handle& handle)
     90 {
     91     if (!handle.m_sandboxExtension)
     92         return 0;
     93 
     94     return adoptRef(new SandboxExtension(handle));
     95 }
     96 
     97 static 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 
    112 static 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 
    155 void 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 
    163 String 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 
    187 SandboxExtension::SandboxExtension(const Handle& handle)
    188     : m_sandboxExtension(handle.m_sandboxExtension)
    189 {
    190     handle.m_sandboxExtension = 0;
    191 }
    192 
    193 SandboxExtension::~SandboxExtension()
    194 {
    195     if (!m_sandboxExtension)
    196         return;
    197 
    198     WKSandboxExtensionInvalidate(m_sandboxExtension);
    199     WKSandboxExtensionDestroy(m_sandboxExtension);
    200 }
    201 
    202 bool 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 
    213 bool SandboxExtension::consume()
    214 {
    215     ASSERT(m_sandboxExtension);
    216 
    217     return WKSandboxExtensionConsume(m_sandboxExtension);
    218 }
    219 
    220 bool 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