Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.2:Test
libtirpc
libtirpc-0.1.9-0005-Fix-xp_raddr-handling-in-sv...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libtirpc-0.1.9-0005-Fix-xp_raddr-handling-in-svc_fd_create-etc.patch of Package libtirpc
From 59c374c4b507aeca957ed0096d98006edf601375 Mon Sep 17 00:00:00 2001 From: Olaf Kirch <okir@suse.de> Date: Tue, 30 Sep 2008 15:04:17 -0400 Subject: [PATCH] Fix xp_raddr handling in svc_fd_create etc Currently svc_fd_create tries to do some clever tricks with IPv4/v6 address mapping. This is broken for several reasons. 1. We don't want IPv4 based transport to look like IPv6 transports. Old applications compiled against tirpc will expect AF_INET addresses, and are not equipped to deal with AF_INET6. 2. There's a buffer overflow. memcpy(&sin6, &ss, sizeof(ss)); copies a full struct sockaddr to a sockaddr_in6 on the stack. Unlikely to be exploitable, but I wonder if this ever worked.... Signed-off-by: Olaf Kirch <okir@suse.de> Signed-off-by: Steve Dickson <steved@redhat.com> --- src/rpc_com.h | 2 + src/svc_dg.c | 7 +----- src/svc_vc.c | 65 +++++++++++++++++++++++++++----------------------------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/rpc_com.h b/src/rpc_com.h index 110d35a..a935080 100644 --- a/src/rpc_com.h +++ b/src/rpc_com.h @@ -85,6 +85,8 @@ bool_t __svc_clean_idle(fd_set *, int, bool_t); bool_t __xdrrec_setnonblock(XDR *, int); bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t); void __xprt_unregister_unlocked(SVCXPRT *); +void __xprt_set_raddr(SVCXPRT *, const struct sockaddr_storage *); + SVCXPRT **__svc_xports; int __svc_maxrec; diff --git a/src/svc_dg.c b/src/svc_dg.c index a72abe4..76a480e 100644 --- a/src/svc_dg.c +++ b/src/svc_dg.c @@ -193,12 +193,7 @@ again: xprt->xp_rtaddr.len = alen; } memcpy(xprt->xp_rtaddr.buf, &ss, alen); -#ifdef PORTMAP - if (ss.ss_family == AF_INET6) { - xprt->xp_raddr = *(struct sockaddr_in6 *)xprt->xp_rtaddr.buf; - xprt->xp_addrlen = sizeof (struct sockaddr_in6); - } -#endif /* PORTMAP */ + __xprt_set_raddr(xprt, &ss); xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); if (! xdr_callmsg(xdrs, msg)) { diff --git a/src/svc_vc.c b/src/svc_vc.c index 3d77aef..c62343b 100644 --- a/src/svc_vc.c +++ b/src/svc_vc.c @@ -117,6 +117,29 @@ map_ipv4_to_ipv6(sin, sin6) } /* + * This is used to set xprt->xp_raddr in a way legacy + * apps can deal with + */ +void +__xprt_set_raddr(SVCXPRT *xprt, const struct sockaddr_storage *ss) +{ + switch (ss->ss_family) { + case AF_INET6: + memcpy(&xprt->xp_raddr, ss, sizeof(struct sockaddr_in6)); + xprt->xp_addrlen = sizeof (struct sockaddr_in6); + break; + case AF_INET: + memcpy(&xprt->xp_raddr, ss, sizeof(struct sockaddr_in)); + xprt->xp_addrlen = sizeof (struct sockaddr_in); + break; + default: + xprt->xp_raddr.sin6_family = AF_UNSPEC; + xprt->xp_addrlen = sizeof (struct sockaddr); + break; + } +} + +/* * Usage: * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size); * @@ -201,7 +224,6 @@ svc_fd_create(fd, sendsize, recvsize) u_int recvsize; { struct sockaddr_storage ss; - struct sockaddr_in6 sin6; socklen_t slen; SVCXPRT *ret; @@ -228,28 +250,16 @@ svc_fd_create(fd, sendsize, recvsize) warnx("svc_fd_create: could not retrieve remote addr"); goto freedata; } - if (ss.ss_family == AF_INET) { - map_ipv4_to_ipv6((struct sockaddr_in *)&ss, &sin6); - } else { - memcpy(&sin6, &ss, sizeof(ss)); - } ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = sizeof(ss); ret->xp_rtaddr.buf = mem_alloc((size_t)sizeof(ss)); if (ret->xp_rtaddr.buf == NULL) { warnx("svc_fd_create: no mem for local addr"); goto freedata; } - if (ss.ss_family == AF_INET) - memcpy(ret->xp_rtaddr.buf, &ss, (size_t)sizeof(ss)); - else - memcpy(ret->xp_rtaddr.buf, &sin6, (size_t)sizeof(ss)); -#ifdef PORTMAP - if (sin6.sin6_family == AF_INET6 || sin6.sin6_family == AF_LOCAL) { - memcpy(&ret->xp_raddr, ret->xp_rtaddr.buf, - sizeof(struct sockaddr_in6)); - ret->xp_addrlen = sizeof (struct sockaddr_in6); - } -#endif /* PORTMAP */ + memcpy(ret->xp_rtaddr.buf, &ss, (size_t)sizeof(ss)); + + /* Set xp_raddr for compatibility */ + __xprt_set_raddr(ret, &ss); return ret; @@ -312,7 +322,6 @@ rendezvous_request(xprt, msg) struct cf_rendezvous *r; struct cf_conn *cd; struct sockaddr_storage addr; - struct sockaddr_in6 sin6; socklen_t len; struct __rpc_sockinfo si; SVCXPRT *newxprt; @@ -344,27 +353,15 @@ again: */ newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); - if (addr.ss_family == AF_INET) { - map_ipv4_to_ipv6((struct sockaddr_in *)&addr, &sin6); - } else { - memcpy(&sin6, &addr, len); - } newxprt->xp_rtaddr.buf = mem_alloc(len); if (newxprt->xp_rtaddr.buf == NULL) return (FALSE); - if (addr.ss_family == AF_INET) - memcpy(newxprt->xp_rtaddr.buf, &addr, len); - else - memcpy(newxprt->xp_rtaddr.buf, &sin6, len); + memcpy(newxprt->xp_rtaddr.buf, &addr, len); newxprt->xp_rtaddr.maxlen = newxprt->xp_rtaddr.len = len; -#ifdef PORTMAP - if (sin6.sin6_family == AF_INET6 || sin6.sin6_family == AF_LOCAL) { - memcpy(&newxprt->xp_raddr, newxprt->xp_rtaddr.buf, - sizeof(struct sockaddr_in6)); - newxprt->xp_addrlen = sizeof(struct sockaddr_in6); - } -#endif /* PORTMAP */ + + __xprt_set_raddr(newxprt, &addr); + if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) { len = 1; /* XXX fvdl - is this useful? */ -- 1.5.6
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor