<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>