diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2020-10-23 18:09:01 +0300 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2020-10-25 11:28:55 +0200 |
commit | 239cdc48640055aee8f758cf8f92048aba362f54 (patch) | |
tree | 815d218307ca4a3862153e91a9d0ef16e0c0add0 | |
parent | 897ea21e57034e45bf3bc5997ba1b560eabc8221 (diff) | |
download | mariadb-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.c | 25 |
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) |