Disable mmap'd cache files if container is class A
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Feb 2017 21:30:21 +0000 (21:30 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Feb 2017 21:30:21 +0000 (21:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=168241
<rdar://problem/23676252>

Reviewed by JF Bastien and Chris Dumez.

If the mmap'd cache file gets evicted and the device is locked,
then WebContent won't be able to bring the file back in under
class A, causing SIGBUS.

In those circumstances, don't use mmap'd files.

* NetworkProcess/cache/NetworkCache.h:
(WebKit::NetworkCache::Cache::canUseSharedMemoryForBodyData):
* NetworkProcess/cache/NetworkCacheEntry.cpp:
(WebKit::NetworkCache::Entry::initializeShareableResourceHandleFromStorageRecord):

    Don't initialize the shareable resource handle for the map if forbidden.

* NetworkProcess/cache/NetworkCacheFileSystem.cpp:
(WebKit::NetworkCache::canUseSharedMemoryForPath):

    Query the system for the protection status of the cache path.

* NetworkProcess/cache/NetworkCacheFileSystem.h:
* NetworkProcess/cache/NetworkCacheStorage.cpp:
(WebKit::NetworkCache::Storage::Storage):
* NetworkProcess/cache/NetworkCacheStorage.h:
(WebKit::NetworkCache::Storage::canUseSharedMemoryForBodyData):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212244 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCache.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheEntry.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystem.h
Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp
Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h

index 393cb77..fe0a0fb 100644 (file)
@@ -1,3 +1,35 @@
+2017-02-13  Antti Koivisto  <antti@apple.com>
+
+        Disable mmap'd cache files if container is class A
+        https://bugs.webkit.org/show_bug.cgi?id=168241
+        <rdar://problem/23676252>
+
+        Reviewed by JF Bastien and Chris Dumez.
+
+        If the mmap'd cache file gets evicted and the device is locked,
+        then WebContent won't be able to bring the file back in under
+        class A, causing SIGBUS.
+
+        In those circumstances, don't use mmap'd files.
+
+        * NetworkProcess/cache/NetworkCache.h:
+        (WebKit::NetworkCache::Cache::canUseSharedMemoryForBodyData):
+        * NetworkProcess/cache/NetworkCacheEntry.cpp:
+        (WebKit::NetworkCache::Entry::initializeShareableResourceHandleFromStorageRecord):
+
+            Don't initialize the shareable resource handle for the map if forbidden.
+
+        * NetworkProcess/cache/NetworkCacheFileSystem.cpp:
+        (WebKit::NetworkCache::canUseSharedMemoryForPath):
+
+            Query the system for the protection status of the cache path.
+
+        * NetworkProcess/cache/NetworkCacheFileSystem.h:
+        * NetworkProcess/cache/NetworkCacheStorage.cpp:
+        (WebKit::NetworkCache::Storage::Storage):
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+        (WebKit::NetworkCache::Storage::canUseSharedMemoryForBodyData):
+
 2017-02-13  Youenn Fablet  <youennf@gmail.com>
 
         [WebRTC] libwebrtc socket factory is not assigning the right socket type
index 49d9660..bbedce3 100644 (file)
@@ -382,13 +382,15 @@ std::unique_ptr<Entry> Cache::store(const WebCore::ResourceRequest& request, con
     auto cacheEntry = makeEntry(request, response, WTFMove(responseData));
     auto record = cacheEntry->encodeAsStorageRecord();
 
-    m_storage->store(record, [completionHandler = WTFMove(completionHandler)](const Data& bodyData) {
+    m_storage->store(record, [this, completionHandler = WTFMove(completionHandler)](const Data& bodyData) {
         MappedBody mappedBody;
 #if ENABLE(SHAREABLE_RESOURCE)
-        if (auto sharedMemory = bodyData.tryCreateSharedMemory()) {
-            mappedBody.shareableResource = ShareableResource::create(sharedMemory.releaseNonNull(), 0, bodyData.size());
-            ASSERT(mappedBody.shareableResource);
-            mappedBody.shareableResource->createHandle(mappedBody.shareableResourceHandle);
+        if (canUseSharedMemoryForBodyData()) {
+            if (auto sharedMemory = bodyData.tryCreateSharedMemory()) {
+                mappedBody.shareableResource = ShareableResource::create(sharedMemory.releaseNonNull(), 0, bodyData.size());
+                ASSERT(mappedBody.shareableResource);
+                mappedBody.shareableResource->createHandle(mappedBody.shareableResourceHandle);
+            }
         }
 #endif
         completionHandler(mappedBody);
index 51d7762..ca2bbc2 100644 (file)
@@ -130,6 +130,7 @@ public:
     void dumpContentsToFile();
 
     String recordsPath() const;
+    bool canUseSharedMemoryForBodyData() const { return m_storage && m_storage->canUseSharedMemoryForBodyData(); }
 
 #if ENABLE(NETWORK_CACHE_SPECULATIVE_REVALIDATION)
     SpeculativeLoadManager* speculativeLoadManager() { return m_speculativeLoadManager.get(); }
index 5ee62b1..b96bbcd 100644 (file)
@@ -146,6 +146,9 @@ std::unique_ptr<Entry> Entry::decodeStorageRecord(const Storage::Record& storage
 #if ENABLE(SHAREABLE_RESOURCE)
 void Entry::initializeShareableResourceHandleFromStorageRecord() const
 {
+    if (!NetworkCache::singleton().canUseSharedMemoryForBodyData())
+        return;
+
     auto sharedMemory = m_sourceStorageRecord.body.tryCreateSharedMemory();
     if (!sharedMemory)
         return;
index 091193a..52ac566 100644 (file)
 
 #if ENABLE(NETWORK_CACHE)
 
+#include "Logging.h"
 #include <WebCore/FileSystem.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <wtf/Assertions.h>
 #include <wtf/Function.h>
 #include <wtf/text/CString.h>
 
+#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
+#include <sys/attr.h>
+#include <unistd.h>
+#endif
+
 #if USE(SOUP)
 #include <gio/gio.h>
 #include <wtf/glib/GRefPtr.h>
@@ -126,6 +133,37 @@ void updateFileModificationTimeIfNeeded(const String& path)
     utimes(WebCore::fileSystemRepresentation(path).data(), nullptr);
 }
 
+bool canUseSharedMemoryForPath(const String& path)
+{
+#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
+    struct {
+        uint32_t length;
+        uint32_t protectionClass;
+    } attrBuffer;
+
+    attrlist attrList = { };
+    attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+    attrList.commonattr = ATTR_CMN_DATA_PROTECT_FLAGS;
+    int32_t error = getattrlist(WebCore::fileSystemRepresentation(path).data(), &attrList, &attrBuffer, sizeof(attrBuffer), FSOPT_NOFOLLOW);
+    if (error) {
+        RELEASE_LOG_ERROR(Network, "Unable to get cache directory protection class, disabling use of shared mapped memory");
+        return false;
+    }
+
+    // For stricter protection classes shared maps could disappear when device is locked.
+    const uint32_t fileProtectionCompleteUntilFirstUserAuthentication = 3;
+    bool isSafe = attrBuffer.protectionClass >= fileProtectionCompleteUntilFirstUserAuthentication;
+
+    if (!isSafe)
+        RELEASE_LOG(Network, "Disallowing use of shared mapped memory due to container protection class %u", attrBuffer.protectionClass);
+
+    return isSafe;
+#else
+    UNUSED_PARAM(path);
+    return true;
+#endif
+}
+
 }
 }
 
index 1583606..22e716f 100644 (file)
@@ -46,6 +46,8 @@ struct FileTimes {
 FileTimes fileTimes(const String& path);
 void updateFileModificationTimeIfNeeded(const String& path);
 
+bool canUseSharedMemoryForPath(const String& path);
+
 }
 }
 
index 6eab160..46e35db 100644 (file)
@@ -211,6 +211,7 @@ Storage::Storage(const String& baseDirectoryPath, Salt salt)
     : m_basePath(baseDirectoryPath)
     , m_recordsPath(makeRecordsDirectoryPath(baseDirectoryPath))
     , m_salt(salt)
+    , m_canUseSharedMemoryForBodyData(canUseSharedMemoryForPath(baseDirectoryPath))
     , m_readOperationTimeoutTimer(*this, &Storage::cancelAllReadOperations)
     , m_writeOperationDispatchTimer(*this, &Storage::dispatchPendingWriteOperations)
     , m_ioQueue(WorkQueue::create("com.apple.WebKit.Cache.Storage", WorkQueue::Type::Concurrent))
index 8994339..30b5f13 100644 (file)
@@ -100,6 +100,8 @@ public:
 
     const Salt& salt() const { return m_salt; }
 
+    bool canUseSharedMemoryForBodyData() const { return m_canUseSharedMemoryForBodyData; }
+
     ~Storage();
 
 private:
@@ -146,6 +148,8 @@ private:
 
     const Salt m_salt;
 
+    const bool m_canUseSharedMemoryForBodyData;
+
     size_t m_capacity { std::numeric_limits<size_t>::max() };
     size_t m_approximateRecordsSize { 0 };