From owner-freebsd-alpha Wed Jan 30 13:46:35 2002 Delivered-To: freebsd-alpha@freebsd.org Received: from r220-1.rz.RWTH-Aachen.DE (r220-1.rz.RWTH-Aachen.DE [134.130.3.31]) by hub.freebsd.org (Postfix) with ESMTP id 9700637B402 for ; Wed, 30 Jan 2002 13:46:29 -0800 (PST) Received: from r220-1.rz.RWTH-Aachen.DE (relay2.RWTH-Aachen.DE [134.130.3.1]) by r220-1.rz.RWTH-Aachen.DE (8.10.1/8.11.3-2) with ESMTP id g0ULkQL24859 for ; Wed, 30 Jan 2002 22:46:26 +0100 (MET) Received: from hyperion.informatik.rwth-aachen.de (hyperion.Informatik.RWTH-Aachen.DE [137.226.194.33]) by r220-1.rz.RWTH-Aachen.DE (8.10.1/8.11.3/6) with ESMTP id g0ULkQu24851 for ; Wed, 30 Jan 2002 22:46:26 +0100 (MET) Received: from margaux.informatik.rwth-aachen.de (margaux.Informatik.RWTH-Aachen.DE [137.226.194.72]) by hyperion.informatik.rwth-aachen.de (8.9.1b+Sun/8.9.1) with ESMTP id WAA29572 for ; Wed, 30 Jan 2002 22:44:55 +0100 (MET) Received: (from stolz@localhost) by margaux.informatik.rwth-aachen.de (8.9.1b+Sun/8.9.1-gb-2) id WAA14161 for alpha@freebsd.org; Wed, 30 Jan 2002 22:46:21 +0100 (MET) Date: Wed, 30 Jan 2002 22:46:21 +0100 From: Volker Stolz To: alpha@freebsd.org Subject: rpc.statd/SIOCGIFCONF revisited Message-ID: <20020130224621.A14154@i2.informatik.rwth-aachen.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="RnlQjJ0d97Da+TV1" Content-Disposition: inline User-Agent: Mutt/1.3.17i Sender: owner-freebsd-alpha@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org --RnlQjJ0d97Da+TV1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here's another try after the previous patch did mor good than harm. What happens is this: the ioctl fills a buffer with various entries for interfaces. If it's a sockaddr, everything goes well, that's 7x8 = 56 bytes. Unluckily, for inet6, you get 28 bytes. In your buffer that means something like --|--|--|... 56 28 XX Now the userland code in e.g. libc/rpc/get_myaddress.c memcpy tried now to access XX which obviusly isn't at an 8 byte aligned address. memcpy() *should* be able to copy this region. *But*: memcpy() gets optimized by gcc to use floating point registers (unless you specify -fno-builtin). These instructions can only work on double word aligned data :-/ Something similar happens when you use an assignment like foo = *bar. If you use -fno-builtin, get_myaddress will crash at *addr = *((struct sockaddr_in *)&ifrn->ifr_addr); for a similar reason (the address has to be double word aligned or the ldq will throw... You can find several hints in itojun's and on NetBSD, boling down to inet6 not being LP64 friendly, and SIOCGIFCONF being especially nasty. The attached patch *should* do the following: copy the requested number of bytes but advance to the next aligned positioned and update the sa_len entry only in the structure returned to userland. Thus, if you just use the sa_len entry without resorting to sizeof() your application should work fine. Comments are definetly appreciated. I cannot claim that I understand everything of the stuff going on there, so I'd like to get some thumbs up/down from savvier people. -- Wonderful \hbox (0.80312pt too nice) in paragraph at lines 16--18 Volker Stolz * stolz@i2.informatik.rwth-aachen.de Please use PGP or S/MIME for correspondence! --RnlQjJ0d97Da+TV1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="alpha.patch" --- sys/net/if.c.orig Wed Jan 30 21:25:50 2002 +++ sys/net/if.c Wed Jan 30 21:34:27 2002 @@ -1318,17 +1318,20 @@ sizeof (ifr)); ifrp++; } else { - if (space < sizeof (ifr) + sa->sa_len - + if (space < sizeof (ifr) + _ALIGN(sa->sa_len) - sizeof(*sa)) break; - space -= sa->sa_len - sizeof(*sa); + space -= _ALIGN(sa->sa_len) - sizeof(*sa); error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr.ifr_name)); if (error == 0) error = copyout((caddr_t)sa, (caddr_t)&ifrp->ifr_addr, sa->sa_len); - ifrp = (struct ifreq *) - (sa->sa_len + (caddr_t)&ifrp->ifr_addr); + /* Update sa_len to aligned value in output */ + ifrp->ifr_addr.sa_len = _ALIGN(sa->sa_len); + /* Advance ptr, accounting for spilled padding, too */ + ifrp = _ALIGN((struct ifreq *) + (sa->sa_len + (caddr_t)&ifrp->ifr_addr)); } if (error) break; --RnlQjJ0d97Da+TV1-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-alpha" in the body of the message