Skip to content
Permalink
Browse files

Do not interpose functions before initialization

Static initializers have no defined order in which they are run;
interposed functions, however, take effect at program initialization. In
some cases, our interposed functions would be called by libSystem's
constructors and prior to *our* constructors, and this would lead to
crashes in trace mode as we would be in an uninitialized state. All our
interposers now immediately delegate to their interposees until the are
sure initialization has been performed.

Closes: https://trac.macports.org/ticket/60702
  • Loading branch information
saagarjha authored and neverpanic committed Jun 28, 2020
1 parent 62e0767 commit d96e5a85afd0ce3cdd9d8e56409ba89bafd9cccc
@@ -39,6 +39,10 @@
#include <unistd.h>

static int _dt_access(const char *path, int amode) {
if (!__darwintrace_initialized) {
return access(path, amode);
}

__darwintrace_setup();

int result = 0;
@@ -48,6 +48,10 @@
* will be set to the FD to be closed when closing should be allowed.
*/
static int _dt_close(int fd) {
if (!__darwintrace_initialized) {
return close(fd);
}

__darwintrace_setup();

FILE *stream = __darwintrace_sock();
@@ -88,7 +88,6 @@ volatile int __darwintrace_close_sock = -1;
FILE *__darwintrace_stderr = NULL;

static inline void __darwintrace_log_op(const char *op, const char *path);
static void __darwintrace_setup_tls() __attribute__((constructor));
static char *__send(const char *buf, uint32_t len, int answer);

/**
@@ -121,6 +120,27 @@ static _Atomic(char *) filemap;
static char *filemap;
#endif


volatile bool __darwintrace_initialized = false;

/**
* "Constructors" we'd like to run before we do anything. As using
* __attribute__((constructor)) for these would be unsafe here (as our
* interposed functions might end up being called first) we'll run them manually
* before we interpose anything.
*/
static void (*constructors[])() = {
__darwintrace_setup_tls,
__darwintrace_store_env,
};

void __darwintrace_run_constructors() {
for (size_t i = 0; i < sizeof(constructors) / sizeof(*constructors); ++i) {
constructors[i]();
}
__darwintrace_initialized = true;
}

static void __darwintrace_sock_destructor(FILE *dtsock) {
__darwintrace_close_sock = fileno(dtsock);
fclose(dtsock);
@@ -132,7 +152,7 @@ static void __darwintrace_sock_destructor(FILE *dtsock) {
* Setup method called as constructor to set up thread-local storage for the
* thread id and the darwintrace socket.
*/
static void __darwintrace_setup_tls() {
void __darwintrace_setup_tls() {
if (0 != (errno = pthread_key_create(&tid_key, NULL))) {
perror("darwintrace: pthread_key_create");
abort();
@@ -130,6 +130,12 @@ void __darwintrace_close();
*/
bool __darwintrace_is_in_sandbox(const char *path, int flags);

/**
* Whether darwintrace has been fully initialized or not. Do not interpose if
* this has not been set to true.
*/
volatile bool __darwintrace_initialized;

#ifdef DARWINTRACE_USE_PRIVATE_API
#include <errno.h>
#include <stdlib.h>
@@ -182,4 +188,22 @@ static inline void __darwintrace_sock_set(FILE *stream) {
abort();
}
}

/**
* Initialize TLS variables.
*/
void __darwintrace_setup_tls();

/**
* Grab environment variables at startup.
*/
void __darwintrace_store_env();

/**
* Runs our "constructors". By this point all of the system libraries we link
* against should be fully initialized, so we can call their functions safely.
* Once our initialization is complete we may begin interposing.
*/
void __darwintrace_run_constructors() __attribute__((constructor));

#endif /* defined(DARWINTRACE_USE_PRIVATE_API) */
@@ -46,6 +46,10 @@
* FDs are numbered in ascending order.
*/
static int _dt_dup2(int filedes, int filedes2) {
if (!__darwintrace_initialized) {
return dup2(filedes, filedes2);
}

__darwintrace_setup();

FILE *stream = __darwintrace_sock();
@@ -51,6 +51,10 @@
* outside the sandbox that already exist.
*/
static int _dt_mkdir(const char *path, mode_t mode) {
if (!__darwintrace_initialized) {
return mkdir(path, mode);
}

__darwintrace_setup();

int result = 0;
@@ -46,6 +46,15 @@
* when attempting to create a file, i.e., when \c O_CREAT is set.
*/
static int _dt_open(const char *path, int flags, ...) {
if (!__darwintrace_initialized) {
va_list args;
va_start(args, flags);
mode_t mode = va_arg(args, int);
va_end(args);

return open(path, flags, mode);
}

__darwintrace_setup();
int result = 0;

@@ -52,8 +52,6 @@
#include <spawn.h>
#endif

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
@@ -83,7 +81,7 @@ 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() {
void __darwintrace_store_env() {
#define COPYENV(name, variable, valuevar) do {\
char *val;\
if (NULL != (val = getenv(#name))) {\
@@ -249,6 +247,10 @@ static inline int check_interpreter(const char *restrict path) {
* using \c check_interpreter.
*/
static int _dt_execve(const char *path, char *const argv[], char *const envp[]) {
if (!__darwintrace_initialized) {
return execve(path, argv, envp);
}

__darwintrace_setup();

int result = 0;
@@ -291,6 +293,10 @@ DARWINTRACE_INTERPOSE(_dt_execve, execve);
*/
static int _dt_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]) {
if (!__darwintrace_initialized) {
return posix_spawn(pid, path, file_actions, attrp, argv, envp);
}

__darwintrace_setup();

int result = 0;
@@ -67,6 +67,10 @@ struct dirent64 {
size_t __getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep);

static size_t _dt_getdirentries64(int fd, void *buf, size_t bufsize, __darwin_off_t *basep) {
if (!__darwintrace_initialized) {
return __getdirentries64(fd, buf, bufsize, basep);
}

__darwintrace_setup();

size_t sz = __getdirentries64(fd, buf, bufsize, basep);
@@ -123,6 +127,10 @@ struct dirent32 {
int getdirentries(int fd, char *buf, int nbytes, long *basep);

static int _dt_getdirentries(int fd, char *buf, int nbytes, long *basep) {
if (!__darwintrace_initialized) {
return getdirentries(fd, buf, nbytes, basep);
}

__darwintrace_setup();

size_t sz = getdirentries(fd, buf, nbytes, basep);
@@ -43,6 +43,10 @@
* Deny \c readlink(2) if the file is not within the sandbox bounds.
*/
static ssize_t _dt_readlink(const char *path, char *buf, size_t bufsiz) {
if (!__darwintrace_initialized) {
return readlink(path, buf, bufsiz);
}

__darwintrace_setup();

int result = 0;
@@ -44,6 +44,10 @@
* sandbox.
*/
static int _dt_rename(const char *from, const char *to) {
if (!__darwintrace_initialized) {
return rename(from, to);
}

__darwintrace_setup();

int result = 0;
@@ -44,6 +44,10 @@
* sandbox.
*/
static int _dt_rmdir(const char *path) {
if (!__darwintrace_initialized) {
return rmdir(path);
}

__darwintrace_setup();

int result = 0;
@@ -50,6 +50,10 @@ int stat(const char *path, void *sb);
* sandbox.
*/
static int _dt_stat(const char *path, void *sb) {
if (!__darwintrace_initialized) {
return stat(path, sb);
}

__darwintrace_setup();

int result = 0;
@@ -75,6 +79,10 @@ int stat64(const char *path, void *sb);
int stat$INODE64(const char *path, void *sb);

static int _dt_stat64(const char *path, void *sb) {
if (!__darwintrace_initialized) {
return stat64(path, sb);
}

__darwintrace_setup();

int result = 0;
@@ -99,6 +107,10 @@ DARWINTRACE_INTERPOSE(_dt_stat64, stat$INODE64);
int lstat(const char *path, void *sb);

static int _dt_lstat(const char *path, void *sb) {
if (!__darwintrace_initialized) {
return lstat(path, sb);
}

__darwintrace_setup();

int result = 0;
@@ -125,6 +137,10 @@ int lstat64(const char *path, void *sb);
int lstat$INODE64(const char *path, void *sb);

static int _dt_lstat64(const char *path, void *sb) {
if (!__darwintrace_initialized) {
return lstat64(path, sb);
}

__darwintrace_setup();

int result = 0;
@@ -44,6 +44,10 @@
* of the sandbox and simulate non-existence of the file instead.
*/
static int _dt_unlink(const char *path) {
if (!__darwintrace_initialized) {
return unlink(path);
}

__darwintrace_setup();

int result = 0;

0 comments on commit d96e5a8

Please sign in to comment.
You can’t perform that action at this time.