[113026] trunk/base/src

cal at macports.org cal at macports.org
Wed Nov 6 17:50:28 PST 2013


Revision: 113026
          https://trac.macports.org/changeset/113026
Author:   cal at macports.org
Date:     2013-11-06 17:50:28 -0800 (Wed, 06 Nov 2013)
Log Message:
-----------
darwintrace: major overhaul, now successfully compiles all ports I have installed (except go)

 - Split darwintrace.c into separate files for different syscalls to clean up
   the mess. This does prevent some inlining that used to take place before,
   makes some global variables necessary and required me to define
   a darwintrace functions API, but it makes the whole thing so much cleaner.
 - Now compiles without -Wno-deprecated-declarations, because stat.c no longer
   includes sys/stat.h. While that might seem wrong at first, it actually makes
   things easier for us, because we can avoid the function renaming magic Apple
   introduced to support 64-bit inodes.
 - darwintrace now prints all syscalls with their returned result in debug mode
   (except for syscalls that do not return on success, those are printed with
   a question mark instead, but with the return value, if they do return).
 - Dropped legacy code supporting non C99 compilers in darwintrace.c
 - Removed the code that enabled redirecting opened locations into a different
   directory, since it was completely untested, very likely broken and hard to
   maintain.
 - Added handler for posix_spawn(2). This fixes a lot of problems that would
   previously break builds (e.g. using /opt/local/bin/ar, although that should
   have been outside the sandbox, which in turn used /opt/local/bin/ranlib,
   which failed and broke builds).
 - Avoid memory leak when execve(2) failed that was also affecting
   posix_spawn(2).
 - Use compare and swap primitives provided by Apple in libkern/OSAtomic.h
   instead of GCC's __sync_bool_compare_and_swap. Should fix the build on some
   older systems that don't support the compiler builtin.
 - Use getattrlist(2) instead of fcntl(F_GETPATH) to get the absolute path of
   files referenced using the volfs at /.vol/. TODO: Do this before checking
   against sandbox bounds (it's currently only used before reporting sandbox
   violations).
 - Improve support for tracing symlinks: Previously, only the symlink's name
   would be checked against the sandbox, not its target. Now both the name and
   the target is checked, if it is the last component of a path to be checked
   against the sandbox bounds. While there are some directory symlinks in some
   ports I doubt any of them cross a port boundary, which would be incorrectly
   detected at the moment.
 - Add a flag to support allowing access to directories completely for syscalls
   that do not operate on directories (i.e., all except rename, rmdir and
   mkdir).
 - Increase the size of the communication buffer used between tracelib and
   darwintrace.
 - Abort in tracelib, if the filemap buffer size is exceeded, rather than
   reading invalid memory later in darwintrace.
 - Fix a segfault in tracelib when installing a port with no dependents.

Modified Paths:
--------------
    trunk/base/src/darwintracelib1.0/Makefile
    trunk/base/src/darwintracelib1.0/darwintrace.c
    trunk/base/src/pextlib1.0/tracelib.c

Added Paths:
-----------
    trunk/base/src/darwintracelib1.0/access.c
    trunk/base/src/darwintracelib1.0/close.c
    trunk/base/src/darwintracelib1.0/darwintrace.h
    trunk/base/src/darwintracelib1.0/dup2.c
    trunk/base/src/darwintracelib1.0/mkdir.c
    trunk/base/src/darwintracelib1.0/open.c
    trunk/base/src/darwintracelib1.0/proc.c
    trunk/base/src/darwintracelib1.0/readdir.c
    trunk/base/src/darwintracelib1.0/readlink.c
    trunk/base/src/darwintracelib1.0/rename.c
    trunk/base/src/darwintracelib1.0/rmdir.c
    trunk/base/src/darwintracelib1.0/stat.c
    trunk/base/src/darwintracelib1.0/unlink.c

Modified: trunk/base/src/darwintracelib1.0/Makefile
===================================================================
--- trunk/base/src/darwintracelib1.0/Makefile	2013-11-07 01:32:29 UTC (rev 113025)
+++ trunk/base/src/darwintracelib1.0/Makefile	2013-11-07 01:50:28 UTC (rev 113026)
@@ -1,6 +1,7 @@
 # This Makefile will only be run on Darwin systems; we can safely use
 # Apple-specifics here
-OBJS=		darwintrace.o
+SRCS=		$(wildcard *.c)
+OBJS=		$(SRCS:%.c=%.o)
 SHLIB_NAME=	darwintrace${SHLIB_SUFFIX}
 INSTALLDIR=	${DESTDIR}${datadir}/macports/Tcl/darwintrace1.0
 
@@ -9,11 +10,7 @@
 # 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=
-# The /l?stat64/ functions are deprecated since 10.6. We know that, but still
-# want to use them anyway.
-# Build darwintrace for universal archs so support all binaries this system can
-# run.
-CFLAGS+= -fPIC -Wno-deprecated-declarations ${UNIVERSAL_ARCHFLAGS}
+CFLAGS+= -fPIC ${UNIVERSAL_ARCHFLAGS}
 SHLIB_LDFLAGS+=${UNIVERSAL_ARCHFLAGS}
 
 all:: ${SHLIB_NAME}

Added: trunk/base/src/darwintracelib1.0/access.c
===================================================================
--- trunk/base/src/darwintracelib1.0/access.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/access.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+int access(const char *path, int amode) {
+#define access(x, y) syscall(SYS_access, (x), (y))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = access(path, amode);
+	}
+
+	debug_printf("access(%s) = %d\n", path, result);
+
+	return result;
+#undef access
+}


Property changes on: trunk/base/src/darwintracelib1.0/access.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/close.c
===================================================================
--- trunk/base/src/darwintracelib1.0/close.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/close.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#define DARWINTRACE_USE_PRIVATE_API 1
+#include "darwintrace.h"
+
+#include <stdio.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c close(2) to deny closing the file descriptor used by
+ * darwintrace to communicate with the control socket. Since we sometimes want
+ * to close our socket using \c fclose(3) and that internally calls \c
+ * close(2), we need a way to specifically allow closing the socket when we
+ * need to. This possibility is the \c __darwintrace_close_sock variable, which
+ * will be set to the FD to be closed when closing should be allowed.
+ */
+int close(int fd) {
+#define close(x) syscall(SYS_close, (x))
+	__darwintrace_setup();
+
+	FILE *stream = __darwintrace_sock();
+	if (stream) {
+		int dtsock = fileno(stream);
+		if (fd == dtsock && dtsock != __darwintrace_close_sock) {
+			errno = EBADF;
+			return -1;
+		}
+	}
+
+	return close(fd);
+#undef close
+}


Property changes on: trunk/base/src/darwintracelib1.0/close.c
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: trunk/base/src/darwintracelib1.0/darwintrace.c
===================================================================
--- trunk/base/src/darwintracelib1.0/darwintrace.c	2013-11-07 01:32:29 UTC (rev 113025)
+++ trunk/base/src/darwintracelib1.0/darwintrace.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -35,44 +35,17 @@
  * @APPLE_BSD_LICENSE_HEADER_END@
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#define DARWINTRACE_USE_PRIVATE_API 1
+#include "darwintrace.h"
 
-#if HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
+#ifdef HAVE_LIBKERN_OSATOMIC_H
+#include <libkern/OSAtomic.h>
 #endif
 
-#if defined(_DARWIN_FEATURE_64_BIT_INODE) && !defined(_DARWIN_FEATURE_ONLY_64_BIT_INODE)
-/* The architecture we're building for has multiple versions of stat.
-   We need to undo sys/cdefs.h changes for _DARWIN_FEATURE_64_BIT_INODE */
-#undef  __DARWIN_64_BIT_INO_T
-#define __DARWIN_64_BIT_INO_T 0
-#undef  __DARWIN_SUF_64_BIT_INO_T
-#define __DARWIN_SUF_64_BIT_INO_T ""
-#undef _DARWIN_FEATURE_64_BIT_INODE
-#endif
-
-#ifdef HAVE_CRT_EXTERNS_H
-#include <crt_externs.h>
-#endif
-
-#ifdef HAVE_SYS_PATHS_H
-#include <sys/paths.h>
-#endif
-
-#include <ctype.h>
-#include <dirent.h>
-#include <dlfcn.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <pthread.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
+#include <sys/attr.h>
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
@@ -81,6 +54,14 @@
 #include <sys/un.h>
 #include <unistd.h>
 
+#if __DARWIN_64_BIT_INO_T
+#define STATSYSNUM SYS_stat64
+#define LSTATSYSNUM SYS_lstat64
+#else
+#define STATSYSNUM SYS_stat
+#define LSTATSYSNUM SYS_lstat
+#endif
+
 #ifndef HAVE_STRLCPY
 /* Define strlcpy if it's not available. */
 size_t strlcpy(char *dst, const char *src, size_t size) {
@@ -99,52 +80,43 @@
 
 #include "../pextlib1.0/strlcat.c"
 
-/* global variables (only checked when setup is first called)
- * DARWINTRACE_LOG
- *    path to the log file (no logging happens if it's unset).
+// Global Variables
+/**
+ * PID of the process darwintrace was last used in. This is used to detect
+ * forking and opening a new connection to the control socket in the child
+ * process. Not doing so would potentially cause two processes writing to the
+ * same socket.
  */
+pid_t __darwintrace_pid = (pid_t) - 1;
 
-/*
- * DARWINTRACE_DEBUG: verbose output of operations to debug darwintrace
+/**
+ * Helper variable containing the number of the darwintrace socket, iff the
+ * close(2) syscall should be allowed to close it. Used by \c
+ * __darwintrace_close.
  */
-#ifndef DARWINTRACE_DEBUG
-#define DARWINTRACE_DEBUG (0)
-#endif
+volatile int __darwintrace_close_sock = -1;
 
+/**
+ * Debug socket. Will be initialized by a constructor function.
+ */
+FILE *__darwintrace_stderr = NULL;
+
 static inline void __darwintrace_log_op(const char *op, const char *path);
-static void __darwintrace_copy_env() __attribute__((constructor));
 static void __darwintrace_setup_tls() __attribute__((constructor));
-static inline char *__darwintrace_alloc_env(const char *varName, const char *varValue);
-static inline char *const *__darwintrace_restore_env(char *const envp[]);
-static inline void __darwintrace_setup();
 static char *__send(const char *buf, uint32_t len, int answer);
 
 /**
- * PID of the process darwintrace was last used in. This is used to detect
- * forking and opening a new connection to the control socket in the child
- * process. Not doing so would potentially cause two processes writing to the
- * same socket.
- */
-static pid_t __darwintrace_pid = (pid_t) - 1;
-
-/**
  * pthread_key_ts for the pthread_t returned by pthread_self() and the
  * darwintrace socket to ensure the socket is only used from a single thread.
  */
 static pthread_key_t tid_key;
-static pthread_key_t sock_key;
+// The sock key is needed in close(2) and dup2(2)
+pthread_key_t sock_key;
 
 /**
- * Helper variable containing the number of the darwintrace socket, iff the
- * close(2) syscall should be allowed to close it. Used by \c
- * __darwintrace_close.
- */
-static volatile int __darwintrace_close_sock = -1;
-
-/**
  * size of the communication buffer
  */
-#define BUFFER_SIZE 1024
+#define BUFFER_SIZE 4096
 
 /**
  * Variable holding the sandbox bounds in the following format:
@@ -153,55 +125,18 @@
  *  <operation>     :: '0' | '1' | '2'
  * where
  *  0: allow
- *  1: map the path to the one given in additional_data
+ *  1: map the path to the one given in additional_data (currently unsupported)
  *  2: check for a dependency using the socket
  */
 static char *filemap;
 
 enum {
     FILEMAP_ALLOW = 0,
-    FILEMAP_REDIR = 1,
+    // FILEMAP_REDIR = 1,
     FILEMAP_ASK   = 2
 };
 
 /**
- * Copy of the DYLD_INSERT_LIBRARIES environment variable to restore it in
- * execve(2). DYLD_INSERT_LIBRARIES is needed to preload this library into any
- * process' address space.
- */
-static char *__env_dyld_insert_libraries;
-
-/**
- * Copy of the DYLD_FORCE_FLAT_NAMESPACE environment variable to restore it in
- * execve(2). DYLD_FORCE_FLAT_NAMESPACE=1 is needed for the preload-based
- * sandbox to work.
- */
-static char *__env_dyld_force_flat_namespace;
-
-/**
- * Copy of the DARWINTRACE_LOG environment variable to restore it in execve(2).
- * Contains the path to the unix socket used for communication with the
- * MacPorts-side of the sandbox.
- */
-static char *__env_darwintrace_log;
-
-#if DARWINTRACE_DEBUG
-#   if __STDC_VERSION__>=199901L
-#       define debug_printf(format, ...) \
-	fprintf(stderr, "darwintrace[%d]: " format, getpid(), __VA_ARGS__);
-#   else
-__attribute__((format(printf, 1, 2))) static inline void debug_printf(const char *format, ...) {
-	va_list args;
-	va_start(args, format);
-	vfprintf(stderr, format, args);
-	va_end(args);
-}
-#   endif
-#else
-#   define debug_printf(...)
-#endif
-
-/**
  * Setup method called as constructor to set up thread-local storage for the
  * thread id and the darwintrace socket.
  */
@@ -217,13 +152,6 @@
 }
 
 /**
- * Convenience getter function for the thread-local darwintrace socket
- */
-static inline FILE *__darwintrace_sock() {
-	return (FILE *) pthread_getspecific(sock_key);
-}
-
-/**
  * Convenience getter function for the thread ID
  */
 static inline pthread_t __darwintrace_tid() {
@@ -233,16 +161,6 @@
 /**
  * Convenience setter function for the thread-local darwintrace socket
  */
-static inline void __darwintrace_sock_set(FILE *stream) {
-	if (0 != (errno = pthread_setspecific(sock_key, stream))) {
-		perror("darwintrace: pthread_setspecific");
-		abort();
-	}
-}
-
-/**
- * Convenience setter function for the thread-local darwintrace socket
- */
 static inline void __darwintrace_tid_set() {
 	if (0 != (errno = pthread_setspecific(tid_key, (const void *) pthread_self()))) {
 		perror("darwintrace: pthread_setspecific");
@@ -260,7 +178,7 @@
 	char p;
 
 	/* '/' is the allow all wildcard */
-	if (str[0] == '\0' || (str[0] == '/' && str[1] == '\0')) {
+	if (prefix[0] == '\0' || (prefix[0] == '/' && prefix[1] == '\0')) {
 		return 1;
 	}
 
@@ -271,129 +189,7 @@
 	return (p == '\0' && (s == '/' || s == '\0'));
 }
 
-/**
- * Return false if str doesn't begin with prefix, true otherwise.
- */
-static inline bool __darwintrace_strbeginswith(const char *str, const char *prefix) {
-	char s;
-	char p;
-	do {
-		s = *str++;
-		p = *prefix++;
-	} while (p && (p == s));
-	return (p == '\0');
-}
-
 /*
- * Copy the environment variables, if they're defined. This is run as
- * a constructor at startup.
- */
-static void __darwintrace_copy_env() {
-#define COPYENV(name, variable) \
-	if (NULL != (val = getenv(#name))) {\
-		if (NULL == (variable = strdup(val))) {\
-			perror("darwintrace: strdup");\
-			abort();\
-		}\
-	} else {\
-		variable = NULL;\
-	}
-
-	char *val;
-	COPYENV(DYLD_INSERT_LIBRARIES,     __env_dyld_insert_libraries)
-	COPYENV(DYLD_FORCE_FLAT_NAMESPACE, __env_dyld_force_flat_namespace)
-	COPYENV(DARWINTRACE_LOG,           __env_darwintrace_log)
-#undef COPYENV
-}
-
-/**
- * Allocate a X=Y string where X is the variable name and Y its value.
- * Return the new string.
- *
- * If the value is NULL, return NULL.
- */
-static inline char *__darwintrace_alloc_env(const char *name, const char *val) {
-	char *result = NULL;
-
-	if (val) {
-		size_t size = strlen(name) + strlen(val) + 2;
-		if (NULL == (result = malloc(size))) {
-			perror("darwintrace: malloc");
-			abort();
-		}
-		snprintf(result, size, "%s=%s", name, val);
-		if (size > 0) {
-			result[size - 1] = '\0';
-		}
-	}
-
-	return result;
-}
-
-/**
- * This function checks that envp contains the global variables we had when the
- * library was loaded and modifies it if it doesn't.
- */
-static inline char *const *__darwintrace_restore_env(char *const envp[]) {
-	/* allocate the strings. */
-	/* we don't care about the leak here because we're going to call execve,
-	 * which, if it succeeds, will get rid of our heap */
-	char *dyld_insert_libraries_ptr     = __darwintrace_alloc_env("DYLD_INSERT_LIBRARIES",     __env_dyld_insert_libraries);
-	char *dyld_force_flat_namespace_ptr = __darwintrace_alloc_env("DYLD_FORCE_FLAT_NAMESPACE", __env_dyld_force_flat_namespace);
-	char *darwintrace_log_ptr           = __darwintrace_alloc_env("DARWINTRACE_LOG",           __env_darwintrace_log);
-
-	char *const *enviter = envp;
-	size_t envlen = 0;
-	char **copy;
-	char **copyiter;
-
-	while (*enviter != NULL) {
-		envlen++;
-		enviter++;
-	}
-
-	/* 4 is sufficient for the three variables we copy and the terminator */
-	copy = malloc(sizeof(char *) * (envlen + 4));
-
-	enviter  = envp;
-	copyiter = copy;
-
-	while (*enviter != NULL) {
-		char *val = *enviter;
-		if (__darwintrace_strbeginswith(val, "DYLD_INSERT_LIBRARIES=")) {
-			val = dyld_insert_libraries_ptr;
-			dyld_insert_libraries_ptr = NULL;
-		} else if (__darwintrace_strbeginswith(val, "DYLD_FORCE_FLAT_NAMESPACE=")) {
-			val = dyld_force_flat_namespace_ptr;
-			dyld_force_flat_namespace_ptr = NULL;
-		} else if (__darwintrace_strbeginswith(val, "DARWINTRACE_LOG=")) {
-			val = darwintrace_log_ptr;
-			darwintrace_log_ptr = NULL;
-		}
-
-		if (val) {
-			*copyiter++ = val;
-		}
-
-		enviter++;
-	}
-
-	if (dyld_insert_libraries_ptr) {
-		*copyiter++ = dyld_insert_libraries_ptr;
-	}
-	if (dyld_force_flat_namespace_ptr) {
-		*copyiter++ = dyld_force_flat_namespace_ptr;
-	}
-	if (darwintrace_log_ptr) {
-		*copyiter++ = darwintrace_log_ptr;
-	}
-
-	*copyiter = 0;
-
-	return copy;
-}
-
-/*
  * Data structures and functions to iterate over the filemap received from
  * tracelib code.
  */
@@ -425,16 +221,13 @@
  *
  * \param[out] command location for the command specified for this filemap
  *                     entry
- * \param[out] replacement location for a replacement path, if any. This field
- *                         is only valid if the command field indicates
- *                         a replacement path is being used.
  * \param[in]  it pointer to a \c filemap_iterator_t keeping the state of this
  *                iteration
  * \return string containing the path this filemap entry corresponds to, or \c
  *         NULL if the end of the filemap was reached
  */
-static inline char *__darwintrace_filemap_iter(char *command, char **replacement, filemap_iterator_t *it) {
-	enum { PATH, COMMAND, REPLACEPATH, DONE } state = PATH;
+static inline char *__darwintrace_filemap_iter(char *command, filemap_iterator_t *it) {
+	enum { PATH, COMMAND, DONE } state = PATH;
 	char *t;
 	char *path;
 
@@ -452,31 +245,24 @@
 	while (state != DONE) {
 		switch (state) {
 			case DONE:
-				fprintf(stderr, "darwintrace: illegal state in dfa in " __FILE__ ":%d\n", __LINE__);
-				abort();
+				/* unreachable */
 				break;
 			case PATH:
-				if (!*t) {
+				if (*t == '\0') {
 					state = COMMAND;
 				}
 				break;
 			case COMMAND:
 				*command = *t;
 				if (*t == 1) {
-					state = REPLACEPATH;
-					*replacement = t + 1;
-				} else {
-					state = DONE;
-					/* the byte after the status code is 0, if the status
-					 * code isn't 1 */
-					t++;
+					fprintf(stderr, "darwintrace: unsupported state REPLACEPATH in dfa in " __FILE__ ":%d\n", __LINE__);
+					abort();
 				}
+				state = DONE;
+				/* the byte after the status code is '\0', if the status code
+				 * isn't 1 (which is no longer supported) */
+				t++;
 				break;
-			case REPLACEPATH:
-				if (!*t) {
-					state = DONE;
-				}
-				break;
 		}
 		t++;
 	}
@@ -493,11 +279,23 @@
 	char *newfilemap;
 #if DARWINTRACE_DEBUG && 0
 	filemap_iterator_t it;
-	char *path, *replacement, command;
+	char *path, command;
 #endif
 
-#if __GNUC__ && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
-#error Please build with gcc-4.2 or later
+#if defined(HAVE_OSATOMICCOMPAREANDSWAPPTR)
+#	define CAS(old, new, mem) OSAtomicCompareAndSwapPtr(old, new, (void * volatile *) (mem))
+#elif defined(__LP64__)
+#	ifdef HAVE_OSATOMICCOMPAREANDSWAP64
+#		define CAS(old, new, mem) OSAtomicCompareAndSwap64((int64_t) (old), (int64_t) (new), (volatile int64_t *) (mem))
+#	else
+#		error "No 64-bit compare and swap primitive available on 64-bit OS."
+#	endif
+#else
+#	ifdef HAVE_OSATOMICCOMPAREANDSWAP32
+#		define CAS(old, new, mem) OSAtomicCompareAndSwap32((int32_t) (old), (int32_t) (new), (volatile int32_t *) (mem))
+#	else
+#		error "No 32-bit compare and swap primitive available."
+#	endif
 #endif
 
 	/*
@@ -514,12 +312,12 @@
 		if (filemap != NULL)
 			break;
 		newfilemap = __send("filemap\t", (uint32_t) strlen("filemap\t"), 1);
-	} while (!__sync_bool_compare_and_swap(&filemap, NULL, newfilemap));
+	} while (!CAS(NULL, newfilemap, &filemap));
 
 #if DARWINTRACE_DEBUG && 0
 	for (__darwintrace_filemap_iterator_init(&it);
-	        (path = __darwintrace_filemap_iter(&command, &replacement, &it));) {
-		debug_printf("filemap: {cmd=%d, path=%-120s, replacement=%s}\n", command, path, (command == 1) ? replacement : "-");
+	        (path = __darwintrace_filemap_iter(&command, &it));) {
+		debug_printf("filemap: {cmd=%d, path=%s}\n", command, path);
 	}
 #endif
 }
@@ -530,7 +328,7 @@
  * library and this library prevents closing the socket to MacPorts, we use \c
  * __darwintrace_close_sock to allow closing specific FDs.
  */
-static inline void __darwintrace_close() {
+void __darwintrace_close() {
 	FILE *dtsock = __darwintrace_sock();
 	if (dtsock) {
 		__darwintrace_close_sock = fileno(dtsock);
@@ -546,7 +344,7 @@
  * called after \c fork(2), i.e. when the current PID doesn't match the one
  * stored when the function was called last.
  */
-static inline void __darwintrace_setup() {
+void __darwintrace_setup() {
 	/*
 	 * Check whether this is a child process and we've inherited the socket. We
 	 * want to avoid race conditions with our parent process when communicating
@@ -629,17 +427,30 @@
 	const char *realpath;
 
 	do {
-#		if 0
-#       ifdef __APPLE__ /* Only Darwin has volfs and F_GETPATH */
-		/* TODO Use getattrlist(2) ATTR_CMN_NAME to get this */
-		if ((fd > 0) && (strncmp(path, "/.vol/", 6) == 0)) {
-			if (fcntl(fd, F_GETPATH, pathbuf) != -1) {
+		if (false && strncmp(path, "/.vol/", 6) == 0) {
+			// path in VOLFS, try to get inode -> name lookup from
+			// getattrlist(2).
+			struct attrlist attrlist;
+			attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
+			attrlist.reserved = 0;
+			attrlist.commonattr = ATTR_CMN_FULLPATH;
+			attrlist.volattr = 0;
+			attrlist.dirattr = 0;
+			attrlist.fileattr = 0;
+			attrlist.forkattr = 0;
+
+			char attrbuf[sizeof(uint32_t) + sizeof(attrreference_t) + (PATH_MAX)];
+			/*           attrlength         attrref_t for the name     UTF-8 name up to PATH_MAX chars */
+			if (-1 == (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))) {
+				perror("darwintrace: getattrlist");
+				// ignore and just print the /.vol/ path
+			} else {
+				attrreference_t *nameAttrRef = (attrreference_t *) (attrbuf + sizeof(uint32_t));
+				strlcpy(pathbuf, ((char *) nameAttrRef) + nameAttrRef->attr_dataoffset, sizeof(pathbuf));
 				realpath = pathbuf;
 				break;
 			}
 		}
-#       endif
-#		endif
 
 		if (*path != '/') {
 			if (!getcwd(pathbuf, sizeof(pathbuf))) {
@@ -672,14 +483,14 @@
  * \return 1, if access should be granted, 0, if access should be denied, and
  *         -1 if MacPorts doesn't know about the file.
  */
-static int dependency_check(char *path) {
-#define stat(y, z) syscall(SYS_stat, (y), (z))
+static int dependency_check(const char *path) {
+#define lstat(y, z) syscall(LSTATSYSNUM, (y), (z))
 	char buffer[BUFFER_SIZE], *p;
 	uint32_t len;
 	int result = 0;
 	struct stat st;
 
-	if (-1 == stat(path, &st)) {
+	if (-1 == lstat(path, &st)) {
 		return 1;
 	}
 	if (S_ISDIR(st.st_mode)) {
@@ -717,7 +528,7 @@
 
 	free(p);
 	return result;
-#undef stat
+#undef lstat
 }
 
 /**
@@ -794,128 +605,67 @@
 }
 
 /**
- * Check a path against the current sandbox
+ * Check a fully normalized path against the current sandbox. Helper function
+ * for __darwintrace_is_in_sandbox; do not use directly.
  *
- * \param[in] path the path to be checked; not necessarily absolute
- * \param[out] newpath buffer for a replacement path when redirection should
- *                     occur. Initialize the first byte with 0 before calling
- *                     this function. The buffer should be at least MAXPATHLEN
- *                     bytes large. If newpath[0] isn't 0 after the call,
- *                     redirection should occur and the path from newpath
- *                     should be used for the syscall instead.
- * \param[in] report If access to this path is being denied, report it as
- *                   sandbox violation. Set this to \c true for all operations
- *                   that read file contents. Set this to \c false for
- *                   operations that only check for the file's existance, e.g.,
- *                   reading a directory.
- * \return 1, if the file is within sandbox bounds, 0, if access should be denied
+ * \param[in] path the path to be checked; must be absolute and normalized.
+ * \param[in] flags A binary or combination of the following flags:
+ *                  - DT_REPORT: If access to this path is being denied, report
+ *                    it as sandbox violation. Set this for all operations that
+ *                    read file contents or check file attributes. Omit this
+ *                    flag for operations that might only attempt to access
+ *                    a file by chance, such as readdir(3).
+ *                  - DT_ALLOWDIR: Whether to always allow access if the given
+ *                    path references an existing directory. Set this for
+ *                    read operations such as stat(2), omit this for operations
+ *                    that modify directories like rmdir(2) and mkdir(2).
+ * \return \c true if the file is within sandbox bounds, \c false if access
+ *         should be denied
  */
-static inline bool __darwintrace_is_in_sandbox(const char *path, char *newpath, bool report) {
-	char *t, *_;
-	char *strpos, *normpos;
-	char lpath[MAXPATHLEN];
-	char normalizedpath[MAXPATHLEN];
+static inline bool __darwintrace_sandbox_check(const char *path, int flags) {
+#define lstat(x,y) syscall(LSTATSYSNUM, (x), (y))
 	filemap_iterator_t filemap_it;
+
 	char command;
-	char *replacementpath;
+	char *t;
 
-	__darwintrace_setup();
-
-	if (!filemap) {
+	if (path[0] == '/' && path[1] == '\0') {
+		// Always allow access to /. Strange things start to happen if you deny this.
 		return true;
 	}
 
-	/* Make sure the path is absolute. */
-	if (*path == '/') {
-		strcpy(lpath, path);
-	} else {
-		if (getcwd(lpath, MAXPATHLEN - 1) == NULL) {
-			perror("darwintrace: getcwd");
-			abort();
+	if ((flags & DT_ALLOWDIR) > 0) {
+		struct stat st;
+		if (-1 != lstat(path, &st) && S_ISDIR(st.st_mode)) {
+			return true;
 		}
-		strlcat(lpath, "/", MAXPATHLEN);
-		strlcat(lpath, path, MAXPATHLEN);
 	}
 
-	/* Make sure the path is normalized. NOTE: Do _not_ use realpath(3) here.
-	 * Doing so _will_ lead to problems. This is essentially a very simple
-	 * re-implementation of realpath(3). */
-	normalizedpath[0] = '\0';
-	strpos = lpath + 1;
-	normpos = normalizedpath;
-	for (;;) {
-		char *curpos = strsep(&strpos, "/");
-		if (curpos == NULL) {
-			/* reached the end of the path */
-			break;
-		} else if (*curpos == '\0') {
-			/* empty entry, ignore */
-			continue;
-		} else if (curpos[0] == '.' && curpos[1] == '\0') {
-			/* no-op directory, ignore */
-			continue;
-		} else if (curpos[0] == '.' && curpos[1] == '.' && curpos[2] == '\0') {
-			/* walk up one directory */
-			char *lastSep = strrchr(normalizedpath, '/');
-			if (lastSep == NULL) {
-				/* path is completely empty */
-				normpos = normalizedpath;
-				*normpos = '\0';
-				continue;
-			}
-			/* remove last component by overwriting the slash with \0, update normpos */
-			*lastSep = '\0';
-			normpos = lastSep;
-			continue;
-		}
-		/* default case: standard path, copy */
-		*normpos++ = '/';
-		strcpy(normpos, curpos);
-	}
-	if (*normalizedpath == '\0') {
-		normalizedpath[0] = '/';
-		normalizedpath[1] = '\0';
-	}
-
-	/* Iterate over the sandbox bounds and try to find a directive matching this path */
+	// Iterate over the sandbox bounds and try to find a directive matching this path
 	for (__darwintrace_filemap_iterator_init(&filemap_it);
-	        (t = __darwintrace_filemap_iter(&command, &replacementpath, &filemap_it));) {
-		if (__darwintrace_pathbeginswith(normalizedpath, t)) {
-			/* move t to the integer describing how to handle this match */
-			t += strlen(t) + 1;
-			switch (*t) {
+	        (t = __darwintrace_filemap_iter(&command, &filemap_it));) {
+		if (__darwintrace_pathbeginswith(path, t)) {
+			switch (command) {
 				case FILEMAP_ALLOW:
 					return true;
-				case FILEMAP_REDIR:
-					if (!newpath) {
-						return false;
-					}
-					/* the redirected path starts right after the byte telling
-					 * us we should redirect */
-					strcpy(newpath, t + 1);
-					_ = newpath + strlen(newpath);
-					/* append '/' if it's missing */
-					if (_[-1] != '/') {
-						*_++ = '/';
-					}
-					strcpy(_, normalizedpath);
-					return true;
 				case FILEMAP_ASK:
-					/* ask the socket whether this file is OK */
-					switch (dependency_check(normalizedpath)) {
+					// ask the socket whether this file is OK
+					switch (dependency_check(path)) {
 						case 1:
 							return true;
 						case -1:
-							/* if the file isn't known to MacPorts, allow
-							 * access anyway, but report a sandbox violation.
-							 * TODO find a better solution */
-							if (report)
-								__darwintrace_log_op("sandbox_violation", normalizedpath);
+							// if the file isn't known to MacPorts, allow
+							// access anyway, but report a sandbox violation.
+							// TODO find a better solution
+							if ((flags & DT_REPORT) > 0) {
+								__darwintrace_log_op("sandbox_violation", path);
+							}
 							return true;
 						case 0:
-							/* file belongs to a foreign port, deny access */
-							if (report)
-								__darwintrace_log_op("sandbox_violation", normalizedpath);
+							// file belongs to a foreign port, deny access
+							if ((flags & DT_REPORT) > 0) {
+								__darwintrace_log_op("sandbox_violation", path);
+							}
 							return false;
 					}
 				default:
@@ -925,547 +675,161 @@
 		}
 	}
 
-	if (report)
-		__darwintrace_log_op("sandbox_violation", normalizedpath);
+	if ((flags & DT_REPORT) > 0) {
+		__darwintrace_log_op("sandbox_violation", path);
+	}
 	return false;
+#undef lstat
 }
 
-/* wrapper for open(2) preventing opening files outside the sandbox */
-int open(const char *path, int flags, ...) {
-#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
-	mode_t mode;
-	va_list args;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("open(%s)\n", path);
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		debug_printf("open %s was forbidden\n", path);
-		errno = ((flags & O_CREAT) > 0) ? EACCES : ENOENT;
-		return -1;
+/**
+ * Check a path against the current sandbox
+ *
+ * \param[in] path the path to be checked; not necessarily absolute
+ * \param[in] flags A binary or combination of the following flags:
+ *                  - DT_REPORT: If access to this path is being denied, report
+ *                    it as sandbox violation. Set this for all operations that
+ *                    read file contents or check file attributes. Omit this
+ *                    flag for operations that might only attempt to access
+ *                    a file by chance, such as readdir(3).
+ *                  - DT_ALLOWDIR: Whether to always allow access if the given
+ *                    path references an existing directory. Set this for
+ *                    read operations such as stat(2), omit this for operations
+ *                    that modify directories like rmdir(2) and mkdir(2).
+ * \return \c true if the file is within sandbox bounds, \c false if access
+ *         should be denied
+ */
+bool __darwintrace_is_in_sandbox(const char *path, int flags) {
+#define lstat(x, y) syscall(LSTATSYSNUM, (x), (y))
+#define readlink(x,y,z) syscall(SYS_readlink, (x), (y), (z))
+	if (!filemap) {
+		return true;
 	}
 
-	if (*newpath) {
-		path = newpath;
-	}
+	char *pathComponents[MAXPATHLEN / 2 + 2];
+	size_t componentIdx = 0;
 
-	/* Why mode here ? */
-	va_start(args, flags);
-	mode = va_arg(args, int);
-	va_end(args);
-
-	return open(path, flags, mode);
-#undef open
-}
-
-/* Log calls to readlink(2) into the file specified by DARWINTRACE_LOG.
-   Only logs if the DARWINTRACE_LOG environment variable is set.
-   Only logs files where the readlink succeeds.
-*/
-#ifdef READLINK_IS_NOT_P1003_1A
-int readlink(const char *path, char *buf, int bufsiz) {
-#else
-ssize_t readlink(const char *path, char *buf, size_t bufsiz) {
-#endif
-#define readlink(x,y,z) syscall(SYS_readlink, (x), (y), (z))
-	char newpath[MAXPATHLEN];
-
-	debug_printf("readlink(%s)\n", path);
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
+	// Make sure the path is absolute.
+	char cwd[MAXPATHLEN];
+	if (path == NULL) {
+		// this is most certainly invalid, let the syscall deal with it
+		return true;
 	}
+	if (*path != '/') {
+		// The path isn't absolute, start by populating pathcomponents with the
+		// current working directory
+		if (getcwd(cwd, sizeof(cwd)) == NULL) {
+			perror("darwintrace: getcwd");
+			abort();
+		}
 
-	if (*newpath) {
-		path = newpath;
+		char *lastToken = cwd + 1;
+		char *token = NULL;
+		while (NULL != (token = strsep(&lastToken, "/"))) {
+			pathComponents[componentIdx++] = token;
+		}
 	}
 
-	return readlink(path, buf, bufsiz);
-#undef readlink
-}
+	// Copy path to a writable buffer
+	char lpath[strlen(path) + 1];
+	strcpy(lpath, path);
 
-int execve(const char *path, char *const argv[], char *const envp[]) {
-#define execve(x,y,z) syscall(SYS_execve, (x), (y), (z))
-#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
-#define close(x) syscall(SYS_close, (x))
-#define lstat(x, y) syscall(SYS_lstat, (x), (y))
-	debug_printf("execve(%s)\n", path);
-	__darwintrace_setup();
-	struct stat sb;
-	/* for symlinks, we want to capture both the original path and the modified
-	 * one, since for $prefix/bin/gcc -> mp-gcc-4.8, both "gcc_select" and
-	 * "gcc48" are contributors. This requires changes to the select code such
-	 * that the symlinks are registered to the *_select ports. Since this
-	 * a general problem (when executing $prefix/libexec/mysql/bin/foo where
-	 * $prefix/libexec/mysql is a symlink to $prefix/libexec/mysql55, the
-	 * mysql_select port needs to be a contributor!) we should really implement
-	 * this in __darwintrace_is_in_sandbox().
-	 */
-	if (lstat(path, &sb) == 0) {
-		if (!__darwintrace_is_in_sandbox(path, NULL, true)) {
-			errno = ENOENT;
-			return -1;
-		}
-
-		int fd = open(path, O_RDONLY, 0);
-		if (fd > 0) {
-			char buffer[MAXPATHLEN + 1];
-			ssize_t bytes_read;
-
-			/* Read the file for the interpreter. Fortunately, on OS X:
-			 *   The system guarantees to read the number of bytes requested if
-			 *   the descriptor references a normal file that has that many
-			 *   bytes left before the end-of-file, but in no other case.
-			 * That _does_ save us another ugly loop to get things right. */
-			bytes_read = read(fd, buffer, MAXPATHLEN);
-			buffer[bytes_read] = '\0';
-			const char *buffer_end = buffer + bytes_read;
-			if (bytes_read > 2 && buffer[0] == '#' && buffer[1] == '!') {
-				char *interp = buffer + 2;
-
-				/* skip past leading whitespace */
-				while (interp < buffer_end && isblank(*interp)) {
-					++interp;
-				}
-				/* found interpreter (or ran out of data); skip until next
-				 * whitespace, then terminate the string */
-				if (interp < buffer_end) {
-					char *interp_end = interp;
-					strsep(&interp_end, " \t");
-				}
-
-				/* check the iterpreter against the sandbox */
-				if (!__darwintrace_is_in_sandbox(interp, NULL, true)) {
-					close(fd);
-					errno = ENOENT;
-					return -1;
-				}
+	/* Make sure the path is normalized. NOTE: Do _not_ use realpath(3) here.
+	 * Doing so _will_ lead to problems. This is essentially a very simple
+	 * re-implementation of realpath(3). */
+	char *lastToken = lpath;
+	char *token = NULL;
+	while (NULL != (token = strsep(&lastToken, "/"))) {
+		if (token[0] == '\0') {
+			// empty entry, ignore
+		} else if (token[0] == '.' && token[1] == '\0') {
+			// reference to current directory, ignore
+		} else if (token[0] == '.' && token[1] == '.' && token[2] == '\0') {
+			// walk up one directory, but not if it's the last one, because /.. -> /
+			if (componentIdx > 0) {
+				componentIdx--;
 			}
-
-			close(fd);
-
+		} else {
+			// default case: standard path
+			pathComponents[componentIdx++] = token;
 		}
 	}
 
-	/* our variables won't survive exec, clean up */
-	__darwintrace_close();
-	__darwintrace_pid = (pid_t) - 1;
+	char link[MAXPATHLEN];
+	char normPath[MAXPATHLEN];
+	bool pathIsSymlink;
+	size_t loopCount = 0;
+	do {
+		pathIsSymlink = false;
 
-	/* call the original execve function, but fix the environment if required. */
-	return execve(path, argv, __darwintrace_restore_env(envp));
-#undef lstat
-#undef close
-#undef open
-#undef execve
-}
-
-/* if darwintrace has been initialized, trap attempts to close our file
- * descriptor */
-int close(int fd) {
-#define close(x) syscall(SYS_close, (x))
-	FILE *stream = __darwintrace_sock();
-	if (stream) {
-		int dtsock = fileno(stream);
-		if (fd == dtsock && dtsock != __darwintrace_close_sock) {
-			errno = EBADF;
-			return -1;
+		if (++loopCount >= 10) {
+			// assume cylce and let the OS deal with that (yes, this actually
+			// happens in software!)
+			break;
 		}
-	}
 
-	return close(fd);
-#undef close
-}
+		char *normPathPos = normPath;
+		*normPathPos = '\0';
 
-/* if darwintrace has been initialized, trap attempts to dup2 over our file descriptor */
-int dup2(int filedes, int filedes2) {
-#define dup2(x, y) syscall(SYS_dup2, (x), (y))
-	FILE *stream = __darwintrace_sock();
-
-	debug_printf("dup2(%d, %d)\n", filedes, filedes2);
-	if (stream && filedes2 == fileno(stream)) {
-		/* if somebody tries to close our file descriptor, just move it out of
-		 * the way. Make sure it doesn't end up as stdin/stdout/stderr, though!
-		 * */
-		int new_darwintrace_fd;
-		FILE *new_stream;
-
-		if (-1 == (new_darwintrace_fd = fcntl(fileno(stream), F_DUPFD, STDOUT_FILENO + 1))) {
-			/* if duplicating fails, do not allow overwriting either! */
-			return -1;
+		// Build a canonical representation of the path
+		for (size_t i = 0; i < componentIdx; ++i) {
+			*normPathPos++ = '/';
+			normPathPos = stpcpy(normPathPos, pathComponents[i]);
 		}
-
-		debug_printf("moving __darwintrace FD from %d to %d\n", fileno(stream), new_darwintrace_fd);
-		__darwintrace_close();
-		if (NULL == (new_stream = fdopen(new_darwintrace_fd, "a+"))) {
-			perror("darwintrace: fdopen");
-			abort();
+		if (componentIdx == 0) {
+			// path is "/"
+			*normPathPos++ = '/';
+			*normPathPos = '\0';
 		}
-		__darwintrace_sock_set(new_stream);
-	}
 
-	return dup2(filedes, filedes2);
-#undef dup2
-}
-
-/* Trap attempts to unlink a file outside the sandbox. */
-int unlink(const char *path) {
-#define __unlink(x) syscall(SYS_unlink, (x))
-	char newpath[MAXPATHLEN];
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		debug_printf("unlink %s was forbidden\n", path);
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		path = newpath;
-	}
-
-	debug_printf("unlink %s was allowed\n", path);
-
-	return __unlink(path);
-}
-
-/* Trap attempts to create directories outside the sandbox.
- */
-int mkdir(const char *path, mode_t mode) {
-#define __mkdir(x,y) syscall(SYS_mkdir, (x), (y))
-	char newpath[MAXPATHLEN];
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
+		// Check whether the last component is a symlink; if it is, check
+		// whether it is in the sandbox, expand it and do the same thing again.
 		struct stat st;
-		if (-1 == lstat(path, &st)) {
-			if (errno == ENOENT) {
-				/* directory doesn't exist yet */
-				debug_printf("mkdir was forbidden at %s\n", path);
-				errno = EACCES;
-				return -1;
+		if (lstat(normPath, &st) != -1 && S_ISLNK(st.st_mode)) {
+			if (!__darwintrace_sandbox_check(normPath, flags)) {
+				return false;
 			}
-		}
-		/* otherwise, mkdir will do nothing or fail with a hopefully meaningful
-		 * error */
-	} else {
-		if (*newpath) {
-			path = newpath;
-		}
 
-		debug_printf("mkdir was allowed at %s\n", path);
-	}
+			pathIsSymlink = true;
 
-	return __mkdir(path, mode);
-}
+			ssize_t linksize;
+			if (-1 == (linksize = readlink(normPath, link, sizeof(link)))) {
+				perror("darwintrace: readlink");
+				abort();
+			}
+			link[linksize] = '\0';
 
-/* Trap attempts to remove directories outside the sandbox.
- */
-int rmdir(const char *path) {
-#define __rmdir(x) syscall(SYS_rmdir, (x))
-	if (!__darwintrace_is_in_sandbox(path, NULL, true)) {
-		debug_printf("removing directory %s was forbidden\n", path);
-		errno = ENOENT;
-		return -1;
-	}
+			if (*link == '/') {
+				// symlink is absolute, start fresh
+				componentIdx = 0;
+			} else {
+				// symlink is relative, remove last component
+				if (componentIdx > 0) {
+					componentIdx--;
+				}
+			}
 
-	debug_printf("rmdir %s was allowed\n", path);
-
-	return __rmdir(path);
-}
-
-/* Trap attempts to rename files/directories outside the sandbox.
- */
-int rename(const char *from, const char *to) {
-#define __rename(x,y) syscall(SYS_rename, (x), (y))
-	if (!__darwintrace_is_in_sandbox(from, NULL, true)) {
-		/* outside sandbox, forbid */
-		debug_printf("renaming from %s was forbidden\n", from);
-		errno = ENOENT;
-		return -1;
-	}
-	if (!__darwintrace_is_in_sandbox(to, NULL, true)) {
-		debug_printf("renaming to %s was forbidden\n", to);
-		errno = EACCES;
-		return -1;
-	}
-
-	debug_printf("renaming from %s to %s was allowed\n", from, to);
-
-	return __rename(from, to);
-}
-
-int stat(const char *path, struct stat *sb) {
-#define stat(path, sb) syscall(SYS_stat, path, sb)
-	int result = 0;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("stat(%s)\n", path);
-	if (-1 == (result = stat(path, sb))) {
-		return -1;
-	}
-
-	if (S_ISDIR(sb->st_mode)) {
-		return result;
-	}
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		result = stat(newpath, sb);
-	}
-
-	return result;
-#undef stat
-}
-
-#if defined(__DARWIN_64_BIT_INO_T) && !defined(_DARWIN_FEATURE_ONLY_64_BIT_INODE)
-
-int stat64(const char *path, struct stat64 *sb) {
-#define stat64(path, sb) syscall(SYS_stat64, path, sb)
-	int result = 0;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("stat64(%s)\n", path);
-	if (-1 == (result = stat64(path, sb))) {
-		return -1;
-	}
-
-	if (S_ISDIR(sb->st_mode)) {
-		return result;
-	}
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		result = stat64(newpath, sb);
-	}
-
-	return result;
-#undef stat64
-}
-
-int stat$INODE64(const char *path, struct stat64 *sb) {
-	return stat64(path, sb);
-}
-
-#endif /* defined(__DARWIN_64_BIT_INO_T) && !defined(_DARWIN_FEATURE_ONLY_64_BIT_INODE) */
-
-
-int lstat(const char *path, struct stat *sb) {
-#define lstat(path, sb) syscall(SYS_lstat, path, sb)
-	int result = 0;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("lstat(%s)\n", path);
-	if (-1 == (result = lstat(path, sb))) {
-		return -1;
-	}
-
-	if (S_ISDIR(sb->st_mode)) {
-		return result;
-	}
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		result = lstat(newpath, sb);
-	}
-
-	return result;
-#undef lstat
-}
-
-#if defined(__DARWIN_64_BIT_INO_T) && !defined(_DARWIN_FEATURE_ONLY_64_BIT_INODE)
-
-int lstat64(const char *path, struct stat64 *sb) {
-#define lstat64(path, sb) syscall(SYS_lstat64, path, sb)
-	int result = 0;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("lstat64(%s)\n", path);
-	if (-1 == (result = lstat64(path, sb))) {
-		return -1;
-	}
-
-	if (S_ISDIR(sb->st_mode)) {
-		return result;
-	}
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		result = lstat64(newpath, sb);
-	}
-
-	return result;
-#undef lstat64
-}
-
-int lstat$INODE64(const char *path, struct stat64 *sb) {
-	return lstat64(path, sb);
-}
-
-#endif /* defined(__DARWIN_64_BIT_INO_T) && !defined(_DARWIN_FEATURE_ONLY_64_BIT_INODE) */
-
-/**
- * re-implementation of getdirent(2) and __getdirent64(2) preventing paths
- * outside the sandbox to show up when reading the contents of a directory.
- * Unfortunately, since we need to access the contents of the buffer, but the
- * contents differ by architecture, we can not rely on the dirent structure
- * defined by the header included by this program, because we don't know
- * whether darwintrace.dylib has been compiled for 64bit or 32bit inodes. We
- * thus copy both structs and decide at runtime.
- */
-
-#ifdef __APPLE__
-/* only do this on mac, because fcntl(fd, F_GETPATH) might not be available on
- * other systems, and because other system's syscall names are probably
- * different anyway */
-
-#if defined(__DARWIN_64_BIT_INO_T)
-
-struct dirent64  {
-	__uint64_t  d_ino;      /* file number of entry */
-	__uint64_t  d_seekoff;  /* seek offset */
-	__uint16_t  d_reclen;   /* length of this record */
-	__uint16_t  d_namlen;   /* length of string in d_name */
-	__uint8_t   d_type;     /* file type */
-	char      d_name[__DARWIN_MAXPATHLEN]; /* entry name (up to MAXPATHLEN bytes) */
-};
-
-size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep) {
-#define __getdirentries64(w,x,y,z) syscall(SYS_getdirentries64, (w), (x), (y), (z))
-	size_t sz = __getdirentries64(fd, buf, bufsize, basep);
-	char dirname[MAXPATHLEN];
-	size_t dnamelen;
-
-	if (-1 == fcntl(fd, F_GETPATH, dirname)) {
-		errno = EBADF;
-		return -1;
-	}
-
-	dnamelen = strlen(dirname);
-	if (dirname[dnamelen - 1] != '/') {
-		dirname[dnamelen] = '/';
-		dirname[dnamelen + 1] = '\0';
-		dnamelen++;
-	}
-
-	dnamelen = strlen(dirname);
-	size_t offset;
-	for (offset = 0; offset < sz;) {
-		struct dirent64 *dent = (struct dirent64 *)(((char *) buf) + offset);
-		dirname[dnamelen] = '\0';
-		strcat(dirname, dent->d_name);
-		if (!__darwintrace_is_in_sandbox(dirname, NULL, false)) {
-			debug_printf("__getdirentries64: filtered %s\n", dirname);
-			dent->d_ino = 0;
-		} else {
-			debug_printf("__getdirentries64:  allowed %s\n", dirname);
+			lastToken = link;
+			token = NULL;
+			while (NULL != (token = strsep(&lastToken, "/"))) {
+				if (token[0] == '\0') {
+					// empty entry, ignore
+				} else if (token[0] == '.' && token[1] == '\0') {
+					// reference to current directory, ignore
+				} else if (token[0] == '.' && token[1] == '.' && token[2] == '\0') {
+					// walk up one directory, but not if it's the last one, because /.. -> /
+					if (componentIdx > 0) {
+						componentIdx--;
+					}
+				} else {
+					// default case: standard path
+					pathComponents[componentIdx++] = token;
+				}
+			}
 		}
-		offset += dent->d_reclen;
-	}
+	} while (pathIsSymlink);
 
-	return sz;
-#undef __getdirentries64
-}
-
-#endif /* defined(__DARWIN_64_BIT_INO_T) */
-
-#pragma pack(4)
-struct dirent32 {
-	ino_t d_ino;            /* file number of entry */
-	__uint16_t d_reclen;    /* length of this record */
-	__uint8_t  d_type;      /* file type */
-	__uint8_t  d_namlen;    /* length of string in d_name */
-	char d_name[__DARWIN_MAXNAMLEN + 1]; /* name must be no longer than this */
-};
-#pragma pack()
-
-int getdirentries(int fd, char *buf, int nbytes, long *basep) {
-#define getdirentries(w,x,y,z) syscall(SYS_getdirentries, (w), (x), (y), (z))
-	size_t sz = getdirentries(fd, buf, nbytes, basep);
-	char dirname[MAXPATHLEN];
-	size_t dnamelen;
-
-	if (-1 == fcntl(fd, F_GETPATH, dirname)) {
-		errno = EBADF;
-		return 0;
-	}
-
-	dnamelen = strlen(dirname);
-	if (dirname[dnamelen - 1] != '/') {
-		dirname[dnamelen] = '/';
-		dirname[dnamelen + 1] = '\0';
-		dnamelen++;
-	}
-
-	size_t offset;
-	for (offset = 0; offset < sz;) {
-		struct dirent32 *dent = (struct dirent32 *)(buf + offset);
-		dirname[dnamelen] = '\0';
-		strcat(dirname, dent->d_name);
-		if (!__darwintrace_is_in_sandbox(dirname, NULL, false)) {
-			debug_printf("getdirentries: filtered %s\n", dirname);
-			dent->d_ino = 0;
-		} else {
-			debug_printf("getdirentries:  allowed %s\n", dirname);
-		}
-		offset += dent->d_reclen;
-	}
-
-	return sz;
-#undef getdirentries
-}
-
-int access(const char *path, int amode) {
-#define access(x, y) syscall(SYS_access, (x), (y))
-#define lstat(path, sb) syscall(SYS_lstat, path, sb)
-	struct stat st;
-	char newpath[MAXPATHLEN];
-
-	debug_printf("access(%s, %d)\n", path, amode);
-
-	if (-1 == lstat(path, &st)) {
-		return -1;
-	}
-
-	if (S_ISDIR(st.st_mode)) {
-		return access(path, amode);
-	}
-
-	*newpath = '\0';
-	if (!__darwintrace_is_in_sandbox(path, newpath, true)) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	if (*newpath) {
-		return access(newpath, amode);
-	}
-
-	return access(path, amode);
+	return __darwintrace_sandbox_check(normPath, flags);
+#undef readlink
 #undef lstat
-#undef access
 }
-
-#endif /* __APPLE__ */

Added: trunk/base/src/darwintracelib1.0/darwintrace.h
===================================================================
--- trunk/base/src/darwintracelib1.0/darwintrace.h	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/darwintrace.h	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id$
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+/**
+ * DARWINTRACE_DEBUG: verbose output of operations to debug darwintrace
+ */
+#ifndef DARWINTRACE_DEBUG
+#define DARWINTRACE_DEBUG (0)
+#endif
+
+/**
+ * \c debug_printf() is a macro that will print a message prefixed with
+ * "darwintrace" and the calling process' PID to stderr, or to the file
+ * indicated by the environment variable \c DARWINTRACE_DEBUG, if set.
+ */
+#if DARWINTRACE_DEBUG
+#	define debug_printf(format, ...) \
+		if (__darwintrace_stderr != NULL) { \
+			fprintf(__darwintrace_stderr, "darwintrace[%d]: " format, getpid(), __VA_ARGS__); \
+			fflush(__darwintrace_stderr); \
+		}
+#else
+#   define debug_printf(...)
+#endif
+
+enum {
+	DT_REPORT   = 1 << 0,
+	DT_ALLOWDIR = 1 << 1
+};
+
+/**
+ * Debug socket. Will be set by a constructor function in darwintrace.c.
+ */
+extern FILE *__darwintrace_stderr;
+
+/**
+ * Initializer function, ensures darwintrace has been properly set up and check
+ * whether this process was fork(2)'d or clone(2)'d since the last call. Call
+ * this before calling any other functions from this library.
+ */
+void __darwintrace_setup();
+
+/**
+ * Close the darwintrace socket and set it to \c NULL. Since this uses \c
+ * fclose(3), which internally calls \c close(2), which is intercepted by this
+ * library and this library prevents closing the socket to MacPorts, we use \c
+ * __darwintrace_close_sock to allow closing specific FDs.
+ */
+void __darwintrace_close();
+
+/**
+ * Check a path against the current sandbox
+ *
+ * \param[in] path the path to be checked; not necessarily absolute
+ * \param[in] flags A binary or combination of the following flags:
+ *                  - DT_REPORT: If access to this path is being denied, report
+ *                    it as sandbox violation. Set this for all operations that
+ *                    read file contents or check file attributes. Omit this
+ *                    flag for operations that might only attempt to access
+ *                    a file by chance, such as readdir(3).
+ *                  - DT_ALLOWDIR: Whether to always allow access if the given
+ *                    path references an existing directory. Set this for
+ *                    read operations such as stat(2), omit this for operations
+ *                    that modify directories like rmdir(2) and mkdir(2).
+ * \return \c true if the file is within sandbox bounds, \c false if access
+ *         should be denied
+ */
+bool __darwintrace_is_in_sandbox(const char *path, int flags);
+
+#ifdef DARWINTRACE_USE_PRIVATE_API
+#include <errno.h>
+#include <stdlib.h>
+
+/**
+ * PID of the process darwintrace was last used in. This is used to detect
+ * forking and opening a new connection to the control socket in the child
+ * process. Not doing so would potentially cause two processes writing to the
+ * same socket.
+ */
+extern pid_t __darwintrace_pid;
+
+/**
+ * Copy of the DARWINTRACE_LOG environment variable to restore it in execve(2).
+ * Contains the path to the unix socket used for communication with the
+ * MacPorts-side of the sandbox.
+ */
+extern char *__env_darwintrace_log;
+
+/**
+ * Helper variable containing the number of the darwintrace socket, iff the
+ * close(2) syscall should be allowed to close it. Used by \c
+ * __darwintrace_close.
+ */
+extern volatile int __darwintrace_close_sock;
+
+/**
+ * pthread_key_t for the darwintrace socket to ensure the socket is only used
+ * from a single thread.
+ */
+extern pthread_key_t sock_key;
+
+/**
+ * Convenience getter function for the thread-local darwintrace socket. Do not
+ * consider this part of public API. It is only needed to prevent closing and
+ * duplicating over darwintrace's socket FDs.
+ */
+static inline FILE *__darwintrace_sock() {
+	return (FILE *) pthread_getspecific(sock_key);
+}
+
+/**
+ * Convenience setter function for the thread-local darwintrace socket. Do not
+ * consider this part of public API. It is only needed to prevent closing and
+ * duplicating over darwintrace's socket FDs.
+ */
+static inline void __darwintrace_sock_set(FILE *stream) {
+	if (0 != (errno = pthread_setspecific(sock_key, stream))) {
+		perror("darwintrace: pthread_setspecific");
+		abort();
+	}
+}
+#endif /* defined(DARWINTRACE_USE_PRIVATE_API) */


Property changes on: trunk/base/src/darwintracelib1.0/darwintrace.h
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Rev URL
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/dup2.c
===================================================================
--- trunk/base/src/darwintracelib1.0/dup2.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/dup2.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#define DARWINTRACE_USE_PRIVATE_API 1
+#include "darwintrace.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c dup(2) that moves darwintrace's socket FD if software
+ * attempts to overwrite it using \c dup(2). Shells tend to do that a lot when
+ * FDs are numbered in ascending order.
+ */
+int dup2(int filedes, int filedes2) {
+#define dup2(x, y) syscall(SYS_dup2, (x), (y))
+	__darwintrace_setup();
+
+	FILE *stream = __darwintrace_sock();
+	if (stream && filedes2 == fileno(stream)) {
+		// if somebody tries to close our file descriptor, just move it out of
+		// the way. Make sure it doesn't end up as stdin/stdout/stderr, though!
+		int new_darwintrace_fd;
+		FILE *new_stream;
+
+		if (-1 == (new_darwintrace_fd = fcntl(fileno(stream), F_DUPFD, STDOUT_FILENO + 1))) {
+			// if duplicating fails, do not allow overwriting either!
+			return -1;
+		}
+
+		__darwintrace_close();
+		if (NULL == (new_stream = fdopen(new_darwintrace_fd, "a+"))) {
+			perror("darwintrace: fdopen");
+			abort();
+		}
+		__darwintrace_sock_set(new_stream);
+	}
+
+	return dup2(filedes, filedes2);
+#undef dup2
+}


Property changes on: trunk/base/src/darwintracelib1.0/dup2.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/mkdir.c
===================================================================
--- trunk/base/src/darwintracelib1.0/mkdir.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/mkdir.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c mkdir(2) that prevents creation of directories outside of
+ * the sandbox. Will silently do nothing and return success for directories
+ * outside the sandbox that already exist.
+ */
+int mkdir(const char *path, mode_t mode) {
+#define mkdir(x,y) syscall(SYS_mkdir, (x), (y))
+#define lstat(x,y) syscall(SYS_lstat, (x), (y))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT)) {
+		struct stat st;
+		if (-1 == lstat(path, &st) && errno == ENOENT) {
+			// directory doesn't exist yet */
+			errno = EACCES;
+			result = -1;
+		}
+		// otherwise, leave result at 0 and return to indicate success
+	} else {
+		result = mkdir(path, mode);
+	}
+
+	debug_printf("mkdir(%s) = %d\n", path, result);
+
+	return result;
+#undef lstat
+#undef mkdir
+}


Property changes on: trunk/base/src/darwintracelib1.0/mkdir.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/open.c
===================================================================
--- trunk/base/src/darwintracelib1.0/open.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/open.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.h 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/**
+ * Wrapper function for \c open(2). Prevents opening files outside the sandbox.
+ * Indicates the file does not exist on sandbox violation, or permission denied
+ * when attempting to create a file, i.e., when \c O_CREAT is set.
+ */
+int open(const char *path, int flags, ...) {
+#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
+	__darwintrace_setup();
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ((flags & O_CREAT) > 0) ? EACCES : ENOENT;
+		result = -1;
+	} else {
+		// Read mode and pass it to the syscall, because we cannot optionally pass
+		// parameters to syscalls
+		va_list args;
+		va_start(args, flags);
+		mode_t mode = va_arg(args, int);
+		va_end(args);
+
+		result = open(path, flags, mode);
+	}
+	debug_printf("open(%s) = %d\n", path, result);
+	return result;
+#undef open
+}


Property changes on: trunk/base/src/darwintracelib1.0/open.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/proc.c
===================================================================
--- trunk/base/src/darwintracelib1.0/proc.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/proc.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.h 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#define DARWINTRACE_USE_PRIVATE_API 1
+#include "darwintrace.h"
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <spawn.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+static void store_env() __attribute__((constructor));
+
+/**
+ * Copy of the DYLD_INSERT_LIBRARIES environment variable to restore it in
+ * execve(2). DYLD_INSERT_LIBRARIES is needed to preload this library into any
+ * process' address space.
+ */
+static char *__env_dyld_insert_libraries;
+static char *__env_full_dyld_insert_libraries;
+
+/**
+ * Copy of the DYLD_FORCE_FLAT_NAMESPACE environment variable to restore it in
+ * execve(2). DYLD_FORCE_FLAT_NAMESPACE=1 is needed for the preload-based
+ * sandbox to work.
+ */
+static char *__env_dyld_force_flat_namespace;
+static char *__env_full_dyld_force_flat_namespace;
+
+/**
+ * Copy of the DARWINTRACE_LOG environment variable to restore it in execve(2).
+ * Contains the path to the unix socket used for communication with the
+ * MacPorts-side of the sandbox. Since this variable is also used from
+ * darwintrace.c, is can not be static.
+ */
+char *__env_darwintrace_log;
+static char *__env_full_darwintrace_log;
+
+/**
+ * Copy the environment variables, if they're defined. This is run as
+ * a constructor at startup.
+ */
+static void store_env() {
+#define COPYENV(name, variable, valuevar) do {\
+		char *val;\
+		if (NULL != (val = getenv(#name))) {\
+			size_t lenName = strlen(#name);\
+			size_t lenVal  = strlen(val);\
+			if (NULL == (variable = malloc(lenName + lenVal + 0 + 1))) {\
+				perror("darwintrace: malloc");\
+				abort();\
+			}\
+			strcpy(variable, #name);\
+			strcat(variable, "=");\
+			strcat(variable, val);\
+			valuevar = variable + lenName + 1;\
+		} else {\
+			variable = NULL;\
+			valuevar = NULL;\
+		}\
+	} while (0)
+
+	COPYENV(DYLD_INSERT_LIBRARIES, __env_full_dyld_insert_libraries, __env_dyld_insert_libraries);
+	COPYENV(DYLD_FORCE_FLAT_NAMESPACE, __env_full_dyld_force_flat_namespace, __env_dyld_force_flat_namespace);
+	COPYENV(DARWINTRACE_LOG, __env_full_darwintrace_log, __env_darwintrace_log);
+#undef COPYENV
+
+	char *debugpath = getenv("DARWINTRACE_DEBUG");
+	if (debugpath) {
+		__darwintrace_stderr = fopen(debugpath, "a+");
+	} else {
+		__darwintrace_stderr = stderr;
+	}
+}
+
+/**
+ * Return false if str doesn't begin with prefix, true otherwise.
+ */
+static inline bool __darwintrace_strbeginswith(const char *str, const char *prefix) {
+	char s;
+	char p;
+	do {
+		s = *str++;
+		p = *prefix++;
+	} while (p && (p == s));
+	return (p == '\0');
+}
+
+/**
+ * This function checks that envp contains the global variables we had when the
+ * library was loaded and modifies it if it doesn't. Returns a malloc(3)'d copy
+ * of envp where the appropriate values have been restored. The caller should
+ * pass the returned pointer to free(3) if necessary to avoid leaks.
+ */
+static inline char **restore_env(char *const envp[]) {
+	// we can re-use pre-allocated strings from store_env
+	char *dyld_insert_libraries_ptr     = __env_full_dyld_insert_libraries;
+	char *dyld_force_flat_namespace_ptr = __env_full_dyld_force_flat_namespace;
+	char *darwintrace_log_ptr           = __env_full_darwintrace_log;
+
+	char *const *enviter = envp;
+	size_t envlen = 0;
+	char **copy;
+	char **copyiter;
+
+	while (*enviter != NULL) {
+		envlen++;
+		enviter++;
+	}
+
+	// 4 is sufficient for the three variables we copy and the terminator
+	copy = malloc(sizeof(char *) * (envlen + 4));
+
+	enviter  = envp;
+	copyiter = copy;
+
+	while (*enviter != NULL) {
+		char *val = *enviter;
+		if (__darwintrace_strbeginswith(val, "DYLD_INSERT_LIBRARIES=")) {
+			val = dyld_insert_libraries_ptr;
+			dyld_insert_libraries_ptr = NULL;
+		} else if (__darwintrace_strbeginswith(val, "DYLD_FORCE_FLAT_NAMESPACE=")) {
+			val = dyld_force_flat_namespace_ptr;
+			dyld_force_flat_namespace_ptr = NULL;
+		} else if (__darwintrace_strbeginswith(val, "DARWINTRACE_LOG=")) {
+			val = darwintrace_log_ptr;
+			darwintrace_log_ptr = NULL;
+		}
+
+		if (val) {
+			*copyiter++ = val;
+		}
+
+		enviter++;
+	}
+
+	if (dyld_insert_libraries_ptr) {
+		*copyiter++ = dyld_insert_libraries_ptr;
+	}
+	if (dyld_force_flat_namespace_ptr) {
+		*copyiter++ = dyld_force_flat_namespace_ptr;
+	}
+	if (darwintrace_log_ptr) {
+		*copyiter++ = darwintrace_log_ptr;
+	}
+
+	*copyiter = 0;
+
+	return copy;
+}
+
+/**
+ * Helper function that opens the file indicated by \a path, checks whether it
+ * is a script (i.e., contains a shebang line) and verifies the interpreter is
+ * within the sandbox bounds.
+ *
+ * \param[in] path The path of the file to be executed
+ * \return 0, if access should be granted, a non-zero error code to be stored
+ *         in \c errno otherwise
+ */
+static inline int check_interpreter(const char *restrict path) {
+#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
+#define close(x) syscall(SYS_close, (x))
+	int fd = open(path, O_RDONLY, 0);
+	if (fd <= 0) {
+		return errno;
+	}
+
+	char buffer[MAXPATHLEN + 1 + 2];
+	ssize_t bytes_read;
+
+	/* Read the file for the interpreter. Fortunately, on OS X:
+	 *   The system guarantees to read the number of bytes requested if
+	 *   the descriptor references a normal file that has that many
+	 *   bytes left before the end-of-file, but in no other case.
+	 * That _does_ save us another ugly loop to get things right. */
+	bytes_read = read(fd, buffer, sizeof(buffer) - 1);
+	buffer[bytes_read] = '\0';
+	const char *buffer_end = buffer + bytes_read;
+	if (bytes_read > 2 && buffer[0] == '#' && buffer[1] == '!') {
+		char *interp = buffer + 2;
+
+		/* skip past leading whitespace */
+		while (interp < buffer_end && isblank(*interp)) {
+			++interp;
+		}
+		/* found interpreter (or ran out of data); skip until next
+		 * whitespace, then terminate the string */
+		if (interp < buffer_end) {
+			char *interp_end = interp;
+			strsep(&interp_end, " \t");
+		}
+
+		/* check the iterpreter against the sandbox */
+		if (!__darwintrace_is_in_sandbox(interp, DT_REPORT | DT_ALLOWDIR)) {
+			close(fd);
+			return ENOENT;
+		}
+	}
+
+	close(fd);
+	return 0;
+#undef open
+#undef close
+}
+
+/**
+ * Wrapper for \c execve(2). Denies access and simulates the file does not
+ * exist, if it's outside the sandbox. Also checks for potential interpreters
+ * using \c check_interpreter.
+ */
+int execve(const char *path, char *const argv[], char *const envp[]) {
+#define execve(x,y,z) syscall(SYS_execve, (x), (y), (z))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		int interp_result = check_interpreter(path);
+		if (interp_result != 0) {
+			errno = interp_result;
+			result = -1;
+		} else {
+			// Since \c execve(2) will likely not return, log before calling
+			debug_printf("execve(%s) = ?\n", path);
+
+			// Our variables won't survive exec, clean up
+			__darwintrace_close();
+			__darwintrace_pid = (pid_t) -1;
+
+			// Call the original execve function, but restore environment
+			char **newenv = restore_env(envp);
+			result = execve(path, argv, newenv);
+			free(newenv);
+		}
+	}
+
+	debug_printf("execve(%s) = %d\n", path, result);
+
+	return result;
+#undef execve
+}
+
+// Let's save some typing work...
+typedef int (*posix_spawn_t)(
+			pid_t *restrict,
+			const char *restrict,
+			const posix_spawn_file_actions_t *,
+			const posix_spawnattr_t *restrict,
+			char *const *restrict,
+			char *const *restrict);
+/**
+ * Wrapper for \c posix_spawn(2). Denies access and simulates the file does not
+ * exist, if it's outside the sandbox. Also checks for potential interpreters
+ * using \c check_interpreter.
+ */
+int posix_spawn(pid_t *restrict pid, const char *restrict path, const posix_spawn_file_actions_t *file_actions,
+		const posix_spawnattr_t *restrict attrp, char *const argv[restrict], char *const envp[restrict]) {
+	__darwintrace_setup();
+
+	static posix_spawn_t prev_posix_spawn = NULL;
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		result = ENOENT;
+	} else {
+		int interp_result = check_interpreter(path);
+		if (interp_result != 0) {
+			result = interp_result;
+		} else {
+			short attrflags;
+			if (   attrp != NULL
+				&& posix_spawnattr_getflags(attrp, &attrflags) == 0
+				&& (attrflags & POSIX_SPAWN_SETEXEC) > 0) {
+				// Apple-specific extension: This call will not return, but
+				// behave like execve(2). Since our variables won't survive
+				// that, clean up. Also log the call, because we likely won't
+				// be able to after the call.
+				debug_printf("execve(%s) = ?\n", path);
+
+				__darwintrace_close();
+				__darwintrace_pid = (pid_t) - 1;
+			}
+
+			/* ATTN: the mac syscall you get from syscall(SYS_posix_spawn) corresponds
+			 * to __posix_spawn from /usr/lib/system/libsystem_kernel.dylib. We can not
+			 * override __posix_spawn directly, because it is called from posix_spawn
+			 * inside the same library (i.e., there is no dyld stub we can override).
+			 *
+			 * We cannot override posix_spawn and call __posix_spawn from it
+			 * either, because that will fail with an invalid argument. Thus,
+			 * we need to call the original posix_spawn from here. */
+			// retrieve the original posix_spawn function
+			if (prev_posix_spawn == NULL) {
+				prev_posix_spawn = (posix_spawn_t) dlsym(RTLD_NEXT, "posix_spawn");
+			}
+			// call the original posix_spawn function, but restore environment
+			char **newenv = restore_env(envp);
+			result = prev_posix_spawn(pid, path, file_actions, attrp, argv, newenv);
+			free(newenv);
+		}
+	}
+
+	debug_printf("posix_spawn(%s) = %d\n", path, result);
+
+	return result;
+}


Property changes on: trunk/base/src/darwintracelib1.0/proc.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/readdir.c
===================================================================
--- trunk/base/src/darwintracelib1.0/readdir.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/readdir.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/dirent.h>
+#include <sys/param.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+/**
+ * re-implementation of getdirent(2) and __getdirent64(2) preventing paths
+ * outside the sandbox to show up when reading the contents of a directory.
+ * Unfortunately, since we need to access the contents of the buffer, but the
+ * contents differ by architecture, we can not rely on the dirent structure
+ * defined by the header included by this program, because we don't know
+ * whether darwintrace.dylib has been compiled for 64bit or 32bit inodes. We
+ * thus copy both structs and decide at runtime.
+ */
+
+#if defined(__DARWIN_64_BIT_INO_T)
+
+struct dirent64  {
+	__uint64_t  d_ino;      /* file number of entry */
+	__uint64_t  d_seekoff;  /* seek offset */
+	__uint16_t  d_reclen;   /* length of this record */
+	__uint16_t  d_namlen;   /* length of string in d_name */
+	__uint8_t   d_type;     /* file type */
+	char      d_name[__DARWIN_MAXPATHLEN]; /* entry name (up to MAXPATHLEN bytes) */
+};
+
+size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep) {
+#define __getdirentries64(w,x,y,z) syscall(SYS_getdirentries64, (w), (x), (y), (z))
+	__darwintrace_setup();
+
+	size_t sz = __getdirentries64(fd, buf, bufsize, basep);
+	char dirname[MAXPATHLEN];
+	size_t dnamelen;
+
+	if (-1 == fcntl(fd, F_GETPATH, dirname)) {
+		errno = EBADF;
+		return -1;
+	}
+
+	dnamelen = strlen(dirname);
+	if (dirname[dnamelen - 1] != '/') {
+		dirname[dnamelen] = '/';
+		dirname[dnamelen + 1] = '\0';
+		dnamelen++;
+	}
+
+	dnamelen = strlen(dirname);
+	size_t offset;
+	for (offset = 0; offset < sz;) {
+		struct dirent64 *dent = (struct dirent64 *)(((char *) buf) + offset);
+		dirname[dnamelen] = '\0';
+		strcat(dirname, dent->d_name);
+		if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
+			debug_printf("__getdirentries64: filtered %s\n", dirname);
+			dent->d_ino = 0;
+		} else {
+			debug_printf("__getdirentries64:  allowed %s\n", dirname);
+		}
+		offset += dent->d_reclen;
+	}
+
+	return sz;
+#undef __getdirentries64
+}
+
+#endif /* defined(__DARWIN_64_BIT_INO_T) */
+
+#pragma pack(4)
+struct dirent32 {
+	ino_t d_ino;            /* file number of entry */
+	__uint16_t d_reclen;    /* length of this record */
+	__uint8_t  d_type;      /* file type */
+	__uint8_t  d_namlen;    /* length of string in d_name */
+	char d_name[__DARWIN_MAXNAMLEN + 1]; /* name must be no longer than this */
+};
+#pragma pack()
+
+int getdirentries(int fd, char *buf, int nbytes, long *basep) {
+#define getdirentries(w,x,y,z) syscall(SYS_getdirentries, (w), (x), (y), (z))
+	__darwintrace_setup();
+
+	size_t sz = getdirentries(fd, buf, nbytes, basep);
+	char dirname[MAXPATHLEN];
+	size_t dnamelen;
+
+	if (-1 == fcntl(fd, F_GETPATH, dirname)) {
+		errno = EBADF;
+		return 0;
+	}
+
+	dnamelen = strlen(dirname);
+	if (dirname[dnamelen - 1] != '/') {
+		dirname[dnamelen] = '/';
+		dirname[dnamelen + 1] = '\0';
+		dnamelen++;
+	}
+
+	size_t offset;
+	for (offset = 0; offset < sz;) {
+		struct dirent32 *dent = (struct dirent32 *)(buf + offset);
+		dirname[dnamelen] = '\0';
+		strcat(dirname, dent->d_name);
+		if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
+			debug_printf("getdirentries: filtered %s\n", dirname);
+			dent->d_ino = 0;
+		} else {
+			debug_printf("getdirentries:  allowed %s\n", dirname);
+		}
+		offset += dent->d_reclen;
+	}
+
+	return sz;
+#undef getdirentries
+}


Property changes on: trunk/base/src/darwintracelib1.0/readdir.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/readlink.c
===================================================================
--- trunk/base/src/darwintracelib1.0/readlink.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/readlink.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.h 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <unistd.h>
+
+/**
+ * Deny \c readlink(2) if the file is not within the sandbox bounds.
+ *
+ * FIXME Currently also denies reading the link if the link target does not
+ * exist. To fix this, add a parameter to __darwintrace_is_in_sandbox that
+ * controls whether symlinks should be followed.
+ */
+#ifdef READLINK_IS_NOT_P1003_1A
+int readlink(const char *path, char *buf, int bufsiz) {
+#else
+ssize_t readlink(const char *path, char *buf, size_t bufsiz) {
+#endif
+#define readlink(x,y,z) syscall(SYS_readlink, (x), (y), (z))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = readlink(path, buf, bufsiz);
+	}
+
+	debug_printf("readlink(%s) = %d\n", path, result);
+
+	return result;
+#undef readlink
+}


Property changes on: trunk/base/src/darwintracelib1.0/readlink.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/rename.c
===================================================================
--- trunk/base/src/darwintracelib1.0/rename.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/rename.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c rename(2) to prevent moving a file outside, or out of the
+ * sandbox.
+ */
+int rename(const char *from, const char *to) {
+#define rename(x,y) syscall(SYS_rename, (x), (y))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(from, DT_REPORT)) {
+		errno = ENOENT;
+		result = -1;
+	} else if (!__darwintrace_is_in_sandbox(to, DT_REPORT)) {
+		errno = EACCES;
+		result = -1;
+	} else {
+		result = rename(from, to);
+	}
+
+	debug_printf("rename(%s, %s) = %d\n", from, to, result);
+
+	return result;
+#undef rename
+}


Property changes on: trunk/base/src/darwintracelib1.0/rename.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/rmdir.c
===================================================================
--- trunk/base/src/darwintracelib1.0/rmdir.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/rmdir.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c rmdir(2) to deny deleting directories outside of the
+ * sandbox.
+ */
+int rmdir(const char *path) {
+#define rmdir(x) syscall(SYS_rmdir, (x))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = rmdir(path);
+	}
+
+	debug_printf("rmdir(%s) = %d\n", path, result);
+
+	return result;
+#undef rmdir
+}


Property changes on: trunk/base/src/darwintracelib1.0/rmdir.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/stat.c
===================================================================
--- trunk/base/src/darwintracelib1.0/stat.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/stat.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+// Do *not* include sys/stat.h, it will rewrite the stat to a stat$INODE64 symbol
+
+/**
+ * Wrapper around \c stat(2) to hide information about files outside the
+ * sandbox.
+ */
+int stat(const char *path, void *sb) {
+#define stat(path, sb) syscall(SYS_stat, path, sb)
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = stat(path, sb);
+	}
+
+	debug_printf("stat(%s) = %d\n", path, result);
+
+	return result;
+#undef stat
+}
+
+int stat64(const char *path, void *sb) {
+#define stat64(path, sb) syscall(SYS_stat64, path, sb)
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = stat64(path, sb);
+	}
+
+	debug_printf("stat64(%s) = %d\n", path, result);
+
+	return result;
+#undef stat64
+}
+
+int stat$INODE64(const char *path, void *sb) {
+	return stat64(path, sb);
+}
+
+int lstat(const char *path, void *sb) {
+#define lstat(path, sb) syscall(SYS_lstat, path, sb)
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = lstat(path, sb);
+	}
+
+	debug_printf("lstat(%s) = %d\n", path, result);
+
+	return result;
+#undef lstat
+}
+
+int lstat64(const char *path, void *sb) {
+#define lstat64(path, sb) syscall(SYS_lstat64, path, sb)
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = lstat64(path, sb);
+	}
+
+	debug_printf("lstat64(%s) = %d\n", path, result);
+
+	return result;
+#undef lstat64
+}
+
+int lstat$INODE64(const char *path, void *sb) {
+	return lstat64(path, sb);
+}


Property changes on: trunk/base/src/darwintracelib1.0/stat.c
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/base/src/darwintracelib1.0/unlink.c
===================================================================
--- trunk/base/src/darwintracelib1.0/unlink.c	                        (rev 0)
+++ trunk/base/src/darwintracelib1.0/unlink.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Paul Guyot <pguyot at kallisys.net>,
+ * All rights reserved.
+ * Copyright (c) 2006-2013 The MacPorts Project
+ *
+ * $Id: darwintrace.c 112642 2013-10-28 18:59:19Z cal at macports.org $
+ *
+ * @APPLE_BSD_LICENSE_HEADER_START@
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @APPLE_BSD_LICENSE_HEADER_END@
+ */
+
+#include "darwintrace.h"
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <unistd.h>
+
+/**
+ * Wrapper around \c unlink(2) that will deny attempts to delete files outside
+ * of the sandbox and simulate non-existence of the file instead.
+ */
+int unlink(const char *path) {
+#define unlink(x) syscall(SYS_unlink, (x))
+	__darwintrace_setup();
+
+	int result = 0;
+
+	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
+		errno = ENOENT;
+		result = -1;
+	} else {
+		result = unlink(path);
+	}
+
+	debug_printf("unlink(%s) = %d\n", path, result);
+
+	return result;
+#undef unlink
+}


Property changes on: trunk/base/src/darwintracelib1.0/unlink.c
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: trunk/base/src/pextlib1.0/tracelib.c
===================================================================
--- trunk/base/src/pextlib1.0/tracelib.c	2013-11-07 01:32:29 UTC (rev 113025)
+++ trunk/base/src/pextlib1.0/tracelib.c	2013-11-07 01:50:28 UTC (rev 113026)
@@ -106,7 +106,7 @@
 static void ui_error(const char *format, ...) __printflike(1, 2);
 
 #define MAX_SOCKETS (1024)
-#define BUFSIZE     (1024)
+#define BUFSIZE     (4096)
 
 /**
  * send a buffer \c buf with the given length \c size to the socket \c sock, by
@@ -157,6 +157,9 @@
         return TCL_ERROR;
     }
 
+    // initialize the depends field, in case we don't actually have any dependencies
+    depends = NULL;
+
     return TCL_OK;
 }
 
@@ -309,7 +312,7 @@
     if (!filemap) {
         char *t, * _;
 
-        size_t remaining = 1024;
+        size_t remaining = BUFSIZE;
         filemap = (char *)malloc(remaining);
         if (!filemap) {
             ui_warn("send_file_map: memory allocation failed");
@@ -318,10 +321,12 @@
         t = filemap;
 
 #       define append_allow(path, resolution) do { strlcpy(t, path, remaining); \
-            if (remaining < (strlen(t)+3)) \
+            if (remaining < (strlen(t)+3)) { \
                 remaining=0; \
-            else \
+                fprintf(stderr, "tracelib: insufficient filemap memory\n"); \
+            } else { \
                 remaining-=strlen(t)+3; \
+            } \
             t+=strlen(t)+1; \
             *t++=resolution; \
             *t++=0; \
@@ -429,7 +434,7 @@
     }
 
     /* check our list of dependencies */
-    for (t = depends; *t; t += strlen(t) + 1) {
+    for (t = depends; t && *t; t += strlen(t) + 1) {
         if (strcmp(t, port) == 0) {
             free(port);
             answer(sock, "+");
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20131106/ae4af60a/attachment-0001.html>


More information about the macports-changes mailing list