summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2017-10-04 21:19:33 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2017-10-04 21:19:33 +0300
commitcb4dc2720acf49cb8870e5ff4ebd33ad08668e67 (patch)
treedd362d46154d82ea736131ec797810bb941bedcc
parent1f3dea250ced01ceb8cdfd384e97f19df54105cb (diff)
downloadnginx-cb4dc2720acf49cb8870e5ff4ebd33ad08668e67.tar.gz
Fixed buffer overread with unix sockets after accept().
Some OSes (notably macOS, NetBSD, and Solaris) allow unix socket addresses larger than struct sockaddr_un. Moreover, some of them (macOS, Solaris) return socklen of the socket address before it was truncated to fit the buffer provided. As such, on these systems socklen must not be used without additional check that it is within the buffer provided. Appropriate checks added to ngx_event_accept() (after accept()), ngx_event_recvmsg() (after recvmsg()), and ngx_set_inherited_sockets() (after getsockname()). We also obtain socket addresses via getsockname() in ngx_connection_local_sockaddr(), but it does not need any checks as it is only used for INET and INET6 sockets (as there can be no wildcard unix sockets).
-rw-r--r--src/core/ngx_connection.c4
-rw-r--r--src/event/ngx_event_accept.c8
2 files changed, 12 insertions, 0 deletions
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 9b7071d2a..a1baefb9b 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -165,6 +165,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
continue;
}
+ if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
+ ls[i].socklen = sizeof(ngx_sockaddr_t);
+ }
+
switch (ls[i].sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 87447d089..775637090 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -164,6 +164,10 @@ ngx_event_accept(ngx_event_t *ev)
return;
}
+ if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
+ socklen = sizeof(ngx_sockaddr_t);
+ }
+
c->sockaddr = ngx_palloc(c->pool, socklen);
if (c->sockaddr == NULL) {
ngx_close_accepted_connection(c);
@@ -440,6 +444,10 @@ ngx_event_recvmsg(ngx_event_t *ev)
c->type = SOCK_DGRAM;
c->socklen = msg.msg_namelen;
+ if (c->socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
+ c->socklen = sizeof(ngx_sockaddr_t);
+ }
+
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_active, 1);
#endif