<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/3d95f5f36646602778f25b88265fe868729e41fe">https://github.com/macports/macports-base/commit/3d95f5f36646602778f25b88265fe868729e41fe</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 3d95f5f36646602778f25b88265fe868729e41fe
</span>Author: Clemens Lang <cal@macports.org>
AuthorDate: Sat Dec 19 01:05:22 2020 +0100

<span style='display:block; white-space:pre;color:#404040;'>    darwintrace: Fix potential buffer overflow in readdir(3)
</span>---
 src/darwintracelib1.0/readdir.c | 58 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 48 insertions(+), 10 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/darwintracelib1.0/readdir.c b/src/darwintracelib1.0/readdir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 1ad7dc8b4..e413e6775 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/darwintracelib1.0/readdir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/darwintracelib1.0/readdir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -36,11 +36,12 @@
</span> #include "darwintrace.h"
 
 #include <errno.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <string.h>
</span> #include <sys/dirent.h>
 #include <sys/param.h>
 #include <unistd.h>
<span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <fcntl.h>
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-#include <string.h>
</span> 
 /**
  * re-implementation of getdirent(2) and __getdirent64(2) preventing paths
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -74,11 +75,16 @@ static size_t _dt_getdirentries64(int fd, void *buf, size_t bufsize, __darwin_of
</span>   __darwintrace_setup();
 
        size_t sz = __getdirentries64(fd, buf, bufsize, basep);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        // FIXME Support longer paths
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-   char dirname[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   size_t maxDirname = MAXPATHLEN + 1 + NAME_MAX;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   char *dirname = malloc(maxDirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (dirname == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           errno = ENOMEM;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span>   size_t dnamelen;
 
        if (-1 == fcntl(fd, F_GETPATH, dirname)) {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                free(dirname);
</span>           errno = EBADF;
                return -1;
        }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -90,13 +96,24 @@ static size_t _dt_getdirentries64(int fd, void *buf, size_t bufsize, __darwin_of
</span>           dnamelen++;
        }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        dnamelen = strlen(dirname);
</span>   size_t offset;
        for (offset = 0; offset < sz;) {
                struct dirent64 *dent = (struct dirent64 *)(((char *) buf) + offset);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                size_t dentlen = strlen(dent->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           if (maxDirname < dnamelen + dentlen + 1) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   char *new = realloc(dirname, dnamelen + dentlen + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   if (new == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           free(dirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           errno = EBADF;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   dirname = new;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   maxDirname = dnamelen + dentlen + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>           dirname[dnamelen] = '\0';
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                // FIXME This crashes sometimes
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-           strcat(dirname, dent->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           strlcat(dirname, dent->d_name, maxDirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>           if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
                        debug_printf("__getdirentries64: filtered %s\n", dirname);
                        dent->d_ino = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -106,6 +123,7 @@ static size_t _dt_getdirentries64(int fd, void *buf, size_t bufsize, __darwin_of
</span>           offset += dent->d_reclen;
        }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(dirname);
</span>   return sz;
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -134,12 +152,18 @@ static int _dt_getdirentries(int fd, char *buf, int nbytes, long *basep) {
</span>   __darwintrace_setup();
 
        size_t sz = getdirentries(fd, buf, nbytes, basep);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        char dirname[MAXPATHLEN];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   size_t maxDirname = MAXPATHLEN + 1 + NAME_MAX;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   char *dirname = malloc(maxDirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (dirname == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           errno = ENOMEM;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span>   size_t dnamelen;
 
        if (-1 == fcntl(fd, F_GETPATH, dirname)) {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                free(dirname);
</span>           errno = EBADF;
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return -1;
</span>   }
 
        dnamelen = strlen(dirname);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -152,8 +176,21 @@ static int _dt_getdirentries(int fd, char *buf, int nbytes, long *basep) {
</span>   size_t offset;
        for (offset = 0; offset < sz;) {
                struct dirent32 *dent = (struct dirent32 *)(buf + offset);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                size_t dentlen = strlen(dent->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           if (maxDirname < dnamelen + dentlen + 1) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   char *new = realloc(dirname, dnamelen + dentlen + 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   if (new == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           free(dirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           errno = EBADF;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   dirname = new;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   maxDirname = dnamelen + dentlen + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>           dirname[dnamelen] = '\0';
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                strcat(dirname, dent->d_name);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           strlcat(dirname, dent->d_name, maxDirname);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>           if (!__darwintrace_is_in_sandbox(dirname, DT_ALLOWDIR)) {
                        debug_printf("getdirentries: filtered %s\n", dirname);
                        dent->d_ino = 0;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -163,6 +200,7 @@ static int _dt_getdirentries(int fd, char *buf, int nbytes, long *basep) {
</span>           offset += dent->d_reclen;
        }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        free(dirname);
</span>   return sz;
 }
 
</pre><pre style='margin:0'>

</pre>