<pre style='margin:0'>
Clemens Lang (neverpanic) pushed a commit to branch master
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/4811a0e20ac9bbc19dcb7aaa55c449bf2f2e2bd8">https://github.com/macports/macports-base/commit/4811a0e20ac9bbc19dcb7aaa55c449bf2f2e2bd8</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 4811a0e20ac9bbc19dcb7aaa55c449bf2f2e2bd8
</span>Author: Clemens Lang <cal@macports.org>
AuthorDate: Fri Feb 19 02:13:54 2021 +0100
<span style='display:block; white-space:pre;color:#404040;'> darwintrace: Drop injected env vars on SUID binaries
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> The loader will ignore DYLD_INSERT_LIBRARIES on SUID/SGID binaries so we
</span><span style='display:block; white-space:pre;color:#404040;'> may as well not set them when running such binaries. This could
</span><span style='display:block; white-space:pre;color:#404040;'> potentially be extended with checks for other privileged binaries where
</span><span style='display:block; white-space:pre;color:#404040;'> DYLD_INSERT_LIBRARIES will not work.
</span>---
src/darwintracelib1.0/proc.c | 38 +++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/darwintracelib1.0/proc.c b/src/darwintracelib1.0/proc.c
</span><span style='display:block; white-space:pre;color:#808080;'>index c4885fb91..e3b31c93b 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/darwintracelib1.0/proc.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/darwintracelib1.0/proc.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -44,6 +44,7 @@
</span> #include <stdlib.h>
#include <string.h>
#include <sys/param.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <sys/stat.h>
</span> #include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -123,12 +124,21 @@ static inline bool __darwintrace_strbeginswith(const char *str, const char *pref
</span> * 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.
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * If drop_env is true, returns a copy of envp with the DYLD_INSERT_LIBRARIES
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * and DARWINTRACE_LOG variables removed. This must be used with SUID/SGID
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * binaries, because the kernel will otherwise kill them.
</span> */
<span style='display:block; white-space:pre;background:#ffe0e0;'>-static inline char **restore_env(char *const envp[]) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static inline char **restore_env(char *const envp[], bool drop_env) {
</span> // we can re-use pre-allocated strings from store_env
char *dyld_insert_libraries_ptr = __env_full_dyld_insert_libraries;
char *darwintrace_log_ptr = __env_full_darwintrace_log;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (drop_env) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ dyld_insert_libraries_ptr = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ darwintrace_log_ptr = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> char *const *enviter = envp;
size_t envlen = 0;
char **copy;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -180,8 +190,9 @@ static inline char **restore_env(char *const envp[]) {
</span> * within the sandbox bounds.
*
* \param[in] path The path of the file to be executed
<span style='display:block; white-space:pre;background:#ffe0e0;'>- * \return 0, if access should be granted, a non-zero error code to be stored
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>- * in \c errno otherwise
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * \return 0, if access should be granted, -1 if this is a suid/sgid binary and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * the darwintrace environment should be dropped, a non-zero error code
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * to be stored in \c errno otherwise
</span> */
static inline int check_interpreter(const char *restrict path) {
int fd = open(path, O_RDONLY, 0);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -189,6 +200,13 @@ static inline int check_interpreter(const char *restrict path) {
</span> return errno;
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct stat st;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bool is_suid_sgid = false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (fstat(fd, &st) != -1 && (st.st_mode & (S_ISUID | S_ISGID)) > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ is_suid_sgid = true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> char buffer[MAXPATHLEN + 1 + 2];
ssize_t bytes_read;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -225,6 +243,12 @@ static inline int check_interpreter(const char *restrict path) {
</span> }
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (is_suid_sgid) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* This is a binary (i.e. it doesn't have a shebang), and it's
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * SUID/SGID, we must drop the env vars or the kernel will kill this on
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * load */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> return 0;
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -247,7 +271,7 @@ static int _dt_execve(const char *path, char *const argv[], char *const envp[])
</span> result = -1;
} else {
int interp_result = check_interpreter(path);
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (interp_result != 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (interp_result > 0) {
</span> errno = interp_result;
result = -1;
} else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -259,7 +283,7 @@ static int _dt_execve(const char *path, char *const argv[], char *const envp[])
</span> __darwintrace_pid = (pid_t) -1;
// Call the original execve function, but restore environment
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char **newenv = restore_env(envp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char **newenv = restore_env(envp, interp_result == -1);
</span> result = sip_copy_execve(path, argv, newenv);
free(newenv);
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -292,7 +316,7 @@ static int _dt_posix_spawn(pid_t *restrict pid, const char *restrict path, const
</span> result = ENOENT;
} else {
int interp_result = check_interpreter(path);
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (interp_result != 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (interp_result > 0) {
</span> result = interp_result;
} else {
short attrflags;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -310,7 +334,7 @@ static int _dt_posix_spawn(pid_t *restrict pid, const char *restrict path, const
</span> }
// call the original posix_spawn function, but restore environment
<span style='display:block; white-space:pre;background:#ffe0e0;'>- char **newenv = restore_env(envp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char **newenv = restore_env(envp, interp_result == -1);
</span> result = sip_copy_posix_spawn(pid, path, file_actions, attrp, argv, newenv);
free(newenv);
}
</pre><pre style='margin:0'>
</pre>