Commit 85843491 authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

MDEV-14945 possible buffer overflow in stack resolver

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.

Also move some bigger datastructures to global space. The code is not
run in a multithreaded context so best we don't use up stack space
if it's not needed.
parent 44c958dd
...@@ -147,10 +147,18 @@ const char *my_addr_resolve_init() ...@@ -147,10 +147,18 @@ const char *my_addr_resolve_init()
#include <sys/wait.h> #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 int in[2], out[2];
static pid_t pid; static pid_t pid;
static char addr2line_binary[1024]; static char addr2line_binary[1024];
static char output[1024]; static char output[1024];
static struct pollfd poll_fds;
Dl_info info;
int start_addr2line_fork(const char *binary_path) int start_addr2line_fork(const char *binary_path)
{ {
...@@ -200,15 +208,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -200,15 +208,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
ssize_t extra_bytes_read = 0; ssize_t extra_bytes_read = 0;
ssize_t parsed = 0; ssize_t parsed = 0;
fd_set set; int ret;
struct timeval timeout;
int filename_start = -1; int filename_start = -1;
int line_number_start = -1; int line_number_start = -1;
Dl_info info;
void *offset; void *offset;
poll_fds.fd = out[0];
poll_fds.events = POLLIN | POLLRDBAND;
if (!dladdr(ptr, &info)) if (!dladdr(ptr, &info))
return 1; return 1;
...@@ -230,16 +239,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ...@@ -230,16 +239,16 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc)
if (write(in[1], input, len) <= 0) if (write(in[1], input, len) <= 0)
return 1; return 1;
FD_ZERO(&set);
FD_SET(out[0], &set);
/* 100 ms should be plenty of time for addr2line to issue a response. */ /* 500 ms should be plenty of time for addr2line to issue a response. */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
/* Read in a loop till all the output from addr2line is complete. */ /* Read in a loop till all the output from addr2line is complete. */
while (parsed == total_bytes_read && while (parsed == total_bytes_read &&
select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) (ret= poll(&poll_fds, 1, 500)))
{ {
/* error during poll */
if (ret < 0)
return 1;
extra_bytes_read= read(out[0], output + total_bytes_read, extra_bytes_read= read(out[0], output + total_bytes_read,
sizeof(output) - total_bytes_read); sizeof(output) - total_bytes_read);
if (extra_bytes_read < 0) if (extra_bytes_read < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment