Skip to content
Permalink
Browse files
2011-04-08 Anders Carlsson <andersca@apple.com>
        Reviewed by Dan Bernstein.

        Sandboxing doesn't work if a local file is dropped on the content area
        https://bugs.webkit.org/show_bug.cgi?id=58177
        <rdar://problem/9019253>

        When performing a drag and the dragging pasteboard contains a local file, create a
        sandbox extension and pass it along. If we end up loading the file, the sandbox extension
        tracker will consume the extension.

        * UIProcess/API/mac/WKView.mm:
        (maybeCreateSandboxExtensionFromPasteboard):
        Add helper function.

        (-[WKView performDragOperation:]):
        Create a sandbox extension handle and pass it to performDrag.

        * UIProcess/WebPageProxy.cpp:
        (WebKit::WebPageProxy::dragEntered):
        (WebKit::WebPageProxy::dragUpdated):
        (WebKit::WebPageProxy::dragExited):
        Pass an empty sandbox extension handle to performDragControllerAction.

        (WebKit::WebPageProxy::performDrag):
        Pass the sandbox extension handle along to performDragControllerAction.

        (WebKit::WebPageProxy::performDragControllerAction):
        Send along the sandbox extension handle.

        * WebProcess/WebCoreSupport/WebDragClient.cpp:
        (WebKit::WebDragClient::willPerformDragDestinationAction):
        If the destination action is a load action, call WebPage::willPerformLoadDragDestinationAction.

        * WebProcess/WebPage/WebPage.cpp:
        (WebKit::WebPage::performDragControllerAction):
        Create a sandbox extension.

        (WebKit::WebPage::willPerformLoadDragDestinationAction):
        If we have a sandbox extension, pass it along to the sandbox extension tracker.

        (WebKit::WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction):
        Call setPendingProvisionalSandboxExtension.

        (WebKit::WebPage::SandboxExtensionTracker::beginLoad):
        Call setPendingProvisionalSandboxExtension.

        (WebKit::WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension):
        Factor code from beginLoad out into a separate function.

        * WebProcess/WebPage/WebPage.messages.in:
        PerformDragControllerAction now takes a sandbox extension handle.


Canonical link: https://commits.webkit.org/73134@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83362 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Anders Carlsson committed Apr 9, 2011
1 parent e7165b0 commit 89373334e597c2a765284c9dc33e09e51c8383c4
@@ -1,3 +1,57 @@
2011-04-08 Anders Carlsson <andersca@apple.com>

Reviewed by Dan Bernstein.

Sandboxing doesn't work if a local file is dropped on the content area
https://bugs.webkit.org/show_bug.cgi?id=58177
<rdar://problem/9019253>

When performing a drag and the dragging pasteboard contains a local file, create a
sandbox extension and pass it along. If we end up loading the file, the sandbox extension
tracker will consume the extension.

* UIProcess/API/mac/WKView.mm:
(maybeCreateSandboxExtensionFromPasteboard):
Add helper function.

(-[WKView performDragOperation:]):
Create a sandbox extension handle and pass it to performDrag.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::dragEntered):
(WebKit::WebPageProxy::dragUpdated):
(WebKit::WebPageProxy::dragExited):
Pass an empty sandbox extension handle to performDragControllerAction.

(WebKit::WebPageProxy::performDrag):
Pass the sandbox extension handle along to performDragControllerAction.

(WebKit::WebPageProxy::performDragControllerAction):
Send along the sandbox extension handle.

* WebProcess/WebCoreSupport/WebDragClient.cpp:
(WebKit::WebDragClient::willPerformDragDestinationAction):
If the destination action is a load action, call WebPage::willPerformLoadDragDestinationAction.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::performDragControllerAction):
Create a sandbox extension.

(WebKit::WebPage::willPerformLoadDragDestinationAction):
If we have a sandbox extension, pass it along to the sandbox extension tracker.

(WebKit::WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction):
Call setPendingProvisionalSandboxExtension.

(WebKit::WebPage::SandboxExtensionTracker::beginLoad):
Call setPendingProvisionalSandboxExtension.

(WebKit::WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension):
Factor code from beginLoad out into a separate function.

* WebProcess/WebPage/WebPage.messages.in:
PerformDragControllerAction now takes a sandbox extension handle.

2011-04-08 Alice Liu <alice.liu@apple.com>

Reviewed by Adam Roben.
@@ -1463,12 +1463,40 @@ - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
return YES;
}

// FIXME: This code is more or less copied from Pasteboard::getBestURL.
// It would be nice to be able to share the code somehow.
static void maybeCreateSandboxExtensionFromPasteboard(NSPasteboard *pasteboard, SandboxExtension::Handle& sandboxExtensionHandle)
{
NSArray *types = [pasteboard types];
if (![types containsObject:NSFilenamesPboardType])
return;

NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
if ([files count] != 1)
return;

NSString *file = [files objectAtIndex:0];
BOOL isDirectory;
if (![[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory])
return;

if (isDirectory)
return;

SandboxExtension::createHandle("/", SandboxExtension::ReadOnly, sandboxExtensionHandle);
}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
{
IntPoint client([self convertPoint:[draggingInfo draggingLocation] fromView:nil]);
IntPoint global(globalPoint([draggingInfo draggingLocation], [self window]));
DragData dragData(draggingInfo, client, global, static_cast<DragOperation>([draggingInfo draggingSourceOperationMask]), [self applicationFlags:draggingInfo]);
_data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name]);

SandboxExtension::Handle sandboxExtensionHandle;
maybeCreateSandboxExtensionFromPasteboard([draggingInfo draggingPasteboard], sandboxExtensionHandle);

_data->_page->performDrag(&dragData, [[draggingInfo draggingPasteboard] name], sandboxExtensionHandle);

return YES;
}

@@ -700,25 +700,28 @@ void WebPageProxy::setActualVisibleContentRect(const IntRect& rect)

void WebPageProxy::dragEntered(WebCore::DragData* dragData, const String& dragStorageName)
{
performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName);
SandboxExtension::Handle sandboxExtensionHandle;
performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle);
}

void WebPageProxy::dragUpdated(WebCore::DragData* dragData, const String& dragStorageName)
{
performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName);
SandboxExtension::Handle sandboxExtensionHandle;
performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle);
}

void WebPageProxy::dragExited(WebCore::DragData* dragData, const String& dragStorageName)
{
performDragControllerAction(DragControllerActionExited, dragData, dragStorageName);
SandboxExtension::Handle sandboxExtensionHandle;
performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle);
}

void WebPageProxy::performDrag(WebCore::DragData* dragData, const String& dragStorageName)
void WebPageProxy::performDrag(WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle)
{
performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName);
performDragControllerAction(DragControllerActionPerformDrag, dragData, dragStorageName, sandboxExtensionHandle);
}

void WebPageProxy::performDragControllerAction(DragControllerAction action, WebCore::DragData* dragData, const String& dragStorageName)
void WebPageProxy::performDragControllerAction(DragControllerAction action, WebCore::DragData* dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle)
{
if (!isValid())
return;
@@ -727,7 +730,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, WebC
process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(),
dragData->draggingSourceOperationMask(), dragData->dragDataMap(), dragData->flags()), m_pageID);
#else
process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags()), m_pageID);
process()->send(Messages::WebPage::PerformDragControllerAction(action, dragData->clientPosition(), dragData->globalPosition(), dragData->draggingSourceOperationMask(), dragStorageName, dragData->flags(), sandboxExtensionHandle), m_pageID);
#endif
}

@@ -384,7 +384,7 @@ class WebPageProxy : public APIObject, public WebPopupMenuProxy::Client {
void dragEntered(WebCore::DragData*, const String& dragStorageName = String());
void dragUpdated(WebCore::DragData*, const String& dragStorageName = String());
void dragExited(WebCore::DragData*, const String& dragStorageName = String());
void performDrag(WebCore::DragData*, const String& dragStorageName = String());
void performDrag(WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&);

void didPerformDragControllerAction(uint64_t resultOperation);
void dragEnded(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t operation);
@@ -696,7 +696,7 @@ class WebPageProxy : public APIObject, public WebPopupMenuProxy::Client {

void clearLoadDependentCallbacks();

void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& dragStorageName);
void performDragControllerAction(DragControllerAction, WebCore::DragData*, const String& dragStorageName, const SandboxExtension::Handle&);

PageClient* m_pageClient;
WebLoaderClient m_loaderClient;
@@ -26,14 +26,16 @@
#include "config.h"
#include "WebDragClient.h"

#include <WebCore/NotImplemented.h>
#include "WebPage.h"

using namespace WebCore;

namespace WebKit {

void WebDragClient::willPerformDragDestinationAction(DragDestinationAction, DragData*)
void WebDragClient::willPerformDragDestinationAction(DragDestinationAction action, DragData*)
{
if (action == DragDestinationActionLoad)
m_page->willPerformLoadDragDestinationAction();
}

void WebDragClient::willPerformDragSourceAction(DragSourceAction, const IntPoint&, Clipboard*)
@@ -1488,7 +1488,7 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli
}
}
#else
void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags)
void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle)
{
if (!m_page) {
send(Messages::WebPageProxy::DidPerformDragControllerAction(DragOperationNone));
@@ -1509,10 +1509,23 @@ void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint cli
m_page->dragController()->dragExited(&dragData);
break;

case DragControllerActionPerformDrag:
case DragControllerActionPerformDrag: {
ASSERT(!m_pendingDropSandboxExtension);

m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle);

m_page->dragController()->performDrag(&dragData);

// If we started loading a local file, the sandbox extension tracker would have adopted this
// pending drop sandbox extension. If not, we'll play it safe and invalidate it.
if (m_pendingDropSandboxExtension) {
m_pendingDropSandboxExtension->invalidate();
m_pendingDropSandboxExtension = nullptr;
}

break;

}

default:
ASSERT_NOT_REACHED();
}
@@ -1534,6 +1547,11 @@ void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint glob
m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
}

void WebPage::willPerformLoadDragDestinationAction()
{
m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release());
}

WebEditCommand* WebPage::webEditCommand(uint64_t commandID)
{
return m_editCommandMap.get(commandID).get();
@@ -1861,18 +1879,28 @@ void WebPage::SandboxExtensionTracker::invalidate()
}
}

void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension)
{
setPendingProvisionalSandboxExtension(pendingDropSandboxExtension);
}

void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle)
{
ASSERT(frame->isMainFrame());

setPendingProvisionalSandboxExtension(SandboxExtension::create(handle));
}

void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension)
{
// If we get two beginLoad calls in succession, without a provisional load starting, then
// m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case.
if (m_pendingProvisionalSandboxExtension) {
m_pendingProvisionalSandboxExtension->invalidate();
m_pendingProvisionalSandboxExtension = nullptr;
}
m_pendingProvisionalSandboxExtension = SandboxExtension::create(handle);

m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension;
}

static bool shouldReuseCommittedSandboxExtension(WebFrame* frame)
@@ -290,10 +290,14 @@ class WebPage : public APIObject, public CoreIPC::MessageSender<WebPage> {
void invalidate();

void beginLoad(WebFrame*, const SandboxExtension::Handle& handle);
void willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension);
void didStartProvisionalLoad(WebFrame*);
void didCommitProvisionalLoad(WebFrame*);
void didFailProvisionalLoad(WebFrame*);

private:
void setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension>);

RefPtr<SandboxExtension> m_pendingProvisionalSandboxExtension;
RefPtr<SandboxExtension> m_provisionalSandboxExtension;
RefPtr<SandboxExtension> m_committedSandboxExtension;
@@ -348,10 +352,12 @@ class WebPage : public APIObject, public CoreIPC::MessageSender<WebPage> {
#if PLATFORM(WIN)
void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap&, uint32_t flags);
#else
void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags);
void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags, const SandboxExtension::Handle&);
#endif
void dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation);

void willPerformLoadDragDestinationAction();

void beginPrinting(uint64_t frameID, const PrintInfo&);
void endPrinting();
void computePagesForPrinting(uint64_t frameID, const PrintInfo&, uint64_t callbackID);
@@ -614,6 +620,8 @@ class WebPage : public APIObject, public CoreIPC::MessageSender<WebPage> {
SandboxExtensionTracker m_sandboxExtensionTracker;
uint64_t m_pageID;

RefPtr<SandboxExtension> m_pendingDropSandboxExtension;

bool m_canRunBeforeUnloadConfirmPanel;

bool m_canRunModal;
@@ -120,7 +120,7 @@ messages -> WebPage {
PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, HashMap<UINT,Vector<String>> dataMap, uint32_t flags)
#endif
#if !PLATFORM(WIN)
PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags)
PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
#endif
DragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation)

0 comments on commit 8937333

Please sign in to comment.