mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-11 05:03:34 +01:00
9ce0bdd226
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)".
80 lines
2.4 KiB
C
80 lines
2.4 KiB
C
/* $NetBSD: getdelim.c,v 1.2 2015/12/25 20:12:46 joerg Exp $ */
|
|
/* NetBSD-src: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */
|
|
|
|
/*-
|
|
* Copyright (c) 2011 The NetBSD Foundation, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
* by Christos Zoulas.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef BUFSIZ
|
|
#define BUFSIZ 512
|
|
#endif
|
|
|
|
ssize_t
|
|
compat_getdelim_(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
|
|
{
|
|
char *ptr, *eptr;
|
|
|
|
|
|
if (*buf == NULL || *bufsiz == 0) {
|
|
*bufsiz = BUFSIZ;
|
|
if ((*buf = raw_malloc(*bufsiz)) == NULL)
|
|
return -1;
|
|
}
|
|
|
|
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
|
|
int c = fgetc(fp);
|
|
if (c == -1) {
|
|
if (feof(fp)) {
|
|
ssize_t diff = (ssize_t)(ptr - *buf);
|
|
if (diff != 0) {
|
|
*ptr = '\0';
|
|
return diff;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
*ptr++ = c;
|
|
if (c == delimiter) {
|
|
*ptr = '\0';
|
|
return ptr - *buf;
|
|
}
|
|
if (ptr + 2 >= eptr) {
|
|
char *nbuf;
|
|
size_t nbufsiz = *bufsiz * 2;
|
|
ssize_t d = ptr - *buf;
|
|
if (nbufsiz < *bufsiz ||
|
|
(nbuf = raw_realloc(*buf, nbufsiz)) == NULL)
|
|
return -1;
|
|
*buf = nbuf;
|
|
*bufsiz = nbufsiz;
|
|
eptr = nbuf + nbufsiz;
|
|
ptr = nbuf + d;
|
|
}
|
|
}
|
|
}
|