diff options
author | Ingela Anderton Andin <[email protected]> | 2016-03-01 15:19:36 +0100 |
---|---|---|
committer | Ingela Anderton Andin <[email protected]> | 2016-03-02 15:28:58 +0100 |
commit | b1e4836bcfbfdec0504219ed490c5f53860d8106 (patch) | |
tree | c43b49a187f99ddd17506727225757d272dcb910 | |
parent | 75bc5bebc070a59535b8f6b7b9085c210b4723b5 (diff) | |
download | otp-b1e4836bcfbfdec0504219ed490c5f53860d8106.tar.gz otp-b1e4836bcfbfdec0504219ed490c5f53860d8106.tar.bz2 otp-b1e4836bcfbfdec0504219ed490c5f53860d8106.zip |
Skips any sockets with unsupported protocols.
Patch from end of PR 864
Fixes problem reported in the PR by jeckersb
In this error case, a negative file descriptor is now saved at
listensock[i], which leads to a buffer overflow later on at
https://github.com/msantos/otp/blob/epmd-IPv6-node-reg2/erts/epmd/src/epmd_srv.c#L498
when calling FD_ISSET(listensock[i],&read_mask).
To reproduce this:
Completely disable IPv6 with ipv6.disable=1 on the kernel command line
Build with fortified code (RHEL/CentOS default): CFLAGS='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fno-strict-aliasing'
-rw-r--r-- | erts/epmd/src/epmd_srv.c | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c index 55ec0f7b6c..e1bac99ef9 100644 --- a/erts/epmd/src/epmd_srv.c +++ b/erts/epmd/src/epmd_srv.c @@ -380,7 +380,7 @@ void run(EpmdVars *g) epmd_cleanup_exit(g,1); } } - g->listenfd[i] = listensock[i]; + g->listenfd[bound++] = listensock[i]; #if HAVE_DECL_IPV6_V6ONLY opt = 1; @@ -439,8 +439,6 @@ void run(EpmdVars *g) } } - bound++; - if(listen(listensock[i], SOMAXCONN) < 0) { dbg_perror(g,"failed to listen on socket"); epmd_cleanup_exit(g,1); @@ -451,6 +449,7 @@ void run(EpmdVars *g) dbg_perror(g,"unable to bind any address"); epmd_cleanup_exit(g,1); } + num_sockets = bound; #ifdef HAVE_SYSTEMD_DAEMON } sd_notifyf(0, "READY=1\n" @@ -495,8 +494,8 @@ void run(EpmdVars *g) } for (i = 0; i < num_sockets; i++) - if (FD_ISSET(listensock[i],&read_mask)) { - if (do_accept(g, listensock[i]) && g->active_conn < g->max_conn) { + if (FD_ISSET(g->listenfd[i],&read_mask)) { + if (do_accept(g, g->listenfd[i]) && g->active_conn < g->max_conn) { /* * The accept() succeeded, and we have at least one file * descriptor still free, which means that another accept() |