Changeset 140957 in webkit


Ignore:
Timestamp:
Jan 28, 2013 1:54:15 AM (11 years ago)
Author:
reni@webkit.org
Message:

[WK2] Putting QtWebProcess into a chrooted sandbox
https://bugs.webkit.org/show_bug.cgi?id=90005

.:

Reviewed by Anders Carlsson and Zoltan Herczeg.

Make it possible to build WebKit2 with SandboxProcess.

  • Source/QtWebKit.pro:

Source/WebKit2:

Reviewed by Anders Carlsson and Zoltan Herczeg.

This new feature makes possible to run WebProcess inside a chroot. In this case UIProcess calls the
internal SandboxProcess binary what makes up an environment for WebProcess inside the sandbox and runs the WebProcess.
SandboxProcess first creates two needed device files (random and urandom), mounts filesystems (proc and shared memory),
then links run-time dependencies of WebProcess. After this, SandboxProcess moves to a new pid namespace (cloning with
CLONE_NEWPID flag). Then after an other cloning (with CLONE_FS flag) we share our filesystem with our children. This is
needed because we want to call chroot() function from here and jail our child (WebProcess) too. This will be performed
when WebProcess sends a request for it via an socketpair. If sandboxing is done, SandboxProcess exits.
Since chroot() system call needs sudoer rights SandboxProcess binary should have set its suid flag. However we can reduce
its capabilites. First we restrict the capabilities of the process and the number of its possible resources. Furthermore
we fallback to the nobody or the real user.

  • Configurations/FeatureDefines.xcconfig:
  • SandboxProcess.pro: Added.
  • Shared/linux/SandboxProcess/SandboxEnvironmentLinux.cpp: Added.

(launchChangeRootHelper):
(setEnvironmentVariablesForChangeRootHelper):
(prepareAndStartChangeRootHelper):
(setCapabilities):
(dropPrivileges):
(fileExists):
(directoryPermissions):
(createDirectory):
(createDirectoryPath):
(createDeviceFiles):
(mountFileSystems):
(linkFile):
(linkDirectory):
(collectRunTimeDependencies):
(setupXauthorityForNobodyUser):
(initSandbox):
(restrictCapabilities):
(moveToNewPidNamespace):
(run):
(main):

  • Shared/linux/SandboxProcess/SandboxEnvironmentLinux.h: Added.
  • Shared/linux/SandboxProcess/StringOperations.cpp: Added.

(stringCopy):
(stringConcat):
(stringAppend):

  • Shared/linux/SandboxProcess/StringOperations.h: Added.
  • UIProcess/Launcher/qt/ProcessLauncherQt.cpp:

(WebKit::ProcessLauncher::launchProcess):

  • WebKit2.pri:
  • WebProcess.pro:
  • WebProcess/qt/WebProcessMainQt.cpp:

(WebKit):
(WebKit::chrootMe):
(WebKit::WebProcessMainQt):

Tools:

Reviewed by Anders Carlsson and Zoltan Herczeg.

Add feature flag for suid sandbox in linux.

  • Scripts/webkitperl/FeatureList.pm:
Location:
trunk
Files:
3 added
9 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r140939 r140957  
     12013-01-28  Renata Hodovan  <reni@webkit.org>
     2
     3        [WK2] Putting QtWebProcess into a chrooted sandbox
     4        https://bugs.webkit.org/show_bug.cgi?id=90005
     5
     6        Reviewed by Anders Carlsson and Zoltan Herczeg.
     7
     8        Make it possible to build WebKit2 with SandboxProcess.
     9
     10        * Source/QtWebKit.pro:
     11
    1122013-01-27  David Farler  <dfarler@apple.com>
    213
  • trunk/Source/QtWebKit.pro

    r136235 r140957  
    2323        SUBDIRS += pluginprocess
    2424    }
     25
     26    enable?(SUID_SANDBOX_LINUX) {
     27        sandboxprocess.file = WebKit2/SandboxProcess.pro
     28        SUBDIRS += sandboxprocess
     29    }
    2530}
    2631
  • trunk/Source/WebKit2/ChangeLog

    r140952 r140957  
     12013-01-28  Renata Hodovan  <reni@webkit.org>
     2
     3        [WK2] Putting QtWebProcess into a chrooted sandbox
     4        https://bugs.webkit.org/show_bug.cgi?id=90005
     5
     6        Reviewed by Anders Carlsson and Zoltan Herczeg.
     7
     8        This new feature makes possible to run WebProcess inside a chroot. In this case UIProcess calls the
     9        internal SandboxProcess binary what makes up an environment for WebProcess inside the sandbox and runs the WebProcess.
     10        SandboxProcess first creates two needed device files (random and urandom), mounts filesystems (proc and shared memory),
     11        then links run-time dependencies of WebProcess. After this, SandboxProcess moves to a new pid namespace (cloning with
     12        CLONE_NEWPID flag). Then after an other cloning (with CLONE_FS flag) we share our filesystem with our children. This is
     13        needed because we want to call chroot() function from here and jail our child (WebProcess) too. This will be performed
     14        when WebProcess sends a request for it via an socketpair. If sandboxing is done, SandboxProcess exits.
     15        Since chroot() system call needs sudoer rights SandboxProcess binary should have set its suid flag. However we can reduce
     16        its capabilites. First we restrict the capabilities of the process and the number of its possible resources. Furthermore
     17        we fallback to the nobody or the real user.
     18
     19        * Configurations/FeatureDefines.xcconfig:
     20        * SandboxProcess.pro: Added.
     21        * Shared/linux/SandboxProcess/SandboxEnvironmentLinux.cpp: Added.
     22        (launchChangeRootHelper):
     23        (setEnvironmentVariablesForChangeRootHelper):
     24        (prepareAndStartChangeRootHelper):
     25        (setCapabilities):
     26        (dropPrivileges):
     27        (fileExists):
     28        (directoryPermissions):
     29        (createDirectory):
     30        (createDirectoryPath):
     31        (createDeviceFiles):
     32        (mountFileSystems):
     33        (linkFile):
     34        (linkDirectory):
     35        (collectRunTimeDependencies):
     36        (setupXauthorityForNobodyUser):
     37        (initSandbox):
     38        (restrictCapabilities):
     39        (moveToNewPidNamespace):
     40        (run):
     41        (main):
     42        * Shared/linux/SandboxProcess/SandboxEnvironmentLinux.h: Added.
     43        * Shared/linux/SandboxProcess/StringOperations.cpp: Added.
     44        (stringCopy):
     45        (stringConcat):
     46        (stringAppend):
     47        * Shared/linux/SandboxProcess/StringOperations.h: Added.
     48        * UIProcess/Launcher/qt/ProcessLauncherQt.cpp:
     49        (WebKit::ProcessLauncher::launchProcess):
     50        * WebKit2.pri:
     51        * WebProcess.pro:
     52        * WebProcess/qt/WebProcessMainQt.cpp:
     53        (WebKit):
     54        (WebKit::chrootMe):
     55        (WebKit::WebProcessMainQt):
     56
    1572013-01-28  Christophe Dumez  <christophe.dumez@intel.com>
    258
  • trunk/Source/WebKit2/SandboxProcess.pro

    r140956 r140957  
    11# -------------------------------------------------------------------
    2 # Project file for the WebKit2 web process binary
     2# Project file for the WebKit2 sandbox process binary
    33#
    44# See 'Tools/qmake/README' for an overview of the build system
     
    77TEMPLATE = app
    88
    9 TARGET = QtWebProcess
     9TARGET = SUIDSandboxHelper
    1010DESTDIR = $${ROOT_BUILD_DIR}/bin
    1111
    12 SOURCES += qt/MainQt.cpp
     12CONFIG += console
     13CONFIG -= qt
    1314
    14 QT += network webkit
    15 macx: QT += xml
    16 
    17 haveQtModule(widgets): QT += widgets webkitwidgets
    18 
    19 build?(webkit1): DEFINES += HAVE_WEBKIT1
     15SOURCES += Shared/linux/SandboxProcess/SandboxEnvironmentLinux.cpp
     16HEADERS += Shared/linux/SandboxProcess/SandboxEnvironmentLinux.h
    2017
    2118INSTALLS += target
     19LIBS += -lcap -ldl
    2220
    2321isEmpty(INSTALL_BINS) {
    24     target.path = $$[QT_INSTALL_LIBEXECS]
     22    target.path = $$[QT_INSTALL_BINS]
    2523} else {
    2624    target.path = $$INSTALL_BINS
    2725}
    28 
    29 
  • trunk/Source/WebKit2/UIProcess/Launcher/qt/ProcessLauncherQt.cpp

    r137023 r140957  
    6262#endif
    6363
     64#if ENABLE(SUID_SANDBOX_LINUX)
     65#include <QCoreApplication>
     66#endif
     67
    6468#if OS(DARWIN)
    6569#include <mach/mach_init.h>
     
    167171#endif
    168172
    169     QProcess* webProcess = new QtWebProcess();
    170     webProcess->setProcessChannelMode(QProcess::ForwardedChannels);
    171     webProcess->start(commandLine);
     173    QProcess* webProcessOrSUIDHelper = new QtWebProcess();
     174    webProcessOrSUIDHelper->setProcessChannelMode(QProcess::ForwardedChannels);
     175
     176#if ENABLE(SUID_SANDBOX_LINUX)
     177    if (m_launchOptions.processType == WebProcess) {
     178        QString sandboxCommandLine = QLatin1String("%1 %2 %3");
     179        sandboxCommandLine = sandboxCommandLine.arg(QCoreApplication::applicationDirPath() + QLatin1String("/SUIDSandboxHelper"));
     180        sandboxCommandLine = sandboxCommandLine.arg(executablePathOfWebProcess());
     181        sandboxCommandLine = sandboxCommandLine.arg(sockets[0]);
     182
     183        webProcessOrSUIDHelper->start(sandboxCommandLine);
     184    } else
     185        webProcessOrSUIDHelper->start(commandLine);
     186#else
     187    webProcessOrSUIDHelper->start(commandLine);
     188#endif
    172189
    173190#if OS(UNIX) && !OS(DARWIN)
     
    176193        if (errno != EINTR) {
    177194            ASSERT_NOT_REACHED();
    178             delete webProcess;
     195            delete webProcessOrSUIDHelper;
    179196            return;
    180197        }
     
    182199#endif
    183200
    184     if (!webProcess->waitForStarted()) {
     201    if (!webProcessOrSUIDHelper->waitForStarted()) {
    185202        qDebug() << "Failed to start" << commandLine;
    186203        ASSERT_NOT_REACHED();
     
    189206        mach_port_mod_refs(mach_task_self(), connector, MACH_PORT_RIGHT_RECEIVE, -1);
    190207#endif
    191         delete webProcess;
    192         return;
    193     }
    194 
     208        delete webProcessOrSUIDHelper;
     209        return;
     210    }
    195211#if OS(UNIX)
    196     setpriority(PRIO_PROCESS, webProcess->pid(), 10);
    197 #endif
    198 
    199     RunLoop::main()->dispatch(bind(&WebKit::ProcessLauncher::didFinishLaunchingProcess, this, webProcess, connector));
     212    setpriority(PRIO_PROCESS, webProcessOrSUIDHelper->pid(), 10);
     213#endif
     214    RunLoop::main()->dispatch(bind(&WebKit::ProcessLauncher::didFinishLaunchingProcess, this, webProcessOrSUIDHelper, connector));
    200215}
    201216
  • trunk/Source/WebKit2/WebKit2.pri

    r140802 r140957  
    1616    $$SOURCE_DIR/Platform/qt \
    1717    $$SOURCE_DIR/Shared \
     18    $$SOURCE_DIR/Shared/linux/SandboxProcess \
    1819    $$SOURCE_DIR/Shared/API/c \
    1920    $$SOURCE_DIR/Shared/Authentication \
     
    6465    $$SOURCE_DIR/WebProcess/WebPage/CoordinatedGraphics \
    6566    $$SOURCE_DIR/WebProcess/qt \
    66     $$SOURCE_DIR/PluginProcess
     67    $$SOURCE_DIR/PluginProcess \
    6768
    6869# The WebKit2 Qt APIs depend on qwebkitglobal.h, which lives in WebKit
  • trunk/Source/WebKit2/WebProcess.pro

    r137145 r140957  
    1111
    1212SOURCES += qt/MainQt.cpp
     13
     14INCLUDEPATH = \
     15    $$PWD/Shared/linux/SandboxProcess/ \
     16    $$INCLUDEPATH
    1317
    1418QT += network webkit
  • trunk/Source/WebKit2/WebProcess/qt/WebProcessMainQt.cpp

    r138868 r140957  
    11/*
     2 * Copyright (C) 2013 University of Szeged
     3 * Copyright (C) 2013 Renata Hodovan <reni@inf.u-szeged.hu>
    24 * Copyright (C) 2010 Apple Inc. All rights reserved.
    35 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
     
    3537#include <QUrl>
    3638#include <WebCore/RunLoop.h>
     39#include <errno.h>
    3740#include <runtime/InitializeThreading.h>
     41#include <sys/wait.h>
    3842#include <wtf/MainThread.h>
    3943
     
    5660
    5761extern "C" kern_return_t bootstrap_look_up2(mach_port_t, const name_t, mach_port_t*, pid_t, uint64_t);
     62#endif
     63
     64#if ENABLE(SUID_SANDBOX_LINUX)
     65#include "SandboxEnvironmentLinux.h"
    5866#endif
    5967
     
    140148}
    141149
     150#if ENABLE(SUID_SANDBOX_LINUX)
     151pid_t chrootMe()
     152{
     153    // Get the file descriptor of the socketpair.
     154    char* sandboxSocketDescriptorString = getenv(SANDBOX_DESCRIPTOR);
     155    if (!sandboxSocketDescriptorString)
     156        return -1;
     157
     158    char* firstInvalidCharacter;
     159    long int sandboxSocketDescriptor = strtol(sandboxSocketDescriptorString, &firstInvalidCharacter, 10);
     160    if (*firstInvalidCharacter != '\0') {
     161        fprintf(stderr, "The socket descriptor of sandbox is not valid.\n");
     162        return -1;
     163    }
     164
     165    // Get the PID of the setuid helper.
     166    char* sandboxHelperPIDString = getenv(SANDBOX_HELPER_PID);
     167    pid_t sandboxHelperPID = -1;
     168
     169    // If no PID is available, the default of -1 will do.
     170    if (sandboxHelperPIDString) {
     171        errno = 0;
     172        sandboxHelperPID = strtol(sandboxHelperPIDString, &firstInvalidCharacter, 10);
     173        if (*firstInvalidCharacter != '\0') {
     174            fprintf(stderr, "The PID of sandbox is not valid.\n");
     175            return -1;
     176        }
     177    }
     178
     179    // Send the chrootMe message to the helper.
     180    char sandboxMeMessage = MSG_CHROOTME;
     181    ssize_t numberOfCharacters = write(sandboxSocketDescriptor, &sandboxMeMessage, 1);
     182    if (numberOfCharacters != 1) {
     183        fprintf(stderr, "ChrootMe msg failed to write: %s.\n", strerror(errno));
     184        return -1;
     185    }
     186
     187    // Read the acknowledgement message from the helper.
     188    numberOfCharacters = read(sandboxSocketDescriptor, &sandboxMeMessage, 1);
     189    if (numberOfCharacters != 1 || sandboxMeMessage != MSG_CHROOTED) {
     190        fprintf(stderr, "Couldn't read the confirmation message: %s.\n", strerror(errno));
     191        return -1;
     192    }
     193    close(sandboxSocketDescriptor);
     194
     195    // Wait for the helper process.
     196    int expectedPID = waitpid(sandboxHelperPID, 0, 0);
     197    if (expectedPID != -1 && (sandboxHelperPID == -1 || expectedPID == sandboxHelperPID))
     198        return expectedPID;
     199    fprintf(stderr, "Couldn't wait for the helper process: %s\n", strerror(errno));
     200    return -1;
     201}
     202#endif
     203
    142204Q_DECL_EXPORT int WebProcessMainQt(QGuiApplication* app)
    143205{
     206#if ENABLE(SUID_SANDBOX_LINUX)
     207    pid_t helper = chrootMe();
     208    if (helper == -1) {
     209        fprintf(stderr, "Asking for chroot failed.\n");
     210        return -1;
     211    }
     212#endif
    144213    initializeProxy();
    145 
    146214    JSC::initializeThreading();
    147215    WTF::initializeMainThread();
    148216    RunLoop::initializeMainRunLoop();
    149    
     217
    150218#if USE(QTKIT)
    151219    InitWebCoreSystemInterfaceForWK2();
  • trunk/Tools/ChangeLog

    r140939 r140957  
     12013-01-28  Renata Hodovan  <reni@webkit.org>
     2
     3        [WK2] Putting QtWebProcess into a chrooted sandbox
     4        https://bugs.webkit.org/show_bug.cgi?id=90005
     5
     6        Reviewed by Anders Carlsson and  Zoltan Herczeg.
     7
     8        Add feature flag for suid sandbox in linux.
     9
     10        * Scripts/webkitperl/FeatureList.pm:
     11
    1122013-01-27  David Farler  <dfarler@apple.com>
    213
  • trunk/Tools/Scripts/webkitperl/FeatureList.pm

    r140493 r140957  
    130130    $sqlDatabaseSupport,
    131131    $styleScopedSupport,
     132    $suidLinuxSandbox,
    132133    $svgDOMObjCBindingsSupport,
    133134    $svgFontsSupport,
     
    406407      define => "ENABLE_STYLE_SCOPED", default => (isBlackBerry() || isGtk()), value => \$styleScopedSupport },
    407408
     409    { option => "suid-linux-sandbox", desc => "Toggle suid sandbox for linux",
     410      define => "ENABLE_SUID_SANDBOX_LINUX", default => 0, value => \$suidLinuxSandbox },
     411
    408412    { option => "svg", desc => "Toggle SVG support",
    409413      define => "ENABLE_SVG", default => 1, value => \$svgSupport },
Note: See TracChangeset for help on using the changeset viewer.