]> git.kaiwu.me - nginx.git/commitdiff
Fixed buffer overread with unix sockets after accept().
authorMaxim Dounin <mdounin@mdounin.ru>
Wed, 4 Oct 2017 18:19:33 +0000 (21:19 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Wed, 4 Oct 2017 18:19:33 +0000 (21:19 +0300)
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).

src/core/ngx_connection.c
src/event/ngx_event_accept.c

index 9b7071d2a2ac7b06c92224018d2643cecc5334a6..a1baefb9bc6e3e04b925b0b4e08ba169298be93d 100644 (file)
@@ -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)
index 87447d08937ce30fbe64cdcaf4bd48bf0df34958..77563709057474d9402e7d96b4a7d570249ad457 100644 (file)
@@ -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