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