[WK2] Drop WebProcess capabilities on Linux using seccomp filters
authorthiago.santos@intel.com <thiago.santos@intel.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2013 09:07:32 +0000 (09:07 +0000)
committerthiago.santos@intel.com <thiago.santos@intel.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 Apr 2013 09:07:32 +0000 (09:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=89875

Reviewed by Maciej Stachowiak.

.:

Added the bits to EFL/CMake buildsystem to find the libseccomp
library.

* Source/cmake/FindLibSeccomp.cmake: Added.
* Source/cmake/OptionsEfl.cmake:
* Source/cmake/WebKitFeatures.cmake:
* Source/cmakeconfig.h.cmake:

Source/WebCore:

Make the DATA_DIR global since it is now needed for WebCore and WebKit2.
It is now used to set a sandbox policy for the EFL port.

* PlatformEfl.cmake:

Source/WebKit2:

Introduce the foundations of the SeccompFilter-based sandbox. The
hardening of the WebProcess (and potentially PluginProcess, etc)
works by a combination of the two things:

- Blocking syscalls that are not used, reducing the size of the attack
surface.
- Trapping sensitive syscalls and delegating the execution of these
syscalls to a separated trusted process subject to a set of policies.

The initial implementation traps the open()-family of syscalls on WebKit
EFL's and Qt's WebProcess, but it could be easily used by any Linux port,
since the code is suppose to be Linux-compliant. The list of syscalls handled
by the broker process should definitely grow as we mature the
implementation. Other syscalls needs to be handled to get this sandbox
fully functional, like unlink(), mkdir(), etc.

The broker process should be initialized as early as possible on the
sandboxed process main() function, because it only does a fork(), which
is cheap on Linux. That also aims to minimize the resident memory footprint
of the broker process.

Opening of files for upload and saving downloads is not supported yet,
since it should be handled to the UIProcess in a similar fashion as
the Mac port does.

* PlatformEfl.cmake:
* Shared/linux/SeccompFilters/OpenSyscall.cpp: Added.
(WebKit):
(WebKit::OpenSyscall::createFromOpenatContext):
(WebKit::OpenSyscall::createFromCreatContext):
(WebKit::OpenSyscall::OpenSyscall):
(WebKit::OpenSyscall::setResult):
(WebKit::OpenSyscall::execute):
(WebKit::OpenSyscall::encode):
(WebKit::OpenSyscall::decode):
(WebKit::OpenSyscallResult::OpenSyscallResult):
(WebKit::OpenSyscallResult::~OpenSyscallResult):
(WebKit::OpenSyscallResult::encode):
(WebKit::OpenSyscallResult::decode):
* Shared/linux/SeccompFilters/OpenSyscall.h: Added.
(CoreIPC):
(WebKit):
(OpenSyscall):
(WebKit::OpenSyscall::setPath):
(WebKit::OpenSyscall::setFlags):
(WebKit::OpenSyscall::setMode):
(OpenSyscallResult):
(WebKit::OpenSyscallResult::fd):
(WebKit::OpenSyscallResult::errorNumber):
* Shared/linux/SeccompFilters/SeccompBroker.cpp: Added.
(WebKit):
(SeccompBrokerClient):
(WebKit::sendMessage):
(WebKit::receiveMessage):
(WebKit::SIGSYSHandler):
(WebKit::registerSIGSYSHandler):
(WebKit::SeccompBrokerClient::shared):
(WebKit::SeccompBrokerClient::SeccompBrokerClient):
(WebKit::SeccompBrokerClient::~SeccompBrokerClient):
(WebKit::SeccompBrokerClient::dispatch):
(WebKit::SeccompBrokerClient::handleIfOpeningOnlineCPUCount):
(WebKit::SeccompBroker::launchProcess):
(WebKit::SeccompBroker::initialize):
(WebKit::SeccompBroker::runLoop):
* Shared/linux/SeccompFilters/SeccompBroker.h: Added.
(WebKit):
(SeccompBroker):
(WebKit::SeccompBroker::setSyscallPolicy):
(WebKit::SeccompBroker::SeccompBroker):
* Shared/linux/SeccompFilters/SeccompFilters.cpp: Added.
(WebKit):
(WebKit::SeccompFilters::SeccompFilters):
(WebKit::SeccompFilters::~SeccompFilters):
(WebKit::SeccompFilters::addRule):
(WebKit::SeccompFilters::initialize):
* Shared/linux/SeccompFilters/SeccompFilters.h: Added.
(WebKit):
(SeccompFilters):
(WebKit::SeccompFilters::context):
(WebKit::SeccompFilters::platformInitialize):
* Shared/linux/SeccompFilters/SigactionSyscall.cpp: Added.
(WebKit):
(WebKit::SigactionSyscall::createFromContext):
* Shared/linux/SeccompFilters/SigactionSyscall.h: Added.
(WebKit):
(SigactionSyscall):
* Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp: Added.
(WebKit):
(WebKit::SigprocmaskSyscall::createFromContext):
* Shared/linux/SeccompFilters/SigprocmaskSyscall.h: Added.
(WebKit):
(SigprocmaskSyscall):
* Shared/linux/SeccompFilters/Syscall.cpp: Added.
(WebKit):
(WebKit::Syscall::createFromContext):
(WebKit::Syscall::createFromDecoder):
(WebKit::Syscall::Syscall):
(WebKit::SyscallResult::createFromDecoder):
(WebKit::SyscallResult::SyscallResult):
* Shared/linux/SeccompFilters/Syscall.h: Added.
(CoreIPC):
(WebKit):
(Syscall):
(WebKit::Syscall::~Syscall):
(WebKit::Syscall::type):
(WebKit::Syscall::setContext):
(WebKit::Syscall::context):
(SyscallResult):
(WebKit::SyscallResult::~SyscallResult):
(WebKit::SyscallResult::type):
* Shared/linux/SeccompFilters/SyscallPolicy.cpp: Added.
(WebKit):
(WebKit::removeTrailingSlash):
(WebKit::SyscallPolicy::hasPermissionForPath):
(WebKit::SyscallPolicy::addFilePermission):
(WebKit::SyscallPolicy::addDirectoryPermission):
(WebKit::SyscallPolicy::addDefaultWebProcessPolicy):
* Shared/linux/SeccompFilters/SyscallPolicy.h: Added.
(WebKit):
(SyscallPolicy):
* Target.pri:
* WebKit2.pri:
* WebProcess/efl/SeccompFiltersWebProcessEfl.cpp: Added.
(WebKit):
(WebKit::SeccompFiltersWebProcessEfl::SeccompFiltersWebProcessEfl):
(WebKit::SeccompFiltersWebProcessEfl::platformInitialize):
* WebProcess/efl/SeccompFiltersWebProcessEfl.h: Added.
(WebKit):
(SeccompFiltersWebProcessEfl):
* WebProcess/qt/SeccompFiltersWebProcessQt.cpp: Added.
(WebKit):
(WebKit::SeccompFiltersWebProcessQt::SeccompFiltersWebProcessQt):
(WebKit::SeccompFiltersWebProcessQt::platformInitialize):
* WebProcess/qt/SeccompFiltersWebProcessQt.h: Added.
(WebKit):
(SeccompFiltersWebProcessQt):
* WebProcess/qt/WebProcessQt.cpp:
(WebKit::WebProcess::platformInitializeWebProcess):
* WebProcess/soup/WebProcessSoup.cpp:
(WebKit::WebProcess::platformInitializeWebProcess):

Tools:

Add unit tests to verify if the handling of the open, openat, creat syscall
is being done right. We check if the Read/Write/ReadAndWrite permissions
are respected, if the canonical path is being resolved and if
the permissions are falling back to the topmost parent directory with a
policy set when the directory being opened has no policy.

We also test if any attempt of blocking SIGSYS is silently ignored.
SIGSYS cannot be blocked because in it's handler is where we hook
syscalls to the broker process.

Also added libseccomp to EFL's jhbuild to make the life of developers
willing to help easier.

* Scripts/webkitperl/FeatureList.pm:
* TestWebKitAPI/PlatformEfl.cmake:
* TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp: Added.
(TestWebKitAPI):
(SeccompEnvironment):
(TestWebKitAPI::SeccompEnvironment::SetUp):
(TestWebKitAPI::SeccompEnvironment::TearDown):
(TestWebKitAPI::dummyHandler):
(TestWebKitAPI::TEST):
(TestWebKitAPI::stressTest):
* efl/jhbuild.modules:
* qmake/mkspecs/features/features.pri:

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

37 files changed:
ChangeLog
Source/WebCore/ChangeLog
Source/WebCore/PlatformEfl.cmake
Source/WebKit2/ChangeLog
Source/WebKit2/PlatformEfl.cmake
Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/Syscall.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/Syscall.h [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.cpp [new file with mode: 0644]
Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.h [new file with mode: 0644]
Source/WebKit2/Target.pri
Source/WebKit2/WebKit2.pri
Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.cpp [new file with mode: 0644]
Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.h [new file with mode: 0644]
Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.cpp [new file with mode: 0644]
Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.h [new file with mode: 0644]
Source/WebKit2/WebProcess/qt/WebProcessQt.cpp
Source/WebKit2/WebProcess/soup/WebProcessSoup.cpp
Source/cmake/FindLibSeccomp.cmake [new file with mode: 0644]
Source/cmake/OptionsEfl.cmake
Source/cmake/WebKitFeatures.cmake
Source/cmakeconfig.h.cmake
Tools/ChangeLog
Tools/Scripts/webkitperl/FeatureList.pm
Tools/TestWebKitAPI/PlatformEfl.cmake
Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp [new file with mode: 0644]
Tools/efl/jhbuild.modules
Tools/qmake/mkspecs/features/features.pri

index f8cb03d..5c57fd5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2013-04-09  Thiago Marcos P. Santos  <thiago.santos@intel.com>
+
+        [WK2] Drop WebProcess capabilities on Linux using seccomp filters
+        https://bugs.webkit.org/show_bug.cgi?id=89875
+
+        Reviewed by Maciej Stachowiak.
+
+        Added the bits to EFL/CMake buildsystem to find the libseccomp
+        library.
+
+        * Source/cmake/FindLibSeccomp.cmake: Added.
+        * Source/cmake/OptionsEfl.cmake:
+        * Source/cmake/WebKitFeatures.cmake:
+        * Source/cmakeconfig.h.cmake:
+
 2013-04-09  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Unreviewed. Fix GTK+ 32 bit build.
index 08edd27..358d9b2 100644 (file)
@@ -1,3 +1,15 @@
+2013-04-09  Thiago Marcos P. Santos  <thiago.santos@intel.com>
+
+        [WK2] Drop WebProcess capabilities on Linux using seccomp filters
+        https://bugs.webkit.org/show_bug.cgi?id=89875
+
+        Reviewed by Maciej Stachowiak.
+
+        Make the DATA_DIR global since it is now needed for WebCore and WebKit2.
+        It is now used to set a sandbox policy for the EFL port.
+
+        * PlatformEfl.cmake:
+
 2013-04-08  Ryosuke Niwa  <rniwa@webkit.org>
 
         Remove WebCore.gyp/gypi
index 26727df..bd40368 100644 (file)
@@ -362,8 +362,6 @@ if (WTF_USE_3D_GRAPHICS)
     endif ()
 endif ()
 
-add_definitions(-DDATA_DIR="${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}")
-
 if (ENABLE_WEB_AUDIO)
     list(APPEND WebCore_INCLUDE_DIRECTORIES
         "${WEBCORE_DIR}/platform/audio/gstreamer"
index 916482a..c5590b6 100644 (file)
@@ -1,3 +1,151 @@
+2013-04-09  Thiago Marcos P. Santos  <thiago.santos@intel.com>
+
+        [WK2] Drop WebProcess capabilities on Linux using seccomp filters
+        https://bugs.webkit.org/show_bug.cgi?id=89875
+
+        Reviewed by Maciej Stachowiak.
+
+        Introduce the foundations of the SeccompFilter-based sandbox. The
+        hardening of the WebProcess (and potentially PluginProcess, etc)
+        works by a combination of the two things:
+
+        - Blocking syscalls that are not used, reducing the size of the attack
+        surface.
+        - Trapping sensitive syscalls and delegating the execution of these
+        syscalls to a separated trusted process subject to a set of policies.
+
+        The initial implementation traps the open()-family of syscalls on WebKit
+        EFL's and Qt's WebProcess, but it could be easily used by any Linux port,
+        since the code is suppose to be Linux-compliant. The list of syscalls handled
+        by the broker process should definitely grow as we mature the
+        implementation. Other syscalls needs to be handled to get this sandbox
+        fully functional, like unlink(), mkdir(), etc.
+
+        The broker process should be initialized as early as possible on the
+        sandboxed process main() function, because it only does a fork(), which
+        is cheap on Linux. That also aims to minimize the resident memory footprint
+        of the broker process.
+
+        Opening of files for upload and saving downloads is not supported yet,
+        since it should be handled to the UIProcess in a similar fashion as
+        the Mac port does.
+
+        * PlatformEfl.cmake:
+        * Shared/linux/SeccompFilters/OpenSyscall.cpp: Added.
+        (WebKit):
+        (WebKit::OpenSyscall::createFromOpenatContext):
+        (WebKit::OpenSyscall::createFromCreatContext):
+        (WebKit::OpenSyscall::OpenSyscall):
+        (WebKit::OpenSyscall::setResult):
+        (WebKit::OpenSyscall::execute):
+        (WebKit::OpenSyscall::encode):
+        (WebKit::OpenSyscall::decode):
+        (WebKit::OpenSyscallResult::OpenSyscallResult):
+        (WebKit::OpenSyscallResult::~OpenSyscallResult):
+        (WebKit::OpenSyscallResult::encode):
+        (WebKit::OpenSyscallResult::decode):
+        * Shared/linux/SeccompFilters/OpenSyscall.h: Added.
+        (CoreIPC):
+        (WebKit):
+        (OpenSyscall):
+        (WebKit::OpenSyscall::setPath):
+        (WebKit::OpenSyscall::setFlags):
+        (WebKit::OpenSyscall::setMode):
+        (OpenSyscallResult):
+        (WebKit::OpenSyscallResult::fd):
+        (WebKit::OpenSyscallResult::errorNumber):
+        * Shared/linux/SeccompFilters/SeccompBroker.cpp: Added.
+        (WebKit):
+        (SeccompBrokerClient):
+        (WebKit::sendMessage):
+        (WebKit::receiveMessage):
+        (WebKit::SIGSYSHandler):
+        (WebKit::registerSIGSYSHandler):
+        (WebKit::SeccompBrokerClient::shared):
+        (WebKit::SeccompBrokerClient::SeccompBrokerClient):
+        (WebKit::SeccompBrokerClient::~SeccompBrokerClient):
+        (WebKit::SeccompBrokerClient::dispatch):
+        (WebKit::SeccompBrokerClient::handleIfOpeningOnlineCPUCount):
+        (WebKit::SeccompBroker::launchProcess):
+        (WebKit::SeccompBroker::initialize):
+        (WebKit::SeccompBroker::runLoop):
+        * Shared/linux/SeccompFilters/SeccompBroker.h: Added.
+        (WebKit):
+        (SeccompBroker):
+        (WebKit::SeccompBroker::setSyscallPolicy):
+        (WebKit::SeccompBroker::SeccompBroker):
+        * Shared/linux/SeccompFilters/SeccompFilters.cpp: Added.
+        (WebKit):
+        (WebKit::SeccompFilters::SeccompFilters):
+        (WebKit::SeccompFilters::~SeccompFilters):
+        (WebKit::SeccompFilters::addRule):
+        (WebKit::SeccompFilters::initialize):
+        * Shared/linux/SeccompFilters/SeccompFilters.h: Added.
+        (WebKit):
+        (SeccompFilters):
+        (WebKit::SeccompFilters::context):
+        (WebKit::SeccompFilters::platformInitialize):
+        * Shared/linux/SeccompFilters/SigactionSyscall.cpp: Added.
+        (WebKit):
+        (WebKit::SigactionSyscall::createFromContext):
+        * Shared/linux/SeccompFilters/SigactionSyscall.h: Added.
+        (WebKit):
+        (SigactionSyscall):
+        * Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp: Added.
+        (WebKit):
+        (WebKit::SigprocmaskSyscall::createFromContext):
+        * Shared/linux/SeccompFilters/SigprocmaskSyscall.h: Added.
+        (WebKit):
+        (SigprocmaskSyscall):
+        * Shared/linux/SeccompFilters/Syscall.cpp: Added.
+        (WebKit):
+        (WebKit::Syscall::createFromContext):
+        (WebKit::Syscall::createFromDecoder):
+        (WebKit::Syscall::Syscall):
+        (WebKit::SyscallResult::createFromDecoder):
+        (WebKit::SyscallResult::SyscallResult):
+        * Shared/linux/SeccompFilters/Syscall.h: Added.
+        (CoreIPC):
+        (WebKit):
+        (Syscall):
+        (WebKit::Syscall::~Syscall):
+        (WebKit::Syscall::type):
+        (WebKit::Syscall::setContext):
+        (WebKit::Syscall::context):
+        (SyscallResult):
+        (WebKit::SyscallResult::~SyscallResult):
+        (WebKit::SyscallResult::type):
+        * Shared/linux/SeccompFilters/SyscallPolicy.cpp: Added.
+        (WebKit):
+        (WebKit::removeTrailingSlash):
+        (WebKit::SyscallPolicy::hasPermissionForPath):
+        (WebKit::SyscallPolicy::addFilePermission):
+        (WebKit::SyscallPolicy::addDirectoryPermission):
+        (WebKit::SyscallPolicy::addDefaultWebProcessPolicy):
+        * Shared/linux/SeccompFilters/SyscallPolicy.h: Added.
+        (WebKit):
+        (SyscallPolicy):
+        * Target.pri:
+        * WebKit2.pri:
+        * WebProcess/efl/SeccompFiltersWebProcessEfl.cpp: Added.
+        (WebKit):
+        (WebKit::SeccompFiltersWebProcessEfl::SeccompFiltersWebProcessEfl):
+        (WebKit::SeccompFiltersWebProcessEfl::platformInitialize):
+        * WebProcess/efl/SeccompFiltersWebProcessEfl.h: Added.
+        (WebKit):
+        (SeccompFiltersWebProcessEfl):
+        * WebProcess/qt/SeccompFiltersWebProcessQt.cpp: Added.
+        (WebKit):
+        (WebKit::SeccompFiltersWebProcessQt::SeccompFiltersWebProcessQt):
+        (WebKit::SeccompFiltersWebProcessQt::platformInitialize):
+        * WebProcess/qt/SeccompFiltersWebProcessQt.h: Added.
+        (WebKit):
+        (SeccompFiltersWebProcessQt):
+        * WebProcess/qt/WebProcessQt.cpp:
+        (WebKit::WebProcess::platformInitializeWebProcess):
+        * WebProcess/soup/WebProcessSoup.cpp:
+        (WebKit::WebProcess::platformInitializeWebProcess):
+
 2013-04-08  Grzegorz Czajkowski  <g.czajkowski@samsung.com>
 
         [WK2][EFL] Mark not implemented methods in TextCheckerEfl.
index 784dcd2..5608a9e 100644 (file)
@@ -27,6 +27,14 @@ list(APPEND WebKit2_SOURCES
     Shared/efl/ProcessExecutablePathEfl.cpp
     Shared/efl/WebEventFactory.cpp
 
+    Shared/linux/SeccompFilters/OpenSyscall.cpp
+    Shared/linux/SeccompFilters/SigactionSyscall.cpp
+    Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp
+    Shared/linux/SeccompFilters/SeccompBroker.cpp
+    Shared/linux/SeccompFilters/SeccompFilters.cpp
+    Shared/linux/SeccompFilters/Syscall.cpp
+    Shared/linux/SeccompFilters/SyscallPolicy.cpp
+
     Shared/linux/WebMemorySamplerLinux.cpp
 
     Shared/soup/PlatformCertificateInfo.cpp
@@ -149,6 +157,7 @@ list(APPEND WebKit2_SOURCES
     WebProcess/WebPage/efl/WebInspectorEfl.cpp
     WebProcess/WebPage/efl/WebPageEfl.cpp
 
+    WebProcess/efl/SeccompFiltersWebProcessEfl.cpp
     WebProcess/efl/WebProcessMainEfl.cpp
 
     WebProcess/soup/WebProcessSoup.cpp
@@ -255,6 +264,21 @@ list(APPEND WebProcess_LIBRARIES
     ${SQLITE_LIBRARIES}
 )
 
+if (ENABLE_SECCOMP_FILTERS)
+    list(APPEND WebKit2_LIBRARIES
+        ${LIBSECCOMP_LIBRARIES}
+    )
+    list(APPEND WebKit2_INCLUDE_DIRECTORIES
+        ${LIBSECCOMP_INCLUDE_DIRS}
+    )
+
+    # If building with jhbuild, add the root build directory to the
+    # filesystem access policy.
+    if (IS_DIRECTORY ${CMAKE_SOURCE_DIR}/WebKitBuild/Dependencies)
+        add_definitions(-DSOURCE_DIR=\"${CMAKE_SOURCE_DIR}\")
+    endif ()
+endif ()
+
 if (ENABLE_ECORE_X)
     list(APPEND WebProcess_LIBRARIES
         ${ECORE_X_LIBRARIES}
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.cpp
new file mode 100644 (file)
index 0000000..2be4938
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "OpenSyscall.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "ArgumentCoders.h"
+#include "SyscallPolicy.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <seccomp.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+COMPILE_ASSERT(!O_RDONLY, O_RDONLY);
+COMPILE_ASSERT(O_WRONLY == 1, O_WRONLY);
+COMPILE_ASSERT(O_RDWR == 2, O_RDWR);
+
+PassOwnPtr<Syscall> OpenSyscall::createFromOpenatContext(mcontext_t* context)
+{
+    OwnPtr<OpenSyscall> open = adoptPtr(new OpenSyscall(0));
+
+    open->setFlags(context->gregs[REG_ARG2]);
+    open->setMode(context->gregs[REG_ARG3]);
+    open->setContext(context);
+
+    int fd = context->gregs[REG_ARG0];
+    char* path = reinterpret_cast<char*>(context->gregs[REG_ARG1]);
+
+    if (path[0] == '/') {
+        open->setPath(path);
+        return open.release();
+    }
+
+    struct stat pathStat;
+    if (fstat(fd, &pathStat) == -1) {
+        context->gregs[REG_SYSCALL] = -errno;
+        return nullptr;
+    }
+
+    if (!S_ISDIR(pathStat.st_mode)) {
+        context->gregs[REG_SYSCALL] = -ENOTDIR;
+        return nullptr;
+    }
+
+    char fdLinkPath[32];
+    snprintf(fdLinkPath, sizeof(fdLinkPath), "/proc/self/fd/%d", fd);
+
+    char fdPath[PATH_MAX];
+    ssize_t size = readlink(fdLinkPath, fdPath, sizeof(fdPath) - 1);
+    if (size == -1) {
+        context->gregs[REG_SYSCALL] = -errno;
+        return nullptr;
+    }
+
+    // The "+ 2" here stands for the '/' and null terminator.
+    if (size + strlen(path) + 2 > PATH_MAX) {
+        context->gregs[REG_SYSCALL] = -ENAMETOOLONG;
+        return nullptr;
+    }
+
+    sprintf(&fdPath[size], "/%s", path);
+    open->setPath(fdPath);
+
+    return open.release();
+}
+
+PassOwnPtr<Syscall> OpenSyscall::createFromCreatContext(mcontext_t* context)
+{
+    OpenSyscall* open = new OpenSyscall(0);
+
+    open->setPath(CString(reinterpret_cast<char*>(context->gregs[REG_ARG0])));
+    open->setFlags(O_CREAT | O_WRONLY | O_TRUNC);
+    open->setMode(context->gregs[REG_ARG1]);
+    open->setContext(context);
+
+    return adoptPtr(open);
+}
+
+OpenSyscall::OpenSyscall(mcontext_t* context)
+    : Syscall(__NR_open, context)
+    , m_flags(0)
+    , m_mode(0)
+{
+    if (!context)
+        return;
+
+    m_path = CString(reinterpret_cast<char*>(context->gregs[REG_ARG0]));
+    m_flags = context->gregs[REG_ARG1];
+    m_mode = context->gregs[REG_ARG2];
+}
+
+void OpenSyscall::setResult(const SyscallResult* result)
+{
+    ASSERT(context() && result->type() == type());
+
+    const OpenSyscallResult* openResult = static_cast<const OpenSyscallResult*>(result);
+
+    if (openResult->fd() >= 0)
+        context()->gregs[REG_SYSCALL] = dup(openResult->fd());
+    else
+        context()->gregs[REG_SYSCALL] = -openResult->errorNumber();
+}
+
+PassOwnPtr<SyscallResult> OpenSyscall::execute(const SyscallPolicy& policy)
+{
+    if (!strncmp("/proc/self/", m_path.data(), 11)) {
+        String resolvedSelfPath = ASCIILiteral("/proc/") + String::number(getppid()) + &m_path.data()[10];
+        m_path = resolvedSelfPath.utf8().data();
+    }
+
+    SyscallPolicy::Permission permission = SyscallPolicy::NotAllowed;
+    if (m_flags & O_RDWR)
+        permission = static_cast<SyscallPolicy::Permission>(permission | SyscallPolicy::ReadAndWrite);
+    else if (m_flags & O_WRONLY)
+        permission = static_cast<SyscallPolicy::Permission>(permission | SyscallPolicy::Write);
+    else
+        permission = static_cast<SyscallPolicy::Permission>(permission | SyscallPolicy::Read);
+
+    // Create a file implies write permission on the directory.
+    if (m_flags & O_CREAT || m_flags & O_EXCL)
+        permission = static_cast<SyscallPolicy::Permission>(permission | SyscallPolicy::Write);
+
+    if (!policy.hasPermissionForPath(m_path.data(), permission))
+        return adoptPtr(new OpenSyscallResult(-1, EACCES));
+
+    // Permission granted, execute the syscall. The syscall might still
+    // fail because of hard permissions enforced by the filesystem and
+    // things like if the entry does not exist.
+    int fd = open(m_path.data(), m_flags, m_mode);
+    int errorNumber = fd == -1 ? errno : 0;
+
+    return adoptPtr(new OpenSyscallResult(fd, errorNumber));
+}
+
+void OpenSyscall::encode(CoreIPC::ArgumentEncoder& encoder) const
+{
+    encoder << type();
+    encoder << m_path;
+    encoder << m_flags;
+    encoder << m_mode;
+}
+
+bool OpenSyscall::decode(CoreIPC::ArgumentDecoder* decoder)
+{
+    // m_type already decoded by the parent class.
+
+    if (!decoder->decode(m_path))
+        return false;
+    if (!decoder->decode(m_flags))
+        return false;
+
+    return decoder->decode(m_mode);
+}
+
+OpenSyscallResult::OpenSyscallResult(int fd, int errorNumber)
+    : SyscallResult(__NR_open)
+    , m_fd(fd)
+    , m_errorNumber(errorNumber)
+{
+}
+
+OpenSyscallResult::~OpenSyscallResult()
+{
+    if (m_fd >= 0)
+        close(m_fd);
+}
+
+void OpenSyscallResult::encode(CoreIPC::ArgumentEncoder& encoder) const
+{
+    encoder << type();
+
+    if (m_fd >= 0) {
+        CoreIPC::Attachment attachment(m_fd);
+        encoder.addAttachment(attachment);
+    }
+
+    encoder << m_errorNumber;
+}
+
+bool OpenSyscallResult::decode(CoreIPC::ArgumentDecoder* decoder, int fd)
+{
+    if (fd >= 0)
+        m_fd = fd;
+
+    return decoder->decode(m_errorNumber);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.h b/Source/WebKit2/Shared/linux/SeccompFilters/OpenSyscall.h
new file mode 100644 (file)
index 0000000..c303588
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpenSyscall_h
+#define OpenSyscall_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "Syscall.h"
+#include <wtf/text/CString.h>
+
+namespace CoreIPC {
+class ArgumentDecoder;
+class ArgumentEncoder;
+}
+
+namespace WebKit {
+
+class OpenSyscall : public Syscall {
+public:
+    static PassOwnPtr<Syscall> createFromOpenatContext(mcontext_t*);
+    static PassOwnPtr<Syscall> createFromCreatContext(mcontext_t*);
+
+    explicit OpenSyscall(mcontext_t*);
+
+    void setPath(const CString& path) { m_path = path; };
+    void setFlags(const int flags) { m_flags = flags; };
+    void setMode(const mode_t mode) { m_mode = mode; };
+
+    // Syscall implementation.
+    virtual void setResult(const SyscallResult*);
+    virtual PassOwnPtr<SyscallResult> execute(const SyscallPolicy&);
+    virtual void encode(CoreIPC::ArgumentEncoder&) const;
+    virtual bool decode(CoreIPC::ArgumentDecoder*);
+
+private:
+    CString m_path;
+    int m_flags;
+    mode_t m_mode;
+};
+
+class OpenSyscallResult : public SyscallResult {
+public:
+    OpenSyscallResult(int fd, int errorNumber);
+    ~OpenSyscallResult();
+
+    int fd() const { return m_fd; }
+    int errorNumber() const { return m_errorNumber; }
+
+    // SyscallResult implementation.
+    virtual void encode(CoreIPC::ArgumentEncoder&) const;
+    virtual bool decode(CoreIPC::ArgumentDecoder*, int fd);
+
+private:
+    int m_fd;
+    int m_errorNumber;
+};
+
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // OpenSyscall_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.cpp
new file mode 100644 (file)
index 0000000..e14545d
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SeccompBroker.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "ArgumentCoders.h"
+#include "Syscall.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <seccomp.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef SYS_SECCOMP
+#define SYS_SECCOMP 1
+#endif
+
+static const size_t messageMaxSize = 4096;
+static const char onlineCPUCountPath[] = "/sys/devices/system/cpu/online";
+
+namespace WebKit {
+
+class SeccompBrokerClient {
+public:
+    static SeccompBrokerClient& shared(int socket = -1);
+    ~SeccompBrokerClient();
+
+    void dispatch(Syscall*) const;
+
+    bool handleIfOpeningOnlineCPUCount(mcontext_t*) const;
+
+private:
+    SeccompBrokerClient(int socket);
+
+    int m_socket;
+    int m_onlineCPUCountFd;
+
+    mutable Mutex m_socketLock;
+};
+
+static ssize_t sendMessage(int socket, void* data, size_t size, int fd = -1)
+{
+    ASSERT(size <= messageMaxSize);
+
+    struct msghdr message;
+    memset(&message, 0, sizeof(message));
+
+    struct iovec iov;
+    memset(&iov, 0, sizeof(iov));
+    iov.iov_base = data;
+    iov.iov_len = size;
+
+    message.msg_iov = &iov;
+    message.msg_iovlen = 1;
+
+    char control[CMSG_SPACE(sizeof(fd))];
+    if (fd >= 0) {
+        message.msg_control = control;
+        message.msg_controllen = sizeof(control);
+        memset(message.msg_control, 0, message.msg_controllen);
+
+        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message);
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+
+        memmove(CMSG_DATA(cmsg), &fd, sizeof(fd));
+    }
+
+    return sendmsg(socket, &message, 0);
+}
+
+static ssize_t receiveMessage(int socket, void* data, size_t size, int* fd = 0)
+{
+    struct msghdr message;
+    memset(&message, 0, sizeof(message));
+
+    struct iovec iov;
+    memset(&iov, 0, sizeof(iov));
+    iov.iov_base = data;
+    iov.iov_len = size;
+
+    message.msg_iov = &iov;
+    message.msg_iovlen = 1;
+
+    char control[CMSG_SPACE(sizeof(fd))];
+    message.msg_control = control;
+    message.msg_controllen = sizeof(control);
+    memset(message.msg_control, 0, message.msg_controllen);
+
+    ssize_t receivedBytes = recvmsg(socket, &message, 0);
+
+    if (fd && receivedBytes > 0) {
+        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message);
+        if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+            memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
+        else
+            *fd = -1;
+    }
+
+    return receivedBytes >= 0 ? receivedBytes : -errno;
+}
+
+static void SIGSYSHandler(int signal, siginfo_t* info, void* data)
+{
+    if (signal != SIGSYS || info->si_code != SYS_SECCOMP)
+        CRASH();
+
+    ucontext_t* ucontext = static_cast<ucontext_t*>(data);
+    if (!ucontext)
+        CRASH();
+
+    SeccompBrokerClient* client = &SeccompBrokerClient::shared();
+
+    if (client->handleIfOpeningOnlineCPUCount(&ucontext->uc_mcontext))
+        return;
+
+    // createFromContext might return a nullptr if it is able to resolve the
+    // syscall locally without sending it to the broker process. In this case,
+    // we just return. Examples of locally resolved syscalls are the ones
+    // with cached resources and invalid arguments.
+    OwnPtr<Syscall> syscall = Syscall::createFromContext(ucontext);
+    if (!syscall)
+        return;
+
+    client->dispatch(syscall.get());
+}
+
+static void registerSIGSYSHandler()
+{
+    struct sigaction action;
+    memset(&action, 0, sizeof(action));
+    action.sa_sigaction = &SIGSYSHandler;
+    action.sa_flags = SA_SIGINFO | SA_NODEFER;
+
+    if (sigaction(SIGSYS, &action, 0) < 0)
+        CRASH();
+
+    sigset_t mask;
+    sigemptyset(&mask);
+    sigaddset(&mask, SIGSYS);
+
+    if (sigprocmask(SIG_UNBLOCK, &mask, 0) < 0)
+        CRASH();
+}
+
+SeccompBrokerClient& SeccompBrokerClient::shared(int socket)
+{
+    DEFINE_STATIC_LOCAL(SeccompBrokerClient, brokerClient, (socket));
+
+    return brokerClient;
+}
+
+SeccompBrokerClient::SeccompBrokerClient(int socket)
+    : m_socket(socket)
+    , m_onlineCPUCountFd(open(onlineCPUCountPath, O_RDONLY))
+{
+    ASSERT(m_socket >= 0 && m_onlineCPUCountFd >= 0);
+}
+
+SeccompBrokerClient::~SeccompBrokerClient()
+{
+    close(m_socket);
+    close(m_onlineCPUCountFd);
+}
+
+void SeccompBrokerClient::dispatch(Syscall* syscall) const
+{
+    OwnPtr<CoreIPC::ArgumentEncoder> encoder = CoreIPC::ArgumentEncoder::create();
+    encoder->encode(*syscall);
+
+    char buffer[messageMaxSize];
+    ssize_t receivedBytes = 0;
+    int fd = -1;
+
+    m_socketLock.lock();
+
+    if (sendMessage(m_socket, encoder->buffer(), encoder->bufferSize()) < 0)
+        CRASH();
+
+    while (true) {
+        receivedBytes = receiveMessage(m_socket, &buffer, sizeof(buffer), &fd);
+        if (receivedBytes > 0)
+            break;
+
+        if (receivedBytes != -EINTR)
+            CRASH();
+    }
+
+    m_socketLock.unlock();
+
+    OwnPtr<CoreIPC::ArgumentDecoder> decoder = CoreIPC::ArgumentDecoder::create((const uint8_t*) buffer, receivedBytes);
+    OwnPtr<SyscallResult> result = SyscallResult::createFromDecoder(decoder.get(), fd);
+    if (!result)
+        CRASH();
+
+    syscall->setResult(result.get());
+}
+
+bool SeccompBrokerClient::handleIfOpeningOnlineCPUCount(mcontext_t* context) const
+{
+    if (context->gregs[REG_SYSCALL] != __NR_open)
+        return false;
+
+    const char *path = reinterpret_cast<char*>(context->gregs[REG_ARG0]);
+    if (strcmp(onlineCPUCountPath, path))
+        return false;
+
+    // Malloc will eventually check the number of online CPUs (i.e being
+    // scheduled) present on the system by opening a special file. If it does
+    // that in the middle of the SIGSYS signal handler, it might trigger a
+    // recursive attempt of proxying the open() syscall to the broker.
+    // Because of that, we cache this resource.
+    context->gregs[REG_SYSCALL] = dup(m_onlineCPUCountFd);
+
+    return true;
+}
+
+void SeccompBroker::launchProcess(SeccompFilters* filters, const SyscallPolicy& policy)
+{
+    static bool initialized = false;
+    if (initialized)
+        return;
+
+    // The sigprocmask filters bellow are needed to trap sigprocmask()
+    // so we can prevent the running processes from blocking SIGSYS.
+    filters->addRule("sigprocmask", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIG_BLOCK,
+        1, SeccompFilters::NotEqual, 0);
+    filters->addRule("sigprocmask", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIG_SETMASK,
+        1, SeccompFilters::NotEqual, 0);
+    filters->addRule("rt_sigprocmask", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIG_BLOCK,
+        1, SeccompFilters::NotEqual, 0);
+    filters->addRule("rt_sigprocmask", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIG_SETMASK,
+        1, SeccompFilters::NotEqual, 0);
+
+    // The sigaction filters bellow are needed to trap sigaction()
+    // so we can prevent the running processes from handling SIGSYS.
+    filters->addRule("sigaction", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIGSYS);
+    filters->addRule("rt_sigaction", SeccompFilters::Trap,
+        0, SeccompFilters::Equal, SIGSYS);
+
+    SeccompBroker seccompBroker;
+    seccompBroker.setSyscallPolicy(policy);
+    seccompBroker.initialize();
+
+    initialized = true;
+}
+
+void SeccompBroker::initialize()
+{
+    int sockets[2];
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
+        CRASH();
+
+    pid_t pid = fork();
+    if (pid) { // Sandboxed process.
+        close(sockets[1]);
+        SeccompBrokerClient::shared(sockets[0]);
+        registerSIGSYSHandler();
+    } else { // Broker.
+        // TODO: The broker should setup seccomp filters
+        // for itself and block everything else other than
+        // the minimal set of syscalls needed to execute the
+        // syscalls it is suppose to proxy.
+        close(sockets[0]);
+        runLoop(sockets[1]);
+    }
+}
+
+NO_RETURN void SeccompBroker::runLoop(int socket)
+{
+#ifndef NDEBUG
+    int i = STDERR_FILENO + 1;
+#else
+    int i = 0;
+#endif
+    // Close all inherited file descriptors other
+    // than the socket to the sandboxed process.
+    for (; i < FD_SETSIZE; ++i)
+        if (i != socket)
+            close(i);
+
+    while (true) {
+        char buffer[messageMaxSize];
+        ssize_t receivedBytes = receiveMessage(socket, &buffer, sizeof(buffer));
+        if (receivedBytes == -EINTR)
+            continue;
+
+        if (receivedBytes <= 0)
+            exit(receivedBytes ? EXIT_FAILURE : EXIT_SUCCESS);
+
+        OwnPtr<CoreIPC::ArgumentDecoder> decoder = CoreIPC::ArgumentDecoder::create((const uint8_t*) buffer, receivedBytes);
+        OwnPtr<Syscall> syscall = Syscall::createFromDecoder(decoder.get());
+        if (!syscall)
+            exit(EXIT_FAILURE);
+
+        OwnPtr<SyscallResult> result = syscall->execute(m_policy);
+        if (!result)
+            exit(EXIT_FAILURE);
+
+        OwnPtr<CoreIPC::ArgumentEncoder> encoder = CoreIPC::ArgumentEncoder::create();
+        encoder->encode(*result);
+
+        Vector<CoreIPC::Attachment> attachments = encoder->releaseAttachments();
+        int fd = attachments.size() == 1 ? attachments[0].fileDescriptor() : -1;
+
+        // The client is down, the broker should go away.
+        if (sendMessage(socket, encoder->buffer(), encoder->bufferSize(), fd) < 0)
+            exit(EXIT_SUCCESS);
+    }
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.h b/Source/WebKit2/Shared/linux/SeccompFilters/SeccompBroker.h
new file mode 100644 (file)
index 0000000..a75c86b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SeccompBroker_h
+#define SeccompBroker_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "SeccompFilters.h"
+#include "Syscall.h"
+#include "SyscallPolicy.h"
+#include <signal.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+namespace WebKit {
+
+class SeccompBroker {
+    WTF_MAKE_NONCOPYABLE(SeccompBroker);
+
+public:
+    static void launchProcess(SeccompFilters*, const SyscallPolicy&);
+
+    void initialize();
+    void setSyscallPolicy(const SyscallPolicy& policy) { m_policy = policy; }
+
+private:
+    SeccompBroker() { }
+
+    void runLoop(int socket);
+
+    SyscallPolicy m_policy;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SeccompBroker_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.cpp
new file mode 100644 (file)
index 0000000..9491bd1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SeccompFilters.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "SeccompBroker.h"
+#include <seccomp.h>
+#include <wtf/Assertions.h>
+
+namespace WebKit {
+
+COMPILE_ASSERT(SeccompFilters::Allow == SCMP_ACT_ALLOW, Allow);
+COMPILE_ASSERT(SeccompFilters::Kill == SCMP_ACT_KILL, Kill);
+COMPILE_ASSERT(SeccompFilters::Trap == SCMP_ACT_TRAP, Trap);
+
+COMPILE_ASSERT(SeccompFilters::NotSet == static_cast<SeccompFilters::Operator>(_SCMP_CMP_MIN), NotSet);
+COMPILE_ASSERT(SeccompFilters::NotEqual == static_cast<SeccompFilters::Operator>(SCMP_CMP_NE), NotEqual);
+COMPILE_ASSERT(SeccompFilters::Equal == static_cast<SeccompFilters::Operator>(SCMP_CMP_EQ), Equal);
+
+COMPILE_ASSERT(sizeof(scmp_datum_t) == sizeof(long long), scmp_datum_t);
+
+SeccompFilters::SeccompFilters(Action defaultAction)
+    : m_context(seccomp_init(defaultAction))
+    , m_initialized(false)
+{
+    if (!m_context)
+        CRASH();
+}
+
+SeccompFilters::~SeccompFilters()
+{
+    seccomp_release(m_context);
+}
+
+void SeccompFilters::addRule(const char* syscallName, Action action,
+    unsigned argNum1, Operator operator1, long long data1,
+    unsigned argNum2, Operator operator2, long long data2)
+{
+    int syscall = seccomp_syscall_resolve_name(syscallName);
+    if (syscall == __NR_SCMP_ERROR)
+        CRASH();
+
+    int result;
+    if (operator2 != NotSet)
+        result = seccomp_rule_add(m_context, action, syscall, 2,
+            SCMP_CMP(argNum1, static_cast<scmp_compare>(operator1), data1, 0),
+            SCMP_CMP(argNum2, static_cast<scmp_compare>(operator2), data2, 0));
+    else if (operator1 != NotSet)
+        result = seccomp_rule_add(m_context, action, syscall, 1,
+            SCMP_CMP(argNum1, static_cast<scmp_compare>(operator1), data1, 0));
+    else
+        result = seccomp_rule_add(m_context, action, syscall, 0);
+
+    if (result < 0)
+        CRASH();
+}
+
+void SeccompFilters::initialize()
+{
+    if (m_initialized)
+        return;
+
+    // Implement this is not required in case we are just
+    // setting filters. This is a good place to create the
+    // broker and syscall policy otherwise.
+    platformInitialize();
+
+    if (seccomp_load(m_context) < 0)
+        CRASH();
+
+    m_initialized = true;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.h b/Source/WebKit2/Shared/linux/SeccompFilters/SeccompFilters.h
new file mode 100644 (file)
index 0000000..d49e1fb
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SeccompFilters_h
+#define SeccompFilters_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <wtf/Noncopyable.h>
+
+namespace WebKit {
+
+class SeccompFilters {
+    WTF_MAKE_NONCOPYABLE(SeccompFilters);
+
+public:
+    enum Action {
+        Allow = 0x7fff0000U,
+        Kill  = 0x00000000U,
+        Trap  = 0x00030000U
+    };
+
+    enum Operator {
+        NotSet   = 0,
+        NotEqual = 1,
+        Equal    = 4
+    };
+
+    explicit SeccompFilters(Action defaultAction);
+    virtual ~SeccompFilters();
+
+    void* context() { return m_context; };
+
+    void addRule(const char* syscallName, Action,
+        unsigned argNum1 = 0, Operator operator1 = NotSet, long long data1 = 0,
+        unsigned argNum2 = 0, Operator operator2 = NotSet, long long data2 = 0);
+
+    void initialize();
+
+private:
+    virtual void platformInitialize() { }
+
+    typedef void *HANDLE;
+
+    HANDLE m_context;
+    bool m_initialized;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SeccompFilters_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.cpp
new file mode 100644 (file)
index 0000000..ec12f30
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SigactionSyscall.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <signal.h>
+
+namespace WebKit {
+
+PassOwnPtr<Syscall> SigactionSyscall::createFromContext(mcontext_t* context)
+{
+    // We just ignore any attempt of installing a handler for SIGSYS since this
+    // signal is necessary for the sandbox to work.
+    ASSERT(context && context->gregs[REG_ARG0] == SIGSYS);
+
+    context->gregs[REG_SYSCALL] = 0;
+
+    return nullptr;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.h b/Source/WebKit2/Shared/linux/SeccompFilters/SigactionSyscall.h
new file mode 100644 (file)
index 0000000..90476d4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SigactionSyscall_h
+#define SigactionSyscall_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "Syscall.h"
+
+namespace WebKit {
+
+struct SigactionSyscall {
+    static PassOwnPtr<Syscall> createFromContext(mcontext_t*);
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SigactionSyscall_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp
new file mode 100644 (file)
index 0000000..242b80d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SigprocmaskSyscall.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <signal.h>
+#include <string.h>
+
+namespace WebKit {
+
+PassOwnPtr<Syscall> SigprocmaskSyscall::createFromContext(ucontext_t* ucontext)
+{
+    // This syscall is never proxied to the broker process and resolved locally.
+    // What we do here is silently remove SIGSYS from the signal set so no
+    // thread will ever be able to block it.
+    ASSERT(ucontext);
+
+    mcontext_t mcontext = ucontext->uc_mcontext;
+    int how = mcontext.gregs[REG_ARG0];
+    sigset_t* set = reinterpret_cast<sigset_t*>(mcontext.gregs[REG_ARG1]);
+    sigset_t* oldSet = reinterpret_cast<sigset_t*>(mcontext.gregs[REG_ARG2]);
+
+    if (oldSet)
+        memcpy(oldSet, &ucontext->uc_sigmask, sizeof(sigset_t));
+
+    if (how == SIG_SETMASK)
+        memcpy(&ucontext->uc_sigmask, set, sizeof(sigset_t));
+    else
+        sigorset(&ucontext->uc_sigmask, set, &ucontext->uc_sigmask);
+
+    sigdelset(&ucontext->uc_sigmask, SIGSYS);
+    mcontext.gregs[REG_SYSCALL] = 0;
+
+    return nullptr;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.h b/Source/WebKit2/Shared/linux/SeccompFilters/SigprocmaskSyscall.h
new file mode 100644 (file)
index 0000000..4d0453a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SigprocmaskSyscall_h
+#define SigprocmaskSyscall_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "Syscall.h"
+
+namespace WebKit {
+
+struct SigprocmaskSyscall {
+    static PassOwnPtr<Syscall> createFromContext(ucontext_t*);
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SigprocmaskSyscall_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/Syscall.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/Syscall.cpp
new file mode 100644 (file)
index 0000000..b39cab5
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Syscall.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "ArgumentCoders.h"
+#include "OpenSyscall.h"
+#include "SigactionSyscall.h"
+#include "SigprocmaskSyscall.h"
+#include <seccomp.h>
+
+namespace WebKit {
+
+PassOwnPtr<Syscall> Syscall::createFromContext(ucontext_t* ucontext)
+{
+    mcontext_t* mcontext = &ucontext->uc_mcontext;
+
+    switch (mcontext->gregs[REG_SYSCALL]) {
+    case __NR_open:
+        return adoptPtr(new OpenSyscall(mcontext));
+    case __NR_openat:
+        return OpenSyscall::createFromOpenatContext(mcontext);
+    case __NR_creat:
+        return OpenSyscall::createFromCreatContext(mcontext);
+    case __NR_sigprocmask:
+    case __NR_rt_sigprocmask:
+        return SigprocmaskSyscall::createFromContext(ucontext);
+    case __NR_sigaction:
+    case __NR_rt_sigaction:
+        return SigactionSyscall::createFromContext(mcontext);
+    default:
+        CRASH();
+    }
+
+    return nullptr;
+}
+
+PassOwnPtr<Syscall> Syscall::createFromDecoder(CoreIPC::ArgumentDecoder* decoder)
+{
+    int type;
+    if (!decoder->decode(type))
+        return nullptr;
+
+    OwnPtr<Syscall> syscall;
+    if (type == __NR_open)
+        syscall = adoptPtr(new OpenSyscall(0));
+
+    if (!syscall->decode(decoder))
+        return nullptr;
+
+    return syscall.release();
+}
+
+Syscall::Syscall(int type, mcontext_t* context)
+    : m_type(type)
+    , m_context(context)
+{
+}
+
+PassOwnPtr<SyscallResult> SyscallResult::createFromDecoder(CoreIPC::ArgumentDecoder* decoder, int fd)
+{
+    int type;
+    if (!decoder->decode(type))
+        return nullptr;
+
+    OwnPtr<SyscallResult> result;
+    if (type == __NR_open)
+        result = adoptPtr(new OpenSyscallResult(-1, 0));
+
+    if (!result->decode(decoder, fd))
+        return nullptr;
+
+    return result.release();
+}
+
+SyscallResult::SyscallResult(int type)
+    : m_type(type)
+{
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/Syscall.h b/Source/WebKit2/Shared/linux/SeccompFilters/Syscall.h
new file mode 100644 (file)
index 0000000..e7f0b4b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Syscall_h
+#define Syscall_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#if CPU(X86_64)
+#define REG_SYSCALL REG_RAX
+#define REG_ARG0    REG_RDI
+#define REG_ARG1    REG_RSI
+#define REG_ARG2    REG_RDX
+#define REG_ARG3    REG_R10
+#elif CPU(X86)
+#define REG_SYSCALL REG_EAX
+#define REG_ARG0    REG_EBX
+#define REG_ARG1    REG_ECX
+#define REG_ARG2    REG_EDX
+#define REG_ARG3    REG_ESI
+#else
+#error "CPU not supported."
+#endif
+
+#include <signal.h>
+#include <sys/types.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace CoreIPC {
+class ArgumentDecoder;
+class ArgumentEncoder;
+}
+
+namespace WebKit {
+
+class SyscallResult;
+class SyscallPolicy;
+
+class Syscall {
+    WTF_MAKE_NONCOPYABLE(Syscall);
+
+public:
+    virtual ~Syscall() { }
+
+    static PassOwnPtr<Syscall> createFromContext(ucontext_t*);
+    static PassOwnPtr<Syscall> createFromDecoder(CoreIPC::ArgumentDecoder*);
+
+    int type() const { return m_type; }
+
+    void setContext(mcontext_t* context) { m_context = context; }
+    mcontext_t* context() const { return m_context; }
+
+    virtual void setResult(const SyscallResult*) = 0;
+    virtual PassOwnPtr<SyscallResult> execute(const SyscallPolicy&) = 0;
+    virtual void encode(CoreIPC::ArgumentEncoder&) const = 0;
+    virtual bool decode(CoreIPC::ArgumentDecoder*) = 0;
+
+protected:
+    Syscall(int type, mcontext_t*);
+
+private:
+    int m_type;
+    mcontext_t* m_context;
+};
+
+class SyscallResult {
+    WTF_MAKE_NONCOPYABLE(SyscallResult);
+
+public:
+    virtual ~SyscallResult() { }
+
+    static PassOwnPtr<SyscallResult> createFromDecoder(CoreIPC::ArgumentDecoder*, int fd);
+
+    int type() const { return m_type; }
+
+    virtual void encode(CoreIPC::ArgumentEncoder&) const = 0;
+    virtual bool decode(CoreIPC::ArgumentDecoder*, int fd=-1) = 0;
+
+protected:
+    SyscallResult(int type);
+
+private:
+    int m_type;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // Syscall_h
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.cpp b/Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.cpp
new file mode 100644 (file)
index 0000000..089c4bb
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SyscallPolicy.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "WebProcessCreationParameters.h"
+#include <libgen.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebKit {
+
+static String removeTrailingSlash(const String& path)
+{
+    if (path.endsWith('/'))
+        return path.left(path.length() - 1);
+
+    return path;
+}
+
+bool SyscallPolicy::hasPermissionForPath(const char* path, Permission permission) const
+{
+    // The root directory policy needs to be set because it is the
+    // ultimate fallback when rewinding directories.
+    ASSERT(m_directoryPermission.contains("/"));
+
+    if (permission == NotAllowed)
+        return false;
+
+    char* basePath = strdup(path);
+    char* canonicalPath = canonicalize_file_name(basePath);
+
+    while (canonicalPath) {
+        struct stat pathStat;
+        if (stat(canonicalPath, &pathStat) == -1) {
+            free(basePath);
+            free(canonicalPath);
+            return false;
+        }
+
+        if (S_ISDIR(pathStat.st_mode))
+            break;
+
+        PermissionMap::const_iterator policy = m_filePermission.find(String(canonicalPath));
+        if (policy != m_filePermission.end()) {
+            free(basePath);
+            free(canonicalPath);
+            return (permission & policy->value) == permission;
+        }
+
+        // If not a directory neither a file with a policy defined,
+        // we set canonicalPath to zero to force a rewind to the parent
+        // directory.
+        free(canonicalPath);
+        canonicalPath = 0;
+    }
+
+    while (!canonicalPath) {
+        char* currentBaseDirectory = dirname(basePath);
+        canonicalPath = canonicalize_file_name(currentBaseDirectory);
+    }
+
+    PermissionMap::const_iterator policy = m_directoryPermission.find(String(canonicalPath));
+    while (policy == m_directoryPermission.end()) {
+        char* currentBaseDirectory = dirname(canonicalPath);
+        policy = m_directoryPermission.find(String(currentBaseDirectory));
+    }
+
+    free(basePath);
+    free(canonicalPath);
+
+    return (permission & policy->value) == permission;
+}
+
+void SyscallPolicy::addFilePermission(const String& path, Permission permission)
+{
+    ASSERT(!path.isEmpty() && path.startsWith('/')  && !path.endsWith('/') && !path.contains("//"));
+
+    m_filePermission.set(path, permission);
+}
+
+void SyscallPolicy::addDirectoryPermission(const String& path, Permission permission)
+{
+    ASSERT(path.startsWith('/') && !path.contains("//") && (path.length() == 1 || !path.endsWith('/')));
+
+    m_directoryPermission.set(path, permission);
+}
+
+void SyscallPolicy::addDefaultWebProcessPolicy(const WebProcessCreationParameters& parameters)
+{
+    // Directories settings coming from the UIProcess.
+    if (!parameters.applicationCacheDirectory.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.applicationCacheDirectory), ReadAndWrite);
+    if (!parameters.databaseDirectory.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.databaseDirectory), ReadAndWrite);
+    if (!parameters.localStorageDirectory.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.localStorageDirectory), ReadAndWrite);
+    if (!parameters.diskCacheDirectory.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.diskCacheDirectory), ReadAndWrite);
+    if (!parameters.cookieStorageDirectory.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.cookieStorageDirectory), ReadAndWrite);
+#if USE(SOUP)
+    if (!parameters.cookiePersistentStoragePath.isEmpty())
+        addDirectoryPermission(removeTrailingSlash(parameters.cookiePersistentStoragePath), ReadAndWrite);
+#endif
+
+    // The root policy will block access to any directory or
+    // file unless white listed bellow or by platform.
+    addDirectoryPermission(ASCIILiteral("/"), NotAllowed);
+
+    // Shared libraries, plugins and fonts.
+    addDirectoryPermission(ASCIILiteral("/lib"), Read);
+    addDirectoryPermission(ASCIILiteral("/usr/lib"), Read);
+    addDirectoryPermission(ASCIILiteral("/usr/share"), Read);
+
+    // SSL Certificates.
+    addDirectoryPermission(ASCIILiteral("/etc/ssl/certs"), Read);
+
+    // Fontconfig cache.
+    addDirectoryPermission(ASCIILiteral("/etc/fonts"), Read);
+    addDirectoryPermission(ASCIILiteral("/var/cache/fontconfig"), Read);
+
+    // Audio devices, random number generators, etc.
+    addDirectoryPermission(ASCIILiteral("/dev"), ReadAndWrite);
+
+    // Temporary files and process self information.
+    addDirectoryPermission(ASCIILiteral("/tmp"), ReadAndWrite);
+    addDirectoryPermission(ASCIILiteral("/proc/") + String::number(getpid()), ReadAndWrite);
+
+    // In some distros /dev/shm is a symbolic link to /run/shm, and in
+    // this case, the canonical path resolver will follow the link. If
+    // inside /dev, the policy is already set.
+    addDirectoryPermission(ASCIILiteral("/run/shm"), ReadAndWrite);
+
+    // Needed by glibc for networking and locale.
+    addFilePermission(ASCIILiteral("/etc/gai.conf"), Read);
+    addFilePermission(ASCIILiteral("/etc/host.conf"), Read);
+    addFilePermission(ASCIILiteral("/etc/hosts"), Read);
+    addFilePermission(ASCIILiteral("/etc/localtime"), Read);
+    addFilePermission(ASCIILiteral("/etc/nsswitch.conf"), Read);
+
+    // Needed for DNS resoltion. In some distros, the resolv.conf inside
+    // /etc is just a symbolic link.
+    addFilePermission(ASCIILiteral("/etc/resolv.conf"), Read);
+    addFilePermission(ASCIILiteral("/run/resolvconf/resolv.conf"), Read);
+
+    // Needed to convert uid and gid into names.
+    addFilePermission(ASCIILiteral("/etc/group"), Read);
+    addFilePermission(ASCIILiteral("/etc/passwd"), Read);
+
+    // Needed by the loader.
+    addFilePermission(ASCIILiteral("/etc/ld.so.cache"), Read);
+
+    // Needed by various, including toolkits, for optimizations based
+    // on the current amount of free system memory.
+    addFilePermission(ASCIILiteral("/proc/cpuinfo"), Read);
+    addFilePermission(ASCIILiteral("/proc/filesystems"), Read);
+    addFilePermission(ASCIILiteral("/proc/meminfo"), Read);
+    addFilePermission(ASCIILiteral("/proc/stat"), Read);
+
+    // Needed by D-Bus.
+    addFilePermission(ASCIILiteral("/var/lib/dbus/machine-id"), Read);
+
+    char* homeDir = getenv("HOME");
+    if (homeDir) {
+        // X11 connection token.
+        addFilePermission(String::fromUTF8(homeDir) + "/.Xauthority", Read);
+        // MIME type resolution.
+        addDirectoryPermission(String::fromUTF8(homeDir) +  "/.local/share/mime", Read);
+    }
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.h b/Source/WebKit2/Shared/linux/SeccompFilters/SyscallPolicy.h
new file mode 100644 (file)
index 0000000..cae0e45
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SyscallPolicy_h
+#define SyscallPolicy_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <wtf/HashMap.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+class WebProcessCreationParameters;
+
+class SyscallPolicy {
+public:
+    enum Permission {
+        NotAllowed   = 0,
+        Read         = 1,
+        Write        = 1 << 1,
+        ReadAndWrite = Read | Write
+    };
+
+    bool hasPermissionForPath(const char* path, Permission) const;
+
+    void addFilePermission(const String& path, Permission);
+    void addDirectoryPermission(const String& path, Permission);
+
+    void addDefaultWebProcessPolicy(const WebProcessCreationParameters&);
+
+private:
+    typedef HashMap<String, int> PermissionMap;
+    PermissionMap m_filePermission;
+    PermissionMap m_directoryPermission;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SyscallPolicy_h
index 9c8b80c..b76f65a 100644 (file)
@@ -887,6 +887,29 @@ win32 {
         Platform/CoreIPC/BinarySemaphore.cpp
 }
 
+enable?(SECCOMP_FILTERS) {
+    HEADERS += \
+        Shared/linux/SeccompFilters/OpenSyscall.h \
+        Shared/linux/SeccompFilters/SeccompBroker.h \
+        Shared/linux/SeccompFilters/SeccompFilters.h \
+        Shared/linux/SeccompFilters/SigactionSyscall.h \
+        Shared/linux/SeccompFilters/SigprocmaskSyscall.h \
+        Shared/linux/SeccompFilters/Syscall.h \
+        Shared/linux/SeccompFilters/SyscallPolicy.h \
+        WebProcess/qt/SeccompFiltersWebProcessQt.h
+
+    SOURCES += \
+        Shared/linux/SeccompFilters/OpenSyscall.cpp \
+        Shared/linux/SeccompFilters/SeccompBroker.cpp \
+        Shared/linux/SeccompFilters/SeccompFilters.cpp \
+        Shared/linux/SeccompFilters/SigactionSyscall.cpp \
+        Shared/linux/SeccompFilters/SigprocmaskSyscall.cpp \
+        Shared/linux/SeccompFilters/Syscall.cpp \
+        Shared/linux/SeccompFilters/SyscallPolicy.cpp \
+        WebProcess/qt/SeccompFiltersWebProcessQt.cpp
+
+    DEFINES += SOURCE_DIR=\\\"$${ROOT_WEBKIT_DIR}\\\"
+}
 
 enable?(INSPECTOR_SERVER) {
     HEADERS += \
index 16f4f61..cf1d549 100644 (file)
@@ -83,3 +83,5 @@ linux-*: {
 have?(QTQUICK): QT += qml quick
 
 have?(qtlocation):enable?(GEOLOCATION): QT += location
+
+enable?(SECCOMP_FILTERS): PKGCONFIG += libseccomp
diff --git a/Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.cpp b/Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.cpp
new file mode 100644 (file)
index 0000000..258f01b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SeccompFiltersWebProcessEfl.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include "WebProcessCreationParameters.h"
+#include <WebKit2/SeccompBroker.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace WebKit {
+
+SeccompFiltersWebProcessEfl::SeccompFiltersWebProcessEfl(const WebProcessCreationParameters& parameters)
+    : SeccompFilters(Allow)
+{
+    m_policy.addDefaultWebProcessPolicy(parameters);
+}
+
+void SeccompFiltersWebProcessEfl::platformInitialize()
+{
+    // TODO: We should block all the syscalls and whitelist
+    // what we need + trap what should be handled by the broker.
+    addRule("open", Trap);
+    addRule("openat", Trap);
+    addRule("creat", Trap);
+
+    // Needed by Eeze on NetworkStateNotifierEfl.
+    m_policy.addDirectoryPermission(ASCIILiteral("/sys/bus"), SyscallPolicy::Read);
+    m_policy.addDirectoryPermission(ASCIILiteral("/sys/class"), SyscallPolicy::Read);
+    m_policy.addDirectoryPermission(ASCIILiteral("/sys/devices"), SyscallPolicy::Read);
+    m_policy.addFilePermission(ASCIILiteral("/etc/udev/udev.conf"), SyscallPolicy::Read);
+
+#ifdef SOURCE_DIR
+    // Developers using build-webkit --efl expect some libraries to be loaded
+    // from the build root directory and they also need access to layout test
+    // files. The constant is defined only when jhbuild is detected, which is
+    // an indication of a development build.
+    char* sourceDir = canonicalize_file_name(SOURCE_DIR);
+    if (sourceDir) {
+        m_policy.addDirectoryPermission(String::fromUTF8(sourceDir), SyscallPolicy::ReadAndWrite);
+        free(sourceDir);
+    }
+#endif
+
+    // Place where the theme and icons are installed.
+    char* dataDir = canonicalize_file_name(DATA_DIR);
+    if (dataDir) {
+        m_policy.addDirectoryPermission(String::fromUTF8(dataDir), SyscallPolicy::Read);
+        free(dataDir);
+    }
+
+#if USE(GSTREAMER)
+    // Video playback requires access to the root of the user cache dir which
+    // is not right. We need to check with these directories on gstreamer
+    // can be configured.
+    char* homeDir = getenv("HOME");
+    if (homeDir)
+        m_policy.addDirectoryPermission(String::fromUTF8(homeDir) + "/.cache", SyscallPolicy::ReadAndWrite);
+#endif
+
+    SeccompBroker::launchProcess(this, m_policy);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.h b/Source/WebKit2/WebProcess/efl/SeccompFiltersWebProcessEfl.h
new file mode 100644 (file)
index 0000000..6e32948
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SeccompFiltersWebProcessEfl_h
+#define SeccompFiltersWebProcessEfl_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <WebKit2/SeccompFilters.h>
+#include <WebKit2/SyscallPolicy.h>
+
+namespace WebKit {
+
+class WebProcessCreationParameters;
+
+class SeccompFiltersWebProcessEfl : public SeccompFilters {
+public:
+    SeccompFiltersWebProcessEfl(const WebProcessCreationParameters&);
+
+private:
+    virtual void platformInitialize();
+
+    SyscallPolicy m_policy;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SeccompFiltersWebProcessEfl_h
diff --git a/Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.cpp b/Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.cpp
new file mode 100644 (file)
index 0000000..b44b867
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SeccompFiltersWebProcessQt.h"
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <QFileInfo>
+#include <QLibraryInfo>
+#include <WebKit2/SeccompBroker.h>
+#include <WebKit2/SyscallPolicy.h>
+
+namespace WebKit {
+
+SeccompFiltersWebProcessQt::SeccompFiltersWebProcessQt(const WebProcessCreationParameters& parameters)
+    : SeccompFilters(Allow)
+{
+    m_policy.addDefaultWebProcessPolicy(parameters);
+}
+
+void SeccompFiltersWebProcessQt::platformInitialize()
+{
+    // TODO: We should block all the syscalls and whitelist
+    // what we need + trap what should be handled by the broker.
+    addRule("open", Trap);
+    addRule("openat", Trap);
+    addRule("creat", Trap);
+
+    // Qt directories.
+    m_policy.addDirectoryPermission(QLibraryInfo::location(QLibraryInfo::LibrariesPath), SyscallPolicy::Read);
+    m_policy.addDirectoryPermission(QLibraryInfo::location(QLibraryInfo::PluginsPath), SyscallPolicy::Read);
+
+    // WEBKIT_TESTFONTS is set when running layout tests. We also need to add
+    // the root of the WebKit tree to the sandbox so we can read the tests and
+    // write back the results.
+    const char* path = getenv("WEBKIT_TESTFONTS");
+    if (path) {
+        QFileInfo fontDir(QString::fromUtf8(path));
+        m_policy.addDirectoryPermission(fontDir.canonicalFilePath(), SyscallPolicy::Read);
+
+        QFileInfo sourceDir(QString::fromUtf8(SOURCE_DIR));
+        m_policy.addDirectoryPermission(sourceDir.canonicalFilePath(), SyscallPolicy::ReadAndWrite);
+    }
+
+    SeccompBroker::launchProcess(this, m_policy);
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
diff --git a/Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.h b/Source/WebKit2/WebProcess/qt/SeccompFiltersWebProcessQt.h
new file mode 100644 (file)
index 0000000..ff5e7a8
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SeccompFiltersWebProcessQt_h
+#define SeccompFiltersWebProcessQt_h
+
+#if ENABLE(SECCOMP_FILTERS)
+
+#include <WebKit2/SeccompFilters.h>
+#include <WebKit2/SyscallPolicy.h>
+
+namespace WebKit {
+
+class WebProcessCreationParameters;
+
+class SeccompFiltersWebProcessQt : public SeccompFilters {
+public:
+    SeccompFiltersWebProcessQt(const WebProcessCreationParameters&);
+
+private:
+    virtual void platformInitialize();
+
+    SyscallPolicy m_policy;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(SECCOMP_FILTERS)
+
+#endif // SeccompFiltersWebProcessQt_h
index 2210665..9a67ebf 100644 (file)
@@ -29,6 +29,7 @@
 #include "InjectedBundle.h"
 #include "QtBuiltinBundle.h"
 #include "QtNetworkAccessManager.h"
+#include "SeccompFiltersWebProcessQt.h"
 #include "WKBundleAPICast.h"
 #include "WebProcessCreationParameters.h"
 
@@ -136,6 +137,13 @@ static void parentProcessDiedCallback(void*)
 
 void WebProcess::platformInitializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::MessageDecoder&)
 {
+#if ENABLE(SECCOMP_FILTERS)
+    {
+        WebKit::SeccompFiltersWebProcessQt seccompFilters(parameters);
+        seccompFilters.initialize();
+    }
+#endif
+
     m_networkAccessManager = new QtNetworkAccessManager(this);
 
     if (!parameters.cookieStorageDirectory.isEmpty()) {
index 1c9d332..f1832f9 100644 (file)
 
 #define LIBSOUP_USE_UNSTABLE_REQUEST_API
 
+#if PLATFORM(EFL)
+#include "SeccompFiltersWebProcessEfl.h"
+#endif
+
 #include "WebCookieManager.h"
 #include "WebProcessCreationParameters.h"
 #include <WebCore/FileSystem.h>
@@ -165,6 +169,15 @@ static void languageChanged(void*)
 
 void WebProcess::platformInitializeWebProcess(const WebProcessCreationParameters& parameters, CoreIPC::MessageDecoder&)
 {
+#if ENABLE(SECCOMP_FILTERS)
+    {
+#if PLATFORM(EFL)
+        SeccompFiltersWebProcessEfl seccompFilters(parameters);
+#endif
+        seccompFilters.initialize();
+    }
+#endif
+
     if (!parameters.languages.isEmpty())
         setSoupSessionAcceptLanguage(parameters.languages);
 
diff --git a/Source/cmake/FindLibSeccomp.cmake b/Source/cmake/FindLibSeccomp.cmake
new file mode 100644 (file)
index 0000000..2129c8b
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (c) 2013, Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+#   list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+# * Neither the name of Intel Corporation nor the names of its contributors may
+#   be used to endorse or promote products derived from this software without
+#   specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Try to find libseccomp include and library directories.
+#
+# After successful discovery, this will set for inclusion where needed:
+# LIBSECCOMP_INCLUDE_DIRS - containg the libseccomp headers
+# LIBSECCOMP_LIBRARIES - containg the libseccomp library
+
+include(FindPkgConfig)
+
+pkg_check_modules(PC_LIBSECCOMP libseccomp)
+
+find_path(LIBSECCOMP_INCLUDE_DIRS NAMES seccomp.h
+    HINTS ${PC_LIBSECCOMP_INCLUDE_DIRS} ${PC_LIBSECCOMP_INCLUDEDIR}
+)
+
+find_library(LIBSECCOMP_LIBRARIES NAMES seccomp
+    HINTS ${PC_LIBSECCOMP_LIBRARY_DIRS} ${PC_LIBSECCOMP_LIBDIR}
+)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(seccomp DEFAULT_MSG LIBSECCOMP_INCLUDE_DIRS LIBSECCOMP_LIBRARIES)
index 5fc9016..27874a6 100644 (file)
@@ -47,6 +47,8 @@ set(DATA_INSTALL_DIR "share/${WebKit_LIBRARY_NAME}-${PROJECT_VERSION_MAJOR}" CAC
 set(THEME_BINARY_DIR ${CMAKE_BINARY_DIR}/WebCore/platform/efl/DefaultTheme)
 file(MAKE_DIRECTORY ${THEME_BINARY_DIR})
 
+add_definitions(-DDATA_DIR="${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}")
+
 set(VERSION_SCRIPT "-Wl,--version-script,${CMAKE_MODULE_PATH}/eflsymbols.filter")
 
 WEBKIT_OPTION_BEGIN()
@@ -83,6 +85,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_INFO ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PAGE_VISIBILITY_API ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_RESOLUTION_MEDIA_QUERY ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_REQUEST_ANIMATION_FRAME ON)
+WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SECCOMP_FILTERS OFF)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHADOW_DOM ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHARED_WORKERS ON)
 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPELLCHECK ON)
@@ -242,6 +245,10 @@ if (ENABLE_INSPECTOR)
     add_definitions(-DWEB_INSPECTOR_INSTALL_DIR=\"${CMAKE_INSTALL_PREFIX}/${WEB_INSPECTOR_DIR}\")
 endif ()
 
+if (ENABLE_SECCOMP_FILTERS)
+    find_package(LibSeccomp REQUIRED)
+endif ()
+
 set(CPACK_SOURCE_GENERATOR TBZ2)
 
 # Optimize binary size for release builds by removing dead sections on unix/gcc
index e3ddbf5..0526ca3 100644 (file)
@@ -107,6 +107,7 @@ macro(WEBKIT_OPTION_BEGIN)
     WEBKIT_OPTION_DEFINE(ENABLE_RESOLUTION_MEDIA_QUERY "Toggle resolution media query support" OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_RESOURCE_TIMING "Toggle Resource Timing support" OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_SCRIPTED_SPEECH "Toggle Scripted Speech API support" OFF)
+    WEBKIT_OPTION_DEFINE(ENABLE_SECCOMP_FILTERS "Toggle Linux seccomp filters for the WebProcess support" OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_SHADOW_DOM "Toggle Shadow DOM support" OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_SHARED_WORKERS "Toggle SharedWorkers support" OFF)
     WEBKIT_OPTION_DEFINE(ENABLE_SPELLCHECK "Toggle Spellchecking support (requires Enchant)" OFF)
index f9713a6..4893617 100644 (file)
 #cmakedefine01 ENABLE_RESOLUTION_MEDIA_QUERY
 #cmakedefine01 ENABLE_RESOURCE_TIMING
 #cmakedefine01 ENABLE_SCRIPTED_SPEECH
+#cmakedefine01 ENABLE_SECCOMP_FILTERS
 #cmakedefine01 ENABLE_SHADOW_DOM
 #cmakedefine01 ENABLE_SHARED_WORKERS
 #cmakedefine01 ENABLE_SMOOTH_SCROLLING
index 76e8a4f..ffbaa29 100644 (file)
@@ -1,3 +1,36 @@
+2013-04-09  Thiago Marcos P. Santos  <thiago.santos@intel.com>
+
+        [WK2] Drop WebProcess capabilities on Linux using seccomp filters
+        https://bugs.webkit.org/show_bug.cgi?id=89875
+
+        Reviewed by Maciej Stachowiak.
+
+        Add unit tests to verify if the handling of the open, openat, creat syscall
+        is being done right. We check if the Read/Write/ReadAndWrite permissions
+        are respected, if the canonical path is being resolved and if
+        the permissions are falling back to the topmost parent directory with a
+        policy set when the directory being opened has no policy.
+
+        We also test if any attempt of blocking SIGSYS is silently ignored.
+        SIGSYS cannot be blocked because in it's handler is where we hook
+        syscalls to the broker process.
+
+        Also added libseccomp to EFL's jhbuild to make the life of developers
+        willing to help easier.
+
+        * Scripts/webkitperl/FeatureList.pm:
+        * TestWebKitAPI/PlatformEfl.cmake:
+        * TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp: Added.
+        (TestWebKitAPI):
+        (SeccompEnvironment):
+        (TestWebKitAPI::SeccompEnvironment::SetUp):
+        (TestWebKitAPI::SeccompEnvironment::TearDown):
+        (TestWebKitAPI::dummyHandler):
+        (TestWebKitAPI::TEST):
+        (TestWebKitAPI::stressTest):
+        * efl/jhbuild.modules:
+        * qmake/mkspecs/features/features.pri:
+
 2013-04-09  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION: Autocorrection doesn't work in DumpRenderTree
index 12109db..6883b50 100644 (file)
@@ -125,6 +125,7 @@ my (
     $requestAnimationFrameSupport,
     $resourceTimingSupport,
     $scriptedSpeechSupport,
+    $seccompFiltersSupport,
     $shadowDOMSupport,
     $sharedWorkersSupport,
     $sqlDatabaseSupport,
@@ -401,6 +402,9 @@ my @features = (
     { option => "request-animation-frame", desc => "Toggle Request Animation Frame support",
       define => "ENABLE_REQUEST_ANIMATION_FRAME", default => (isAppleMacWebKit() || isGtk() || isEfl() || isBlackBerry()), value => \$requestAnimationFrameSupport },
 
+    { option => "seccomp-filters", desc => "Toggle Seccomp Filter sandbox",
+      define => "ENABLE_SECCOMP_FILTERS", default => 0, value => \$seccompFiltersSupport },
+
     { option => "scripted-speech", desc => "Toggle Scripted Speech support",
       define => "ENABLE_SCRIPTED_SPEECH", default => 0, value => \$scriptedSpeechSupport },
 
index 287e7dd..35962f5 100644 (file)
@@ -89,6 +89,15 @@ set(test_webkit2_api_BINARIES
     efl/WKViewClientWebProcessCallbacks
 )
 
+# Seccomp filters is an internal API and its symbols
+# are not (and should not) be exposed by default. We
+# can only test it when building shared core.
+if (ENABLE_SECCOMP_FILTERS AND SHARED_CORE)
+    list(APPEND test_webkit2_api_BINARIES
+        SeccompFilters
+    )
+endif ()
+
 set(test_webkit2_api_fail_BINARIES
     CanHandleRequest
     DOMWindowExtensionBasic
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/SeccompFilters.cpp
new file mode 100644 (file)
index 0000000..c666bf6
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <WebKit2/SeccompBroker.h>
+#include <WebKit2/SeccompFilters.h>
+#include <WebKit2/SyscallPolicy.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebKit;
+
+namespace TestWebKitAPI {
+
+DEFINE_STATIC_LOCAL(String, rootDir, (ASCIILiteral("/")));
+DEFINE_STATIC_LOCAL(String, homeDir, (String(getenv("HOME"))));
+DEFINE_STATIC_LOCAL(String, usrDir, (ASCIILiteral("/usr")));
+DEFINE_STATIC_LOCAL(String, usrSbinDir, (ASCIILiteral("/usr/sbin")));
+DEFINE_STATIC_LOCAL(String, testDirRead, (ASCIILiteral("/tmp/WebKitSeccompFilters/testRead")));
+DEFINE_STATIC_LOCAL(String, testDirWrite, (ASCIILiteral("/tmp/WebKitSeccompFilters/testWrite")));
+DEFINE_STATIC_LOCAL(String, testDirReadAndWrite, (ASCIILiteral("/tmp/WebKitSeccompFilters/testReadAndWrite")));
+DEFINE_STATIC_LOCAL(String, testDirNotAllowed, (ASCIILiteral("/tmp/WebKitSeccompFilters/testNotAllowed")));
+DEFINE_STATIC_LOCAL(String, testFileNotAllowed, (testDirReadAndWrite + "/testFilePolicy"));
+DEFINE_STATIC_LOCAL(String, testFileReadAndWrite, (testDirNotAllowed + "/testFilePolicy"));
+
+static const mode_t defaultMode = S_IRUSR | S_IWUSR | S_IXUSR;
+
+class SeccompEnvironment : public testing::Environment {
+public:
+    virtual void SetUp()
+    {
+        ASSERT_TRUE(!homeDir.isEmpty());
+
+        mkdir("/tmp/WebKitSeccompFilters", defaultMode);
+        mkdir(testDirRead.utf8().data(), defaultMode);
+        mkdir(testDirWrite.utf8().data(), defaultMode);
+        mkdir(testDirReadAndWrite.utf8().data(), defaultMode);
+        mkdir(testDirNotAllowed.utf8().data(), defaultMode);
+
+        // Create a file for the Read only and NotAllowed directory before
+        // loading the filters.
+        String file = testDirRead + "/testFile";
+        int fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+        ASSERT_NE(close(fd), -1);
+        file = testDirNotAllowed + "/testFile";
+        fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+        ASSERT_NE(close(fd), -1);
+
+        // Create files for the file policy tests. File policies precedes the
+        // directory policy. In this case, we create a file with read and write
+        // policies inside a directory that is not allowed, and vice versa. 
+        fd = open(testFileNotAllowed.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+        ASSERT_NE(close(fd), -1);
+        fd = open(testFileReadAndWrite.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+        ASSERT_NE(close(fd), -1);
+
+        SyscallPolicy policy;
+        policy.addDirectoryPermission(rootDir, SyscallPolicy::NotAllowed);
+        policy.addDirectoryPermission(usrDir, SyscallPolicy::Read);
+        policy.addDirectoryPermission(usrSbinDir, SyscallPolicy::NotAllowed);
+        policy.addDirectoryPermission(testDirRead, SyscallPolicy::Read);
+        policy.addDirectoryPermission(testDirWrite, SyscallPolicy::Write);
+        policy.addDirectoryPermission(testDirReadAndWrite, SyscallPolicy::ReadAndWrite);
+        policy.addDirectoryPermission(testDirNotAllowed, SyscallPolicy::NotAllowed);
+        policy.addFilePermission(testFileNotAllowed, SyscallPolicy::NotAllowed);
+        policy.addFilePermission(testFileReadAndWrite, SyscallPolicy::ReadAndWrite);
+
+        SeccompFilters seccompFilters(SeccompFilters::Allow);
+        seccompFilters.addRule("open", SeccompFilters::Trap);
+        seccompFilters.addRule("openat", SeccompFilters::Trap);
+        seccompFilters.addRule("creat", SeccompFilters::Trap);
+
+        SeccompBroker::launchProcess(&seccompFilters, policy);
+        seccompFilters.initialize();
+    }
+
+    virtual void TearDown()
+    {
+        // This will have to move to a separated process created before loading
+        // the filters when we put the rmdir/unlink policies in place.
+        unlink("/tmp/WebKitSeccompFilters/testNotAllowed/testFile");
+        unlink("/tmp/WebKitSeccompFilters/testNotAllowed/testFilePolicy");
+        unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile");
+        unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile2");
+        unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFile3");
+        unlink("/tmp/WebKitSeccompFilters/testReadAndWrite/testFilePolicy");
+        unlink("/tmp/WebKitSeccompFilters/testWrite/testFile");
+        unlink("/tmp/WebKitSeccompFilters/testWrite/testFile2");
+        unlink("/tmp/WebKitSeccompFilters/testRead/testFile");
+        rmdir("/tmp/WebKitSeccompFilters/testNotAllowed");
+        rmdir("/tmp/WebKitSeccompFilters/testReadAndWrite");
+        rmdir("/tmp/WebKitSeccompFilters/testWrite");
+        rmdir("/tmp/WebKitSeccompFilters/testRead");
+        rmdir("/tmp/WebKitSeccompFilters");
+    }
+};
+
+::testing::Environment* const env = ::testing::AddGlobalTestEnvironment(new SeccompEnvironment);
+
+static void dummyHandler(int, siginfo_t*, void*)
+{
+}
+
+TEST(WebKit2, sigaction)
+{
+    // Setting a handler should be enough to break any subsequent test if
+    // not silently ignored by the sandbox.
+    struct sigaction action;
+    memset(&action, 0, sizeof(action));
+    action.sa_sigaction = &dummyHandler;
+    action.sa_flags = SA_SIGINFO;
+
+    ASSERT_NE(sigaction(SIGSYS, &action, 0), -1);
+}
+
+TEST(WebKit2, sigprocmask)
+{
+    // We test here the mechanism installed to prevent SIGSYS to be blocked. Any
+    // attemp to add SIGSYS to the set of blocked signals will be silently
+    // ignored (but other signals will be blocked just fine).
+    sigset_t set, oldSet;
+    sigemptyset(&set);
+    sigaddset(&set, SIGSYS);
+    sigaddset(&set, SIGUSR1);
+
+    ASSERT_NE(sigprocmask(SIG_BLOCK, &set, 0), -1);
+    ASSERT_NE(sigprocmask(SIG_BLOCK, 0, &oldSet), -1);
+    ASSERT_FALSE(sigismember(&oldSet, SIGSYS)) << "SIGSYS should not be blocked.";
+    ASSERT_TRUE(sigismember(&oldSet, SIGUSR1)) << "Other signals should be blocked normally.";
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGSYS);
+    sigaddset(&set, SIGUSR2);
+
+    ASSERT_NE(sigprocmask(SIG_SETMASK, &set, &oldSet), -1);
+    ASSERT_NE(sigprocmask(SIG_SETMASK, 0, &set), -1);
+    ASSERT_FALSE(sigismember(&set, SIGSYS)) << "SIGSYS should not be blocked.";
+    ASSERT_TRUE(sigismember(&set, SIGUSR2)) << "Other signals should be blocked normally.";
+    ASSERT_FALSE(sigismember(&oldSet, SIGUSR2));
+
+    ASSERT_NE(sigprocmask(SIG_SETMASK, &oldSet, 0), -1) << "Should restore the old signal set just fine.";
+    ASSERT_NE(sigprocmask(SIG_SETMASK, 0, &set), -1);
+    ASSERT_FALSE(sigismember(&set, SIGUSR2)) << "The restored set doesn't have SIGUSR2.";
+}
+
+TEST(WebKit2, open)
+{
+    // Read only directory.
+    String file = testDirRead + "/testFile";
+    int fd = open(file.utf8().data(), O_RDWR);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_RDONLY | O_CREAT, defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    file = testDirRead + "/ThisFileDoesNotExist";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == ENOENT) << "Should return ENOENT when trying " \
+        "to open a file that does not exit and the permissions are OK.";
+
+    fd = open(file.utf8().data(), O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES) << "Should return EACCES when trying " \
+        "to open a file that does not exit and the permissions are not OK.";
+
+    // Write only directory.
+    file = testDirWrite + "/testFile";
+    fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+    ASSERT_NE(fd, -1);
+    close(fd);
+
+    fd = open(file.utf8().data(), O_RDWR);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_WRONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    // Read an write directory.
+    file = testDirReadAndWrite + "/testFile";
+    fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+    ASSERT_NE(fd, -1);
+    close(fd);
+
+    fd = open(file.utf8().data(), O_RDWR);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = open(file.utf8().data(), O_WRONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    // NotAllowed directory.
+    file = testDirNotAllowed + "/testFile";
+    fd = open(file.utf8().data(), O_WRONLY | O_CREAT, defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_RDWR);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(file.utf8().data(), O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+
+    // The /usr directory here has read permissions, so it's subdirectories
+    // should resolve to the /usr permissions unless explicitly specified.
+    file = usrDir + "/bin/basename";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_NE(fd, -1) << "Subdirectories should with no policy should " \
+        "inherit the parent's policies.";
+    close(fd);
+
+    file = usrSbinDir + "/adduser";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES) << "This directory should have " \
+        "its own policy instead of the parent's.";
+
+    // Access to the rest of the files system is blocked and should
+    // never return anything else other than EACCES regardless if the
+    // file exists or not. The reason is because it will fallback to the
+    // policy of the Root directory, marked as NotAllowed.
+    file = homeDir + "/testFile";
+    fd = open(file.utf8().data(), O_RDWR | O_CREAT, defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open("/etc/passwd", O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    file = testDirReadAndWrite + "/../../../etc/passwd";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    file = testDirReadAndWrite + "/../../.." + testDirReadAndWrite + "/../../../etc/passwd";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    // Here we test file policies. The have precedence over directory policies.
+    // The file bellow lives inside a directory with ReadAndWrite policy.
+    fd = open(testFileNotAllowed.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(testFileNotAllowed.utf8().data(), O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = open(testFileNotAllowed.utf8().data(), O_RDWR);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    file = testDirReadAndWrite + "/../../.." + testDirReadAndWrite + "/testFilePolicy";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    // The next file is located inside a directory marked as NotAllowed, but
+    // it has its own file policy that precedes the directory policy.
+    fd = open(testFileReadAndWrite.utf8().data(), O_RDONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = open(testFileReadAndWrite.utf8().data(), O_WRONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = open(testFileReadAndWrite.utf8().data(), O_RDWR);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    file = testDirReadAndWrite + "/../../.." + testDirNotAllowed + "/testFilePolicy";
+    fd = open(file.utf8().data(), O_RDONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+}
+
+TEST(WebKit2, creat)
+{
+    // Read only directory.
+    String file = testDirRead + "/testFile2";
+    int fd = creat(file.utf8().data(), defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    // Write only directory.
+    file = testDirWrite + "/testFile2";
+    fd = creat(file.utf8().data(), defaultMode);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    // Read an write directory.
+    file = testDirReadAndWrite + "/testFile2";
+    fd = creat(file.utf8().data(), defaultMode);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    // NotAllowed directory.
+    file = testDirNotAllowed + "/testFile2";
+    fd = creat(file.utf8().data(), defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+}
+
+TEST(WebKit2, openat)
+{
+    int dirFd = open(testDirReadAndWrite.utf8().data(), O_RDONLY);
+    ASSERT_NE(dirFd, -1);
+
+    int fd = openat(dirFd, "testFile3", O_RDWR | O_CREAT, defaultMode);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = openat(dirFd, "testFile3", O_RDWR);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = openat(dirFd, "testFile3", O_RDONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    fd = openat(dirFd, "testFile3", O_WRONLY);
+    EXPECT_NE(fd, -1);
+
+    fd = openat(fd, "testFile3", O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == ENOTDIR) << "Should return ENOTDIR when the fd is a file.";
+    close(fd);
+
+    String file = "../../.." + testDirReadAndWrite + "/testFile3";
+    fd = openat(dirFd, file.utf8().data(), O_WRONLY);
+    EXPECT_NE(fd, -1);
+    close(fd);
+
+    file = "../../.." + testDirRead + "/testFile3";
+    fd = openat(dirFd, file.utf8().data(), O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    file = testDirReadAndWrite + "/testFile3";
+    fd = openat(-1, file.utf8().data(), O_WRONLY);
+    EXPECT_NE(fd, -1) << "Directory fd should be ignored when the path is absolute.";
+    close(fd);
+
+    fd = openat(-1, "testFile3", O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EBADF) << "Should return EBADF when the fd is invalid.";
+    close(dirFd);
+
+    dirFd = open(testDirNotAllowed.utf8().data(), O_RDONLY);
+    EXPECT_TRUE(dirFd == -1 && errno == EACCES);
+
+    dirFd = open(testDirRead.utf8().data(), O_RDONLY);
+    ASSERT_NE(dirFd, -1);
+
+    fd = openat(dirFd, "testFile2", O_RDONLY | O_CREAT, defaultMode);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+    fd = openat(dirFd, "testFile", O_WRONLY);
+    EXPECT_TRUE(fd == -1 && errno == EACCES);
+    close(dirFd);
+}
+
+static void* stressTest(void*)
+{
+    for (int i = 0; i < 500; ++i) {
+        int fd = open("/tmp/WebKitSeccompFilters/testRead/testFile", O_RDWR);
+        EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+        fd = open("/tmp/WebKitSeccompFilters/testRead/testFile", O_RDONLY);
+        EXPECT_NE(fd, -1);
+        close(fd);
+
+        fd = open("/tmp/WebKitSeccompFilters/testNotAllowed/testFile", O_RDONLY);
+        EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+        fd = creat("/tmp/WebKitSeccompFilters/testNotAllowed/SholdNotBeAllowed", defaultMode);
+        EXPECT_TRUE(fd == -1 && errno == EACCES);
+
+        int dirFd = open("/tmp/WebKitSeccompFilters/testRead", O_RDONLY);
+        EXPECT_NE(dirFd, -1);
+
+        fd = openat(dirFd, "testFile", O_RDONLY);
+        EXPECT_NE(fd, -1);
+        close(fd);
+        close(dirFd);
+    }
+
+    return 0;
+}
+
+TEST(WebKit2, threading)
+{
+    // Tests if concurrent syscall execution works fine. It can be
+    // also used for performance testing and leak detection. The test
+    // is disabled on Debug mode because it can be way too verbose.
+    pthread_t threads[5];
+
+    for (int i = 0; i < sizeof(threads) / sizeof(pthread_t); ++i)
+        pthread_create(&threads[i], 0, stressTest, 0);
+
+    for (int i = 0; i < sizeof(threads) / sizeof(pthread_t); ++i)
+        pthread_join(threads[i], 0);
+}
+
+} // namespace TestWebKitAPI
index 1c8a022..42dba0e 100644 (file)
@@ -24,6 +24,7 @@
       <dep package="gst-plugins-good"/>
       <dep package="gst-plugins-bad"/>
       <dep package="gst-libav"/>
+      <dep package="libseccomp"/>
     </dependencies>
   </metamodule>
 
@@ -51,6 +52,8 @@
       href="http://download.enlightenment.org"/>
   <repository type="tarball" name="gstreamer"
       href="http://gstreamer.freedesktop.org/src/"/>
+  <repository type="git" name="git.code.sf.net"
+      href="git://git.code.sf.net/p/"/>
 
   <autotools id="cairo" autogen-sh="configure">
     <dependencies>
             hash="sha256:aef8be665096b3a4e64424fb39d7c5da57faaaf95e9fea6c1bb44295d4fb32d5"/>
   </autotools> 
 
+  <autotools id="libseccomp" autogen-sh="configure">
+      <branch module="libseccomp/libseccomp"
+          repo="git.code.sf.net"
+          tag="bbd7ca07a7c76d5cd884dbddec58385e1b7439d2"/>
+  </autotools>
+
 </moduleset>
index f5b74fd..bfc76c0 100644 (file)
@@ -99,6 +99,7 @@ FEATURE_DEFAULTS = \
     ENABLE_RESOURCE_TIMING=0 \
     ENABLE_REQUEST_ANIMATION_FRAME=1 \
     ENABLE_SCRIPTED_SPEECH=0 \
+    ENABLE_SECCOMP_FILTERS=0 \
     ENABLE_SHADOW_DOM=0 \
     ENABLE_SHARED_WORKERS=1 \
     ENABLE_SMOOTH_SCROLLING=1 \