aboutsummaryrefslogtreecommitdiff
path: root/src/ext
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@stoeckmann.org>2019-03-31 12:27:55 +0200
committerGeorge Kadianakis <desnacked@riseup.net>2019-04-10 12:46:27 +0300
commit9ce0bdd22636a332399d65f280915e899a24b69b (patch)
tree7551d308493cdf3a49d61dd83c95ef02266fa7e8 /src/ext
parent9f3f99938e441c09c1b3bf64510b8fb682dba007 (diff)
downloadtor-9ce0bdd22636a332399d65f280915e899a24b69b.tar.gz
tor-9ce0bdd22636a332399d65f280915e899a24b69b.zip
Prevent double free on huge files with 32 bit.
The function compat_getdelim_ is used for tor_getline if tor is compiled on a system that lacks getline and getdelim. These systems should be very rare, considering that getdelim is POSIX. If this system is further a 32 bit architecture, it is possible to trigger a double free with huge files. If bufsiz has been already increased to 2 GB, the next chunk would be 4 GB in size, which wraps around to 0 due to 32 bit limitations. A realloc(*buf, 0) could be imagined as "free(*buf); return malloc(0);" which therefore could return NULL. The code in question considers that an error, but will keep the value of *buf pointing to already freed memory. The caller of tor_getline() would free the pointer again, therefore leading to a double free. This code can only be triggered in dirserv_read_measured_bandwidths with a huge measured bandwith list file on a system that actually allows to reach 2 GB of space through realloc. It is not possible to trigger this on Linux with glibc or other major *BSD systems even on unit tests, because these systems cannot reach so much memory due to memory fragmentation. This patch is effectively based on the penetration test report of cure53 for curl available at https://cure53.de/pentest-report_curl.pdf and explained under section "CRL-01-007 Double-free in aprintf() via unsafe size_t multiplication (Medium)".
Diffstat (limited to 'src/ext')
-rw-r--r--src/ext/getdelim.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/ext/getdelim.c b/src/ext/getdelim.c
index 8254103ff9..1c29baffd9 100644
--- a/src/ext/getdelim.c
+++ b/src/ext/getdelim.c
@@ -67,7 +67,8 @@ compat_getdelim_(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
- if ((nbuf = raw_realloc(*buf, nbufsiz)) == NULL)
+ if (nbufsiz < *bufsiz ||
+ (nbuf = raw_realloc(*buf, nbufsiz)) == NULL)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;