diff options
author | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 03:33:36 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 03:33:36 +0000 |
commit | 8c40f3212b62b828f3cfbe151fb3ecd2294e44ca (patch) | |
tree | ea582d6c5b274418ff853eb67bc8bbbe2ed2d619 /build | |
parent | 06ead8788ef8d9ea7e5db736d563a7fb25df059d (diff) | |
download | chromium_src-8c40f3212b62b828f3cfbe151fb3ecd2294e44ca.zip chromium_src-8c40f3212b62b828f3cfbe151fb3ecd2294e44ca.tar.gz chromium_src-8c40f3212b62b828f3cfbe151fb3ecd2294e44ca.tar.bz2 |
Give plug-in processes an executable heap and disable PIE/ASLR for Native
Client loader processes.
Some plug-ins depend on having an executable heap. They write code to data
pages and attempt to execute it without calling mprotect to mark this code
as executable.
Native Client needs to allocate a contiguous 1GB of address space. ASLR may
interfere with there being a "hole" this large in the address space by the
time NaCl makes its request.
Non-executable heaps are only available in 10.7 and later for 32-bit
processes.
PIE/ASLR was formerly disabled for all processes other than the browser
process. This change reenables it for all processes other than the NaCl
loader. PIE/ASLR is available on 10.5 and later, although the implementation
is stronger in 10.7 than in earlier releases.
This change results in two new helpers in addition to the existing
Chromium Helper.app: Chromium Helper EH.app (for executable heaps) and
Chromium Helper NP.app (for no PIE). libplugin_carbon_interpose.dylib moves
out of the helper .app and directly into the versioned directory. The
InfoPlist.strings have been removed from the helper app, but empty .lproj
directories remain.
BUG=90221, 93551
TEST=everything
Review URL: http://codereview.chromium.org/7714018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97984 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build')
-rw-r--r-- | build/common.gypi | 20 | ||||
-rwxr-xr-x | build/mac/change_mach_o_flags.py (renamed from build/mac/make_heap_non_executable.py) | 79 | ||||
-rwxr-xr-x | build/mac/change_mach_o_flags_from_xcode.sh | 14 | ||||
-rwxr-xr-x | build/mac/make_heap_non_executable_from_xcode.sh | 15 |
4 files changed, 87 insertions, 41 deletions
diff --git a/build/common.gypi b/build/common.gypi index 89824b3..b6b179a 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -1679,16 +1679,20 @@ 'postbuilds': [ { # Arranges for data (heap) pages to be protected against - # code execution when running on Mac OS X 10.7 ("Lion"). + # code execution when running on Mac OS X 10.7 ("Lion"), and + # ensures that the position-independent executable (PIE) bit + # is set for ASLR when running on Mac OS X 10.5 ("Leopard"). 'variables': { - # Define make_heap_non_executable in a variable ending in - # _path so that gyp understands it's a path and performs - # proper relativization during dict merging. - 'make_heap_non_executable_path': - 'mac/make_heap_non_executable_from_xcode.sh', + # Define change_mach_o_flags in a variable ending in _path + # so that GYP understands it's a path and performs proper + # relativization during dict merging. + 'change_mach_o_flags_path': + 'mac/change_mach_o_flags_from_xcode.sh', }, - 'postbuild_name': 'Make Heap Non-Executable', - 'action': ['<(make_heap_non_executable_path)'], + 'postbuild_name': 'Change Mach-O Flags', + 'action': [ + '<(change_mach_o_flags_path)', + ], }, ], }], diff --git a/build/mac/make_heap_non_executable.py b/build/mac/change_mach_o_flags.py index 507403a..1dfe07f 100755 --- a/build/mac/make_heap_non_executable.py +++ b/build/mac/change_mach_o_flags.py @@ -4,10 +4,20 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Usage: make_heap_non_executable.py <executable_path> +# Usage: change_mach_o_flags.py [--executable-heap] [--no-pie] <executable_path> # # Arranges for the executable at |executable_path| to have its data (heap) -# pages protected to prevent execution on Mac OS X 10.7 ("Lion"). +# pages protected to prevent execution on Mac OS X 10.7 ("Lion"), and to have +# the PIE (position independent executable) bit set to enable ASLR (address +# space layout randomization). With --executable-heap or --no-pie, the +# respective bits are cleared instead of set, making the heap executable or +# disabling PIE/ASLR. +# +# This script is able to operate on thin (single-architecture) Mach-O files +# and fat (universal, multi-architecture) files. When operating on fat files, +# it will set or clear the bits for each architecture contained therein. +# +# NON-EXECUTABLE HEAP # # Traditionally in Mac OS X, 32-bit processes did not have data pages set to # prohibit execution. Although user programs could call mprotect and @@ -47,12 +57,24 @@ # with appropriate protection even when vm.allow_data_exec has been tampered # with. # -# This script is able to operate on thin (single-architecture) Mach-O files -# and fat (universal, multi-architecture) files. When operating on fat files, -# it will set the MH_NO_HEAP_EXECUTION bit for each architecture contained -# therein. +# POSITION-INDEPENDENT EXECUTABLES/ADDRESS SPACE LAYOUT RANDOMIZATION +# +# This script sets or clears the MH_PIE bit in an executable's Mach-O header, +# enabling or disabling position independence on Mac OS X 10.5 and later. +# Processes running position-independent executables have varying levels of +# ASLR protection depending on the OS release. The main executable's load +# address, shared library load addresess, and the heap and stack base +# addresses may be randomized. Position-independent executables are produced +# by supplying the -pie flag to the linker (or defeated by supplying -no_pie). +# Executables linked with a deployment target of 10.7 or higher have PIE on +# by default. +# +# This script is never strictly needed during the build to enable PIE, as all +# linkers used are recent enough to support -pie. However, it's used to +# disable the PIE bit as needed on already-linked executables. +import optparse import os import struct import sys @@ -68,7 +90,8 @@ MH_CIGAM = 0xcefaedfe MH_MAGIC_64 = 0xfeedfacf MH_CIGAM_64 = 0xcffaedfe MH_EXECUTE = 0x2 -MH_NO_HEAP_EXECUTION = 0x1000000 +MH_PIE = 0x00200000 +MH_NO_HEAP_EXECUTION = 0x01000000 class MachOError(Exception): @@ -150,14 +173,15 @@ def WriteUInt32(file, uint32, endian): file.write(bytes) -def HandleMachOFile(file, offset=0): +def HandleMachOFile(file, options, offset=0): """Seeks the file-like |file| object to |offset|, reads its |mach_header|, and rewrites the header's |flags| field if appropriate. The header's endianness is detected. Both 32-bit and 64-bit Mach-O headers are supported (mach_header and mach_header_64). Raises MachOError if used on a header that does not have a known magic number or is not of type MH_EXECUTE. The - MH_NO_HEAP_EXECUTION is set in the |flags| field and written to |file| if - not already set. If already set, nothing is written.""" + MH_PIE and MH_NO_HEAP_EXECUTION bits are set or cleared in the |flags| field + according to |options| and written to |file| if any changes need to be made. + If already set or clear as specified by |options|, nothing is written.""" CheckedSeek(file, offset) magic = ReadUInt32(file, '<') @@ -178,13 +202,24 @@ def HandleMachOFile(file, offset=0): 'Mach-O file at offset %d is type 0x%x, expected MH_EXECUTE' % \ (offset, filetype) - if not flags & MH_NO_HEAP_EXECUTION: + original_flags = flags + + if options.no_heap_execution: flags |= MH_NO_HEAP_EXECUTION + else: + flags &= ~MH_NO_HEAP_EXECUTION + + if options.pie: + flags |= MH_PIE + else: + flags &= ~MH_PIE + + if flags != original_flags: CheckedSeek(file, offset + 24) WriteUInt32(file, flags, endian) -def HandleFatFile(file, fat_offset=0): +def HandleFatFile(file, options, fat_offset=0): """Seeks the file-like |file| object to |offset| and loops over its |fat_header| entries, calling HandleMachOFile for each.""" @@ -201,25 +236,33 @@ def HandleFatFile(file, fat_offset=0): # HandleMachOFile will seek around. Come back here after calling it, in # case it sought. fat_arch_offset = file.tell() - HandleMachOFile(file, offset) + HandleMachOFile(file, options, offset) CheckedSeek(file, fat_arch_offset) def main(me, args): - if len(args) != 1: - print >>sys.stderr, 'usage: %s <executable_path>' % me + parser = optparse.OptionParser('%prog [options] <executable_path>') + parser.add_option('--executable-heap', action='store_false', + dest='no_heap_execution', default=True, + help='Clear the MH_NO_HEAP_EXECUTION bit') + parser.add_option('--no-pie', action='store_false', + dest='pie', default=True, + help='Clear the MH_PIE bit') + (options, loose_args) = parser.parse_args(args) + if len(loose_args) != 1: + parser.print_usage() return 1 - executable_path = args[0] + executable_path = loose_args[0] executable_file = open(executable_path, 'rb+') magic = ReadUInt32(executable_file, '<') if magic == FAT_CIGAM: # Check FAT_CIGAM and not FAT_MAGIC because the read was little-endian. - HandleFatFile(executable_file) + HandleFatFile(executable_file, options) elif magic == MH_MAGIC or magic == MH_CIGAM or \ magic == MH_MAGIC_64 or magic == MH_CIGAM_64: - HandleMachOFile(executable_file) + HandleMachOFile(executable_file, options) else: raise MachOError, '%s is not a Mach-O or fat file' % executable_file diff --git a/build/mac/change_mach_o_flags_from_xcode.sh b/build/mac/change_mach_o_flags_from_xcode.sh new file mode 100755 index 0000000..ab3ee49 --- /dev/null +++ b/build/mac/change_mach_o_flags_from_xcode.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# 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. + +# This is a small wrapper script around change_mach_o_flags.py allowing it to +# be invoked easily from Xcode. change_mach_o_flags.py expects its arguments +# on the command line, but Xcode puts its parameters in the environment. + +set -e + +exec "$(dirname "${0}")/change_mach_o_flags.py" \ + "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" diff --git a/build/mac/make_heap_non_executable_from_xcode.sh b/build/mac/make_heap_non_executable_from_xcode.sh deleted file mode 100755 index adfc25d..0000000 --- a/build/mac/make_heap_non_executable_from_xcode.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# 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. - -# This is a small wrapper script around make_heap_non_executable.py allowing -# it to be invoked easily from Xcode. make_heap_non_executable.py expects its -# argument on the command line, and Xcode puts all of its parameters in the -# environment. - -set -e - -exec "$(dirname "${0}")/make_heap_non_executable.py" \ - "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" |