Add sandbox support (issue #524).

- The sandbox is now enabled by default on all platforms. Use the CefSettings.no_sandbox option or the "no-sandbox" command-line flag to disable sandbox support.
- Windows: See cef_sandbox_win.h for requirements to enable sandbox support.
- Windows: If Visual Studio isn't installed in the standard location set the CEF_VCVARS environment variable before running make_distrib.py or automate.py (see msvs_env.bat).
- Linux: For binary distributions a new chrome-sandbox executable with SUID permissions must be placed next to the CEF executable. See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for details on setting up the development environment when building CEF from source code.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1518 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2013-11-15 18:47:02 +00:00
parent 395f443215
commit f5bc72b234
24 changed files with 485 additions and 52 deletions

View File

@@ -561,7 +561,9 @@ if any_changed or options.forcebuild:
command = 'ninja -v -C'
target = ' cefclient'
if options.buildtests:
target = ' cefclient cef_unittests'
target = target + ' cef_unittests'
if platform == 'linux':
target = target + ' chrome_sandbox'
build_dir_suffix = ''
if platform == 'windows' and options.x64build:
build_dir_suffix = '_x64'

118
tools/combine_libs.py Normal file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env python
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# TODO(slightlyoff): move to using shared version of this script.
'''This script makes it easy to combine libs and object files to a new lib,
optionally removing some of the object files in the input libs by regular
expression matching.
For usage information, run the script with a --help argument.
'''
import optparse
import os
import re
import subprocess
import sys
def Shell(*args):
'''Runs the program and args in args, returns the output from the program.'''
process = subprocess.Popen(args,
stdin = None,
stdout = subprocess.PIPE,
stderr = subprocess.STDOUT)
output = process.stdout.readlines()
process.wait()
retcode = process.returncode
if retcode != 0:
raise RuntimeError('%s exited with status %d' % (args[0], retcode))
return output
def CollectRemovals(remove_re, inputs):
'''Returns a list of all object files in inputs that match remove_re.'''
removals = []
for input in inputs:
output = Shell('lib.exe', '/list', input)
for line in output:
line = line.rstrip()
if remove_re.search(line):
removals.append(line)
return removals
def CombineLibraries(output, remove_re, inputs):
'''Combines all the libraries and objects in inputs, while removing any
object files that match remove_re.
'''
removals = []
if remove_re:
removals = CollectRemovals(remove_re, inputs)
if len(removals) > 0:
print 'Removals: ', removals
args = ['lib.exe', '/out:%s' % output]
args += ['/remove:%s' % obj for obj in removals]
args += inputs
Shell(*args)
USAGE = '''usage: %prog [options] <lib or obj>+
Combines input libraries or objects into an output library, while removing
any object file (in the input libraries) that matches a given regular
expression.
'''
def GetOptionParser():
parser = optparse.OptionParser(USAGE)
parser.add_option('-o', '--output', dest = 'output',
help = 'write to this output library')
parser.add_option('-r', '--remove', dest = 'remove',
help = 'object files matching this regexp will be removed '
'from the output library')
return parser
def Main():
'''Main function for this script'''
parser = GetOptionParser()
(opt, args) = parser.parse_args()
output = opt.output
remove = opt.remove
if not output:
parser.error('You must specify an output file')
if not args:
parser.error('You must specify at least one object or library')
output = output.strip()
if remove:
remove = remove.strip()
if remove:
try:
remove_re = re.compile(opt.remove)
except:
parser.error('%s is not a valid regular expression' % opt.remove)
else:
remove_re = None
if sys.platform != 'win32' and sys.platform != 'cygwin':
parser.error('this script only works on Windows for now')
# If this is set, we can't capture lib.exe's output.
if 'VS_UNICODE_OUTPUT' in os.environ:
del os.environ['VS_UNICODE_OUTPUT']
CombineLibraries(output, remove_re, args)
return 0
if __name__ == '__main__':
sys.exit(Main())

View File

@@ -97,7 +97,6 @@
'VCLinkerTool': {
# Set /SUBSYSTEM:WINDOWS.
'SubSystem': '2',
'EntryPointSymbol' : 'wWinMainCRTStartup',
},
'VCManifestTool': {
'AdditionalManifestFiles': [
@@ -112,7 +111,8 @@
'-lrpcrt4.lib',
'-lopengl32.lib',
'-lglu32.lib',
'-l$(ConfigurationName)/libcef.lib'
'-l$(ConfigurationName)/libcef.lib',
'-l$(ConfigurationName)/cef_sandbox.lib',
],
},
'sources': [
@@ -224,6 +224,7 @@
'Resources/cef.pak',
'Resources/devtools_resources.pak',
'Resources/locales/',
'$(BUILDTYPE)/chrome-sandbox',
'$(BUILDTYPE)/libcef.so',
'$(BUILDTYPE)/libffmpegsumo.so',
],

View File

@@ -3,6 +3,10 @@ if [ -z "$1" ]; then
echo "ERROR: Please specify a build target: Debug or Release"
else
make -j8 cefclient BUILDTYPE=$1
if [ $? -eq 0 ]; then
echo "Giving SUID permissions to chrome-sandbox..."
echo "(using sudo so you may be asked for your password)"
sudo -- chown root:root "out/$1/chrome-sandbox" &&
sudo -- chmod 4755 "out/$1/chrome-sandbox"
fi
fi

View File

@@ -169,6 +169,16 @@ def transfer_files(cef_dir, script_dir, transfer_cfg, output_dir, quiet):
new_path = cfg['new_header_path']
normalize_headers(dst, new_path)
def combine_libs(build_dir, libs, dest_lib):
""" Combine multiple static libraries into a single static library. """
cmdline = 'msvs_env.bat python combine_libs.py -o "%s"' % dest_lib
for lib in libs:
lib_path = os.path.join(build_dir, lib)
if not path_exists(lib_path):
raise Exception('Library not found: ' + lib_path)
cmdline = cmdline + ' "%s"' % lib_path
run(cmdline, os.path.join(cef_dir, 'tools'))
def generate_msvs_projects(version):
""" Generate MSVS projects for the specified version. """
sys.stdout.write('Generating '+version+' project files...')
@@ -464,9 +474,23 @@ if platform == 'windows':
if options.ninjabuild:
out_dir = os.path.join(src_dir, 'out')
libcef_dll_file = 'libcef.dll.lib'
sandbox_libs = [
'obj\\base\\base.lib',
'obj\\base\\base_static.lib',
'obj\\cef\\cef_sandbox.lib',
'obj\\base\\third_party\\dynamic_annotations\\dynamic_annotations.lib',
'obj\\sandbox\\sandbox.lib',
]
else:
out_dir = os.path.join(src_dir, 'build')
libcef_dll_file = 'lib/libcef.lib'
sandbox_libs = [
'lib\\base.lib',
'lib\\base_static.lib',
'lib\\cef_sandbox.lib',
'lib\\dynamic_annotations.lib',
'lib\\sandbox.lib',
]
valid_build_dir = None
@@ -485,6 +509,7 @@ if platform == 'windows':
copy_files(os.path.join(build_dir, '*.dll'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, libcef_dll_file), os.path.join(dst_dir, 'libcef.lib'), \
options.quiet)
combine_libs(build_dir, sandbox_libs, os.path.join(dst_dir, 'cef_sandbox.lib'));
if not options.nosymbols:
# create the symbol output directory
@@ -506,6 +531,7 @@ if platform == 'windows':
if mode != 'client':
copy_file(os.path.join(build_dir, libcef_dll_file), os.path.join(dst_dir, 'libcef.lib'), \
options.quiet)
combine_libs(build_dir, sandbox_libs, os.path.join(dst_dir, 'cef_sandbox.lib'));
else:
copy_file(os.path.join(build_dir, 'cefclient.exe'), dst_dir, options.quiet)
@@ -644,6 +670,7 @@ elif platform == 'linux':
valid_build_dir = build_dir
dst_dir = os.path.join(output_dir, 'Debug')
make_dir(dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet)
copy_file(os.path.join(build_dir, lib_dir_name, 'libcef.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'libffmpegsumo.so'), dst_dir, options.quiet)
else:
@@ -663,6 +690,7 @@ elif platform == 'linux':
copy_file(os.path.join(build_dir, 'cefclient'), dst_dir, options.quiet)
else:
copy_file(os.path.join(build_dir, lib_dir_name, 'libcef.so'), dst_dir, options.quiet)
copy_file(os.path.join(build_dir, 'chrome_sandbox'), os.path.join(dst_dir, 'chrome-sandbox'), options.quiet)
copy_file(os.path.join(build_dir, 'libffmpegsumo.so'), dst_dir, options.quiet)
else:
sys.stderr.write("No Release build files.\n")

56
tools/msvs_env.bat Normal file
View File

@@ -0,0 +1,56 @@
@echo off
:: Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
:: reserved. Use of this source code is governed by a BSD-style license
:: that can be found in the LICENSE file.
:: Set up the environment for use with MSVS tools and then execute whatever
:: was specified on the command-line.
set RC=
setlocal
:: In case it's already provided via the environment.
set vcvars="%CEF_VCVARS%"
if exist %vcvars% goto found_vcvars
:: Hardcoded list of MSVS paths.
:: Alternatively we could 'reg query' this key:
:: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Setup\VS;ProductDir
set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 11.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
:: VS 2008 vcvars isn't standalone, it needs this env var.
set VS90COMNTOOLS=%PROGRAMFILES(X86)%\Microsoft Visual Studio 9.0\Common7\Tools\
set vcvars="%PROGRAMFILES(X86)%\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
set VS90COMNTOOLS=%PROGRAMFILES%\Microsoft Visual Studio 9.0\Common7\Tools\
set vcvars="%PROGRAMFILES%\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
if exist %vcvars% goto found_vcvars
set RC=1
echo Failed to find vcvars
goto end
:found_vcvars
echo vcvars:
echo %vcvars%
call %vcvars%
echo PATH:
echo %PATH%
%*
:end
endlocal & set RC=%ERRORLEVEL%
goto omega
:returncode
exit /B %RC%
:omega
call :returncode %RC%