From patchwork Sat Jan 1 21:31:03 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 77163 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4C2C0B70D4 for ; Sun, 2 Jan 2011 08:32:53 +1100 (EST) Received: from localhost ([127.0.0.1]:43524 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PZ94B-0001M1-Uh for incoming@patchwork.ozlabs.org; Sat, 01 Jan 2011 16:32:48 -0500 Received: from [140.186.70.92] (port=37821 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PZ92c-0000qw-RT for qemu-devel@nongnu.org; Sat, 01 Jan 2011 16:31:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PZ92b-0001H7-HW for qemu-devel@nongnu.org; Sat, 01 Jan 2011 16:31:10 -0500 Received: from hall.aurel32.net ([88.191.126.93]:54463) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PZ92b-0001Gu-8v for qemu-devel@nongnu.org; Sat, 01 Jan 2011 16:31:09 -0500 Received: from farad.aurel32.net ([82.232.2.251] helo=volta.aurel32.net) by hall.aurel32.net with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1PZ92Z-0007Xq-9O; Sat, 01 Jan 2011 22:31:07 +0100 Received: from aurel32 by volta.aurel32.net with local (Exim 4.72) (envelope-from ) id 1PZ92X-0000oX-Hp; Sat, 01 Jan 2011 22:31:05 +0100 From: Aurelien Jarno To: qemu-devel@nongnu.org Date: Sat, 1 Jan 2011 22:31:03 +0100 Message-Id: <1293917463-3098-1-git-send-email-aurelien@aurel32.net> X-Mailer: git-send-email 1.7.2.3 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: Aurelien Jarno Subject: [Qemu-devel] [PATCH] slirp: fix unaligned access in bootp code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Slirp code tries to be smart an avoid data copy by using pointer to the data. This solution leads to unaligned access, in this case preq_addr, which is a 32-bit long structure. There is no real point of avoiding data copy in a such case, as the value itself is smaller or the same size as a pointer. The patch replaces pointers to the preq_addr structure by the strcture itself, and use the address 0.0.0.0 if no address has been requested (this is not a valid address in such a request). It compares it with htonl(0L) for correctness reasons, in case a code checker look for such mistakes. It also uses memcpy() for copying the data, which takes care of alignement issues. This fixes an unaligned access on IA64 host while requesting a DHCP address. Signed-off-by: Aurelien Jarno --- slirp/bootp.c | 32 +++++++++++++++++--------------- 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/slirp/bootp.c b/slirp/bootp.c index 41460ff..0905c6d 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -92,13 +92,13 @@ static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr, } static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, - const struct in_addr **preq_addr) + struct in_addr *preq_addr) { const uint8_t *p, *p_end; int len, tag; *pmsg_type = 0; - *preq_addr = NULL; + preq_addr->s_addr = htonl(0L); p = bp->bp_vend; p_end = p + DHCP_OPT_LEN; @@ -124,8 +124,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, *pmsg_type = p[0]; break; case RFC2132_REQ_ADDR: - if (len >= 4) - *preq_addr = (struct in_addr *)p; + if (len >= 4) { + memcpy(&(preq_addr->s_addr), p, 4); + } break; default: break; @@ -133,8 +134,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, p += len; } } - if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) { - *preq_addr = &bp->bp_ciaddr; + if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) && + bp->bp_ciaddr.s_addr) { + memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4); } } @@ -144,15 +146,15 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) struct mbuf *m; struct bootp_t *rbp; struct sockaddr_in saddr, daddr; - const struct in_addr *preq_addr; + struct in_addr preq_addr; int dhcp_msg_type, val; uint8_t *q; /* extract exact DHCP msg type */ dhcp_decode(bp, &dhcp_msg_type, &preq_addr); DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); - if (preq_addr) - DPRINTF(" req_addr=%08x\n", ntohl(preq_addr->s_addr)); + if (preq_addr.s_addr != htonl(0L)) + DPRINTF(" req_addr=%08x\n", ntohl(preq_addr.s_addr)); else DPRINTF("\n"); @@ -175,10 +177,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) memset(rbp, 0, sizeof(struct bootp_t)); if (dhcp_msg_type == DHCPDISCOVER) { - if (preq_addr) { - bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); + if (preq_addr.s_addr != htonl(0L)) { + bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr); if (bc) { - daddr.sin_addr = *preq_addr; + daddr.sin_addr = preq_addr; } } if (!bc) { @@ -190,10 +192,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) } } memcpy(bc->macaddr, slirp->client_ethaddr, 6); - } else if (preq_addr) { - bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); + } else if (preq_addr.s_addr != htonl(0L)) { + bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr); if (bc) { - daddr.sin_addr = *preq_addr; + daddr.sin_addr = preq_addr; memcpy(bc->macaddr, slirp->client_ethaddr, 6); } else { daddr.sin_addr.s_addr = 0;