One of the memcpy(3) callsites in notify_host() uses the size of the copy target to prevent an overrun of the target buffer. However, the target is a sockaddr_storage, while the source is never larger than a sockaddr_in6. Copying off the end of a sockaddr_in6 returned by getaddrinfo(3) could potentially cause a segfault if the allocated memory containing the address is near the end of a page, and the next page is protected. Introduced by commit 93e355bf. Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- utils/statd/sm-notify.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c index ea4ce23..1983ef6 100644 --- a/utils/statd/sm-notify.c +++ b/utils/statd/sm-notify.c @@ -61,6 +61,7 @@ struct nsm_host { char * name; char * path; struct sockaddr_storage addr; + socklen_t addrlen; struct addrinfo *ai; time_t last_used; time_t send_next; @@ -377,7 +378,6 @@ notify_host(int sock, struct nsm_host *host) { struct sockaddr_storage address; struct sockaddr *dest = (struct sockaddr *)&address; - socklen_t destlen = sizeof(address); static unsigned int xid = 0; uint32_t msgbuf[MAXMSGSIZE], *p; unsigned int len; @@ -409,10 +409,11 @@ notify_host(int sock, struct nsm_host *host) */ if (host->retries >= 4) { /* don't rotate if there is only one addrinfo */ - if (host->ai->ai_next == NULL) + if (host->ai->ai_next == NULL) { memcpy(&host->addr, host->ai->ai_addr, host->ai->ai_addrlen); - else { + host->addrlen = host->ai->ai_addrlen; + } else { struct addrinfo *first = host->ai; struct addrinfo **next = &host->ai; @@ -427,13 +428,14 @@ notify_host(int sock, struct nsm_host *host) *next = first; memcpy(&host->addr, first->ai_addr, first->ai_addrlen); + host->addrlen = host->ai->ai_addrlen; } nfs_set_port((struct sockaddr *)&host->addr, 0); host->retries = 0; } - memcpy(dest, &host->addr, destlen); + memcpy(dest, &host->addr, host->addrlen); if (nfs_get_port(dest) == 0) { /* Build a PMAP packet */ xlog(D_GENERAL, "Sending portmap query to %s", host->name); @@ -472,10 +474,10 @@ notify_host(int sock, struct nsm_host *host) } len = (p - msgbuf) << 2; - if (sendto(sock, msgbuf, len, 0, dest, destlen) < 0) + if (sendto(sock, msgbuf, len, 0, dest, host->addrlen) < 0) xlog_warn("Sending Reboot Notification to " "'%s' failed: errno %d (%m)", host->name, errno); - + return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html