+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.
+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
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"
+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.
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
WebProcess/WebPage/efl/WebInspectorEfl.cpp
WebProcess/WebPage/efl/WebPageEfl.cpp
+ WebProcess/efl/SeccompFiltersWebProcessEfl.cpp
WebProcess/efl/WebProcessMainEfl.cpp
WebProcess/soup/WebProcessSoup.cpp
${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}
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
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 += \
have?(QTQUICK): QT += qml quick
have?(qtlocation):enable?(GEOLOCATION): QT += location
+
+enable?(SECCOMP_FILTERS): PKGCONFIG += libseccomp
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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
#include "InjectedBundle.h"
#include "QtBuiltinBundle.h"
#include "QtNetworkAccessManager.h"
+#include "SeccompFiltersWebProcessQt.h"
#include "WKBundleAPICast.h"
#include "WebProcessCreationParameters.h"
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()) {
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+#if PLATFORM(EFL)
+#include "SeccompFiltersWebProcessEfl.h"
+#endif
+
#include "WebCookieManager.h"
#include "WebProcessCreationParameters.h"
#include <WebCore/FileSystem.h>
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);
--- /dev/null
+# 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)
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()
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)
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
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)
#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
+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
$requestAnimationFrameSupport,
$resourceTimingSupport,
$scriptedSpeechSupport,
+ $seccompFiltersSupport,
$shadowDOMSupport,
$sharedWorkersSupport,
$sqlDatabaseSupport,
{ 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 },
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
--- /dev/null
+/*
+ * 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
<dep package="gst-plugins-good"/>
<dep package="gst-plugins-bad"/>
<dep package="gst-libav"/>
+ <dep package="libseccomp"/>
</dependencies>
</metamodule>
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>
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 \