Changeset 141420


Ignore:
Timestamp:
Oct 18, 2015, 12:49:32 AM (19 months ago)
Author:
cal@…
Message:

base: Fix trace mode on El Capitan

OS X El Capitan introduces System Integrity Protection for files. Executables
with this flag set will be started in a sanitized environment by the kernel,
stripping all DYLD_* variables. This breaks trace mode, because tracing relies
on preloading to wrap file related system calls using DYLD_INSERT_LIBRARIES.

A trivial workaround for the problem is to make a copy of the affected
binaries, which will strip the flag, and then adjust the invocation of the
binary to execute the copy instead (but leaving argv[0] as-is to avoid giving
the program an indication of being run from a non-standard location).

This change implements this approach by copying the SIP-flagged binaries to
$prefix/var/macports/sip-workaround on demand iff

  • the system has the SF_RESTRICTED flag defined
  • a binary is started with DYLD_INSERT_LIBRARIES set
  • the file exists and has SF_RESTRICTED set
  • the file isn't SUID or SGID (which we could not reliably copy, and which have never preserved DYLD_* variables)

If the file to be executed is a script and has a shebang line, the checks are
run on the interpreter instead, and if necessary, the interpreter is copied.
This requires interpreting the shebang line in user space.

Copies are created on-demand and are lazy: The file modification times are
checked before overwriting an existing copy. Copies are created in a per-user
folder, which will be created on-demand in a 1777 directory (like /tmp).

Changes are also needed way before darwintrace.dylib first runs: The DYLD_*
variables are already stripped in src/pextlib1.0/system.c, where
/usr/bin/sandbox-exec and /bin/sh are run, which both have the SF_RESTRICTED
flag on 10.11 now. Consequently, the same copying approach is applied there.

Because macports build run in a sandbox, the sandbox boundaries are extended to
allow access to $prefix/var/macports/sip-workaround.

Location:
trunk/base
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/configure.ac

    r140639 r141420  
    313313eval "exec_prefix_expanded=$exec_prefix"
    314314AC_SUBST(prefix_expanded)
     315
     316# Define a path where our trace mode workaround for SIP-protected binaries on
     317# >= 10.11 puts copies
     318AC_DEFINE_UNQUOTED(
     319        [DARWINTRACE_SIP_WORKAROUND_PATH],
     320        ["${prefix}/var/macports/sip-workaround"],
     321        [Absolute path to a directory used by darwintrace to copy SIP-protected files before executing])
     322
    315323# do this twice, since there is a nested variable of
    316324# ${prefix} inside of ${sysconfdir}
  • trunk/base/doc/base.mtree.in

    r100532 r141420  
    2424            registry
    2525            ..
     26            sip-workaround mode=01777
     27            ..
    2628            software
    2729            ..
  • trunk/base/src/darwintracelib1.0

    • Property svn:ignore
      •  

        old new  
         1*.d
        12Makefile
        23darwintrace.dylib
         4sip_copy_proc.c
         5sip_copy_proc.h
  • trunk/base/src/darwintracelib1.0/Makefile.in

    r122044 r141420  
    66# This Makefile will only be run on Darwin systems; we can safely use
    77# Apple-specifics here
    8 SRCS=           $(wildcard *.c)
    9 OBJS=           $(SRCS:%.c=%.o)
    10 SHLIB_NAME=     darwintrace${SHLIB_SUFFIX}
    11 INSTALLDIR=     ${DESTDIR}${TCL_PACKAGE_PATH}/darwintrace1.0
     8SRCS = \
     9        access.c \
     10        close.c \
     11        darwintrace.c \
     12        dup2.c \
     13        mkdir.c \
     14        open.c \
     15        proc.c \
     16        readdir.c \
     17        readlink.c \
     18        rename.c \
     19        rmdir.c \
     20        sip_copy_proc.c \
     21        stat.c \
     22        unlink.c
     23
     24OBJS = $(SRCS:%.c=%.o)
     25SHLIB_NAME = darwintrace$(SHLIB_SUFFIX)
     26INSTALLDIR = $(DESTDIR)$(TCL_PACKAGE_PATH)/darwintrace1.0
    1227
    1328# Yes, we know having $ signs in identifiers is not a very good idea; in the
    1429# case of darwintrace we still need them, though.
    15 CFLAGS_PEDANTIC=
    16 CFLAGS+= -fPIC ${UNIVERSAL_ARCHFLAGS}
    17 SHLIB_LDFLAGS+=${UNIVERSAL_ARCHFLAGS}
     30CFLAGS_PEDANTIC =
     31CFLAGS += -fPIC $(UNIVERSAL_ARCHFLAGS)
     32SHLIB_LDFLAGS += $(UNIVERSAL_ARCHFLAGS)
    1833
    19 all:: ${SHLIB_NAME}
     34# Generate dependency information
     35CPPFLAGS += -MMD -MP
    2036
    21 $(SHLIB_NAME):: ${OBJS}
    22         ${SHLIB_LD} ${OBJS} -o ${SHLIB_NAME} ${SHLIB_LDFLAGS} ${LIBS}
     37all:: $(SHLIB_NAME)
     38
     39# Copy sip_copy_proc.{c,h} from pextlib1.0 where they are also needed
     40sip_copy_proc.c: ../pextlib1.0/sip_copy_proc.c sip_copy_proc.h
     41        cp $< $@
     42
     43sip_copy_proc.h: ../pextlib1.0/sip_copy_proc.h
     44        cp $< $@
     45
     46# This won't be automatically detected during the first run of make, where the
     47# .d files do not exist yet
     48proc.c: sip_copy_proc.h
     49
     50$(SHLIB_NAME):: $(OBJS)
     51        $(SHLIB_LD) $(OBJS) -o $(SHLIB_NAME) $(SHLIB_LDFLAGS) $(LIBS)
    2352
    2453clean::
    25         rm -f ${OBJS} ${SHLIB_NAME} so_locations
     54        rm -f $(OBJS) $(SHLIB_NAME) so_locations sip_copy_proc.c sip_copy_proc.h $(SRCS:%.c=%.d)
    2655
    2756distclean:: clean
     
    2958
    3059install:: all
    31         $(INSTALL) -d -o "${DSTUSR}" -g "${DSTGRP}" -m "${DSTMODE}" "${INSTALLDIR}"
    32         $(INSTALL)    -o "${DSTUSR}" -g "${DSTGRP}" -m 444 "${SHLIB_NAME}" "${INSTALLDIR}"
     60        $(INSTALL) -d -o "$(DSTUSR)" -g "$(DSTGRP)" -m "$(DSTMODE)" "$(INSTALLDIR)"
     61        $(INSTALL)    -o "$(DSTUSR)" -g "$(DSTGRP)" -m 444 "$(SHLIB_NAME)" "$(INSTALLDIR)"
    3362
    3463test::
     64
     65# Include dependency information
     66-include $(SRCS:%.c=%.d)
  • trunk/base/src/darwintracelib1.0/proc.c

    r138557 r141420  
    3838#define DARWINTRACE_USE_PRIVATE_API 1
    3939#include "darwintrace.h"
     40#include "sip_copy_proc.h"
    4041
    4142#include <ctype.h>
     
    279280                        // Call the original execve function, but restore environment
    280281                        char **newenv = restore_env(envp);
    281                         result = execve(path, argv, newenv);
     282                        result = sip_copy_execve(path, argv, newenv);
    282283                        free(newenv);
    283284                }
     
    335336                        // call the original posix_spawn function, but restore environment
    336337                        char **newenv = restore_env(envp);
    337                         result = posix_spawn(pid, path, file_actions, attrp, argv, newenv);
     338                        result = sip_copy_posix_spawn(pid, path, file_actions, attrp, argv, newenv);
    338339                        free(newenv);
    339340                }
  • trunk/base/src/pextlib1.0/Makefile.in

    r138165 r141420  
    55
    66OBJS= \
    7         Pextlib.o strsed.o fgetln.o md5cmd.o setmode.o xinstall.o \
    8         fs-traverse.o strcasecmp.o vercomp.o filemap.o base32cmd.o \
    9         sha1cmd.o curl.o rmd160cmd.o sha256cmd.o readline.o uid.o \
    10         tracelib.o tty.o readdir.o pipe.o adv-flock.o system.o \
    11         mktemp.o realpath.o
     7        Pextlib.o \
     8        adv-flock.o \
     9        base32cmd.o \
     10        curl.o \
     11        fgetln.o \
     12        filemap.o \
     13        fs-traverse.o \
     14        md5cmd.o \
     15        mktemp.o \
     16        pipe.o \
     17        readdir.o \
     18        readline.o \
     19        realpath.o \
     20        rmd160cmd.o \
     21        setmode.o \
     22        sha1cmd.o \
     23        sha256cmd.o \
     24        sip_copy_proc.o \
     25        strcasecmp.o \
     26        strsed.o \
     27        system.o \
     28        tracelib.o \
     29        tty.o \
     30        uid.o \
     31        vercomp.o \
     32        xinstall.o
    1233ifneq (@ac_cv_func_strlcat@,yes)
    1334OBJS+=strlcat.o
  • trunk/base/src/pextlib1.0/system.c

    r141415 r141420  
    5959
    6060#include "system.h"
     61#include "sip_copy_proc.h"
    6162#include "Pextlib.h"
    6263
     
    238239            args[5] = cmdstring;
    239240            args[6] = NULL;
    240             execve(sandbox_exec_path, args, environ);
     241            sip_copy_execve(sandbox_exec_path, args, environ);
    241242        } else {
    242243            args[0] = "sh";
     
    244245            args[2] = cmdstring;
    245246            args[3] = NULL;
    246             execve("/bin/sh", args, environ);
     247            sip_copy_execve("/bin/sh", args, environ);
    247248        }
    248249        exit(128);
  • trunk/base/src/port1.0/portsandbox.tcl

    r123673 r141420  
    4343# sandbox-exec -p '(version 1) (allow default) (deny file-write*) (allow file-write* <filter>)' some-command
    4444proc portsandbox::set_profile {target} {
    45     global os.major portsandbox_profile workpath distpath altprefix \
     45    global os.major portsandbox_profile workpath distpath prefix altprefix \
    4646        package.destpath configure.ccache ccache_dir
    4747
     
    7979    # TODO: remove altprefix support
    8080    lappend allow_dirs $workpath $altprefix
     81    lappend allow_dirs $prefix/var/macports/sip-workaround
    8182    if {${configure.ccache}} {
    8283        lappend allow_dirs $ccache_dir
Note: See TracChangeset for help on using the changeset viewer.