Core: sockaddr lengths now respected by ngx_cmp_sockaddr().

Linux can return AF_UNIX sockaddrs with partially filled sun_path,
resulting in spurious comparison failures and failed binary upgrades.
Added proper checking of the lengths provided.

Reported by Jan Seda,
http://mailman.nginx.org/pipermail/nginx-devel/2016-September/008832.html.
This commit is contained in:
Maxim Dounin 2016-10-10 16:15:41 +03:00
parent 0ed3b2a38b
commit 1c45ee343e

View file

@ -1364,6 +1364,7 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
struct sockaddr_in6 *sin61, *sin62; struct sockaddr_in6 *sin61, *sin62;
#endif #endif
#if (NGX_HAVE_UNIX_DOMAIN) #if (NGX_HAVE_UNIX_DOMAIN)
size_t len;
struct sockaddr_un *saun1, *saun2; struct sockaddr_un *saun1, *saun2;
#endif #endif
@ -1393,15 +1394,21 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
#if (NGX_HAVE_UNIX_DOMAIN) #if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX: case AF_UNIX:
/* TODO length */
saun1 = (struct sockaddr_un *) sa1; saun1 = (struct sockaddr_un *) sa1;
saun2 = (struct sockaddr_un *) sa2; saun2 = (struct sockaddr_un *) sa2;
if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, if (slen1 < slen2) {
sizeof(saun1->sun_path)) len = slen1 - offsetof(struct sockaddr_un, sun_path);
!= 0)
{ } else {
len = slen2 - offsetof(struct sockaddr_un, sun_path);
}
if (len > sizeof(saun1->sun_path)) {
len = sizeof(saun1->sun_path);
}
if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path, len) != 0) {
return NGX_DECLINED; return NGX_DECLINED;
} }