Skip to content

Commit

Permalink
base: Fix trace mode on El Capitan
Browse files Browse the repository at this point in the history
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.

git-svn-id: https://svn.macports.org/repository/macports/trunk/base@141420 d073be05-634f-4543-b044-5fe20cf6d1d6
  • Loading branch information
neverpanic committed Oct 18, 2015
1 parent 7f1c332 commit de1977a
Show file tree
Hide file tree
Showing 9 changed files with 652 additions and 23 deletions.
8 changes: 8 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,14 @@ fi
eval "prefix_expanded=$prefix"
eval "exec_prefix_expanded=$exec_prefix"
AC_SUBST(prefix_expanded)

# Define a path where our trace mode workaround for SIP-protected binaries on
# >= 10.11 puts copies
AC_DEFINE_UNQUOTED(
[DARWINTRACE_SIP_WORKAROUND_PATH],
["${prefix}/var/macports/sip-workaround"],
[Absolute path to a directory used by darwintrace to copy SIP-protected files before executing])

# do this twice, since there is a nested variable of
# ${prefix} inside of ${sysconfdir}
eval "MPCONFIGDIR_EXPANDED=$MPCONFIGDIR"
Expand Down
2 changes: 2 additions & 0 deletions doc/base.mtree.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
..
registry
..
sip-workaround mode=01777
..
software
..
..
Expand Down
58 changes: 45 additions & 13 deletions src/darwintracelib1.0/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,62 @@ include ../../Mk/macports.autoconf.mk

# This Makefile will only be run on Darwin systems; we can safely use
# Apple-specifics here
SRCS= $(wildcard *.c)
OBJS= $(SRCS:%.c=%.o)
SHLIB_NAME= darwintrace${SHLIB_SUFFIX}
INSTALLDIR= ${DESTDIR}${TCL_PACKAGE_PATH}/darwintrace1.0
SRCS = \
access.c \
close.c \
darwintrace.c \
dup2.c \
mkdir.c \
open.c \
proc.c \
readdir.c \
readlink.c \
rename.c \
rmdir.c \
sip_copy_proc.c \
stat.c \
unlink.c

OBJS = $(SRCS:%.c=%.o)
SHLIB_NAME = darwintrace$(SHLIB_SUFFIX)
INSTALLDIR = $(DESTDIR)$(TCL_PACKAGE_PATH)/darwintrace1.0

# Yes, we know having $ signs in identifiers is not a very good idea; in the
# case of darwintrace we still need them, though.
CFLAGS_PEDANTIC=
CFLAGS+= -fPIC ${UNIVERSAL_ARCHFLAGS}
SHLIB_LDFLAGS+=${UNIVERSAL_ARCHFLAGS}
CFLAGS_PEDANTIC =
CFLAGS += -fPIC $(UNIVERSAL_ARCHFLAGS)
SHLIB_LDFLAGS += $(UNIVERSAL_ARCHFLAGS)

# Generate dependency information
CPPFLAGS += -MMD -MP

all:: $(SHLIB_NAME)

all:: ${SHLIB_NAME}
# Copy sip_copy_proc.{c,h} from pextlib1.0 where they are also needed
sip_copy_proc.c: ../pextlib1.0/sip_copy_proc.c sip_copy_proc.h
cp $< $@

$(SHLIB_NAME):: ${OBJS}
${SHLIB_LD} ${OBJS} -o ${SHLIB_NAME} ${SHLIB_LDFLAGS} ${LIBS}
sip_copy_proc.h: ../pextlib1.0/sip_copy_proc.h
cp $< $@

# This won't be automatically detected during the first run of make, where the
# .d files do not exist yet
proc.c: sip_copy_proc.h

$(SHLIB_NAME):: $(OBJS)
$(SHLIB_LD) $(OBJS) -o $(SHLIB_NAME) $(SHLIB_LDFLAGS) $(LIBS)

clean::
rm -f ${OBJS} ${SHLIB_NAME} so_locations
rm -f $(OBJS) $(SHLIB_NAME) so_locations sip_copy_proc.c sip_copy_proc.h $(SRCS:%.c=%.d)

distclean:: clean
rm -f Makefile

install:: all
$(INSTALL) -d -o "${DSTUSR}" -g "${DSTGRP}" -m "${DSTMODE}" "${INSTALLDIR}"
$(INSTALL) -o "${DSTUSR}" -g "${DSTGRP}" -m 444 "${SHLIB_NAME}" "${INSTALLDIR}"
$(INSTALL) -d -o "$(DSTUSR)" -g "$(DSTGRP)" -m "$(DSTMODE)" "$(INSTALLDIR)"
$(INSTALL) -o "$(DSTUSR)" -g "$(DSTGRP)" -m 444 "$(SHLIB_NAME)" "$(INSTALLDIR)"

test::

# Include dependency information
-include $(SRCS:%.c=%.d)
5 changes: 3 additions & 2 deletions src/darwintracelib1.0/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#define DARWINTRACE_USE_PRIVATE_API 1
#include "darwintrace.h"
#include "sip_copy_proc.h"

#include <ctype.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -278,7 +279,7 @@ static int _dt_execve(const char *path, char *const argv[], char *const envp[])

// Call the original execve function, but restore environment
char **newenv = restore_env(envp);
result = execve(path, argv, newenv);
result = sip_copy_execve(path, argv, newenv);
free(newenv);
}
}
Expand Down Expand Up @@ -334,7 +335,7 @@ static int _dt_posix_spawn(pid_t *restrict pid, const char *restrict path, const
* we need to call the original posix_spawn from here. */
// call the original posix_spawn function, but restore environment
char **newenv = restore_env(envp);
result = posix_spawn(pid, path, file_actions, attrp, argv, newenv);
result = sip_copy_posix_spawn(pid, path, file_actions, attrp, argv, newenv);
free(newenv);
}
}
Expand Down
31 changes: 26 additions & 5 deletions src/pextlib1.0/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,32 @@ VPATH = @srcdir@
include ../../Mk/macports.autoconf.mk

OBJS= \
Pextlib.o strsed.o fgetln.o md5cmd.o setmode.o xinstall.o \
fs-traverse.o strcasecmp.o vercomp.o filemap.o base32cmd.o \
sha1cmd.o curl.o rmd160cmd.o sha256cmd.o readline.o uid.o \
tracelib.o tty.o readdir.o pipe.o adv-flock.o system.o \
mktemp.o realpath.o
Pextlib.o \
adv-flock.o \
base32cmd.o \
curl.o \
fgetln.o \
filemap.o \
fs-traverse.o \
md5cmd.o \
mktemp.o \
pipe.o \
readdir.o \
readline.o \
realpath.o \
rmd160cmd.o \
setmode.o \
sha1cmd.o \
sha256cmd.o \
sip_copy_proc.o \
strcasecmp.o \
strsed.o \
system.o \
tracelib.o \
tty.o \
uid.o \
vercomp.o \
xinstall.o
ifneq (@ac_cv_func_strlcat@,yes)
OBJS+=strlcat.o
endif
Expand Down

0 comments on commit de1977a

Please sign in to comment.