Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2852)

Unified Diff: build/mac/change_mach_o_flags.py

Issue 7714018: Give plug-in processes an executable heap and disable PIE/ASLR for Native (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/common.gypi ('k') | build/mac/change_mach_o_flags_from_xcode.sh » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/mac/change_mach_o_flags.py
===================================================================
--- build/mac/change_mach_o_flags.py (revision 97870)
+++ build/mac/change_mach_o_flags.py (working copy)
@@ -4,11 +4,21 @@
# 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
# mach_vm_protect to deny execution of code in data pages, the kernel would
@@ -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_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 @@
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 @@
'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 @@
# 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
« no previous file with comments | « build/common.gypi ('k') | build/mac/change_mach_o_flags_from_xcode.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698