sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and port uses deleted netbuf.

This commit is contained in:
fbernon 2008-12-10 21:36:44 +00:00
parent 6777ae2ada
commit 411cb39eb4
2 changed files with 56 additions and 51 deletions

View File

@ -26,7 +26,7 @@ HISTORY
2008-10-02 Jonathan Larmour and Rishi Khan 2008-10-02 Jonathan Larmour and Rishi Khan
* sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking
socket. socket.
2008-06-30 Simon Goldschmidt 2008-06-30 Simon Goldschmidt
* mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from
@ -56,6 +56,10 @@ HISTORY
++ Bugfixes: ++ Bugfixes:
2008-12-10 Tamas Somogyi, Frédéric Bernon
* sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and
port uses deleted netbuf.
2008-10-18 Simon Goldschmidt 2008-10-18 Simon Goldschmidt
* tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length
in tcp_parseopt in tcp_parseopt
@ -69,11 +73,11 @@ HISTORY
2008-10-02 Jonathan Larmour 2008-10-02 Jonathan Larmour
* dns.c: Hard-code structure sizes, to avoid issues on some compilers where * dns.c: Hard-code structure sizes, to avoid issues on some compilers where
padding is included. padding is included.
2008-09-30 Jonathan Larmour 2008-09-30 Jonathan Larmour
* sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an
assertion check that addrlen isn't NULL. assertion check that addrlen isn't NULL.
2008-09-30 Jonathan Larmour 2008-09-30 Jonathan Larmour
* tcp.c: Fix bug #24227, wrong error message in tcp_bind. * tcp.c: Fix bug #24227, wrong error message in tcp_bind.

View File

@ -530,19 +530,66 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
if (netconn_type(sock->conn) == NETCONN_TCP) { if (netconn_type(sock->conn) == NETCONN_TCP) {
len -= copylen; len -= copylen;
if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent) { if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent || ((flags & MSG_PEEK)!=0)) {
done = 1; done = 1;
} }
} else { } else {
done = 1; done = 1;
} }
/* Check to see from where the data was.*/
if (done) {
if (from && fromlen) {
struct sockaddr_in sin;
if (netconn_type(sock->conn) == NETCONN_TCP) {
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
}
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = addr->addr;
if (*fromlen > sizeof(sin)) {
*fromlen = sizeof(sin);
}
SMEMCPY(from, &sin, *fromlen);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
} else {
#if SOCKETS_DEBUG
struct sockaddr_in sin;
if (netconn_type(sock->conn) == NETCONN_TCP) {
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
#endif /* SOCKETS_DEBUG */
}
}
/* If we don't peek the incoming message... */ /* If we don't peek the incoming message... */
if ((flags & MSG_PEEK)==0) { if ((flags & MSG_PEEK)==0) {
/* If this is a TCP socket, check if there is data left in the /* If this is a TCP socket, check if there is data left in the
buffer. If so, it should be saved in the sock structure for next buffer. If so, it should be saved in the sock structure for next
time around. */ time around. */
if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) { if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
sock->lastdata = buf; sock->lastdata = buf;
sock->lastoffset += copylen; sock->lastoffset += copylen;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf));
@ -552,55 +599,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf));
netbuf_delete(buf); netbuf_delete(buf);
} }
} else {
done = 1;
} }
} while (!done); } while (!done);
/* Check to see from where the data was.*/
if (from && fromlen) {
struct sockaddr_in sin;
if (netconn_type(sock->conn) == NETCONN_TCP) {
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
}
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = addr->addr;
if (*fromlen > sizeof(sin))
*fromlen = sizeof(sin);
SMEMCPY(from, &sin, *fromlen);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
} else {
#if SOCKETS_DEBUG
struct sockaddr_in sin;
if (netconn_type(sock->conn) == NETCONN_TCP) {
addr = (struct ip_addr*)&(sin.sin_addr.s_addr);
netconn_getaddr(sock->conn, addr, &port, 0);
} else {
addr = netbuf_fromaddr(buf);
port = netbuf_fromport(buf);
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off));
#endif /* SOCKETS_DEBUG */
}
sock_set_errno(sock, 0); sock_set_errno(sock, 0);
return off; return off;
} }