summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2020-10-23 18:09:01 +0300
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2020-10-25 11:28:55 +0200
commit239cdc48640055aee8f758cf8f92048aba362f54 (patch)
tree815d218307ca4a3862153e91a9d0ef16e0c0add0
parent897ea21e57034e45bf3bc5997ba1b560eabc8221 (diff)
downloadmariadb-git-bb-10.1-vicentiu.tar.gz
MDEV-14945 possible buffer overflow in stack resolverbb-10.1-vicentiu
According to https://stackoverflow.com/questions/22827510/how-to-avoid-bad-fd-set-buffer-overflow-crash it seems that using select instead of poll can cause additional memory allocations. As we are in a crashed state, we must prevent allocating any memory (if possible). Thus, switch select call to poll.
-rw-r--r--mysys/my_addr_resolve.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c
index ecb512572b1..878c16e6804 100644
--- a/mysys/my_addr_resolve.c
+++ b/mysys/my_addr_resolve.c
@@ -147,6 +147,12 @@ err:
#include <sys/wait.h>
+#if defined(HAVE_POLL_H)
+#include <poll.h>
+#elif defined(HAVE_SYS_POLL_H)
+#include <sys/poll.h>
+#endif /* defined(HAVE_POLL_H) */
+
static int in[2], out[2];
static pid_t pid;
static char addr2line_binary[1024];
@@ -200,8 +206,8 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
ssize_t extra_bytes_read = 0;
ssize_t parsed = 0;
- fd_set set;
- struct timeval timeout;
+ int ret;
+ struct pollfd fds;
int filename_start = -1;
int line_number_start = -1;
@@ -209,6 +215,9 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
Dl_info info;
void *offset;
+ fds.fd = out[0];
+ fds.events = POLLIN | POLLRDBAND;
+
if (!dladdr(ptr, &info))
return 1;
@@ -230,16 +239,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
if (write(in[1], input, len) <= 0)
return 1;
- FD_ZERO(&set);
- FD_SET(out[0], &set);
- /* 100 ms should be plenty of time for addr2line to issue a response. */
- timeout.tv_sec = 0;
- timeout.tv_usec = 100000;
+ /* 500 ms should be plenty of time for addr2line to issue a response. */
/* Read in a loop till all the output from addr2line is complete. */
while (parsed == total_bytes_read &&
- select(out[0] + 1, &set, NULL, NULL, &timeout) > 0)
+ (ret= poll(&fds, 1, 500)))
{
+ /* error during poll */
+ if (ret < 0)
+ return 1;
+
extra_bytes_read= read(out[0], output + total_bytes_read,
sizeof(output) - total_bytes_read);
if (extra_bytes_read < 0)