提交 8aaf42ed 编写于 作者: A Aurelien Jarno

slirp: fix unaligned access in bootp code

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: NAurelien Jarno <aurelien@aurel32.net>
上级 102c2976
...@@ -92,13 +92,13 @@ static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr, ...@@ -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, 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; const uint8_t *p, *p_end;
int len, tag; int len, tag;
*pmsg_type = 0; *pmsg_type = 0;
*preq_addr = NULL; preq_addr->s_addr = htonl(0L);
p = bp->bp_vend; p = bp->bp_vend;
p_end = p + DHCP_OPT_LEN; p_end = p + DHCP_OPT_LEN;
...@@ -124,8 +124,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, ...@@ -124,8 +124,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
*pmsg_type = p[0]; *pmsg_type = p[0];
break; break;
case RFC2132_REQ_ADDR: case RFC2132_REQ_ADDR:
if (len >= 4) if (len >= 4) {
*preq_addr = (struct in_addr *)p; memcpy(&(preq_addr->s_addr), p, 4);
}
break; break;
default: default:
break; break;
...@@ -133,8 +134,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, ...@@ -133,8 +134,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
p += len; p += len;
} }
} }
if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) { if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&
*preq_addr = &bp->bp_ciaddr; 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) ...@@ -144,15 +146,15 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
struct mbuf *m; struct mbuf *m;
struct bootp_t *rbp; struct bootp_t *rbp;
struct sockaddr_in saddr, daddr; struct sockaddr_in saddr, daddr;
const struct in_addr *preq_addr; struct in_addr preq_addr;
int dhcp_msg_type, val; int dhcp_msg_type, val;
uint8_t *q; uint8_t *q;
/* extract exact DHCP msg type */ /* extract exact DHCP msg type */
dhcp_decode(bp, &dhcp_msg_type, &preq_addr); dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
if (preq_addr) if (preq_addr.s_addr != htonl(0L))
DPRINTF(" req_addr=%08x\n", ntohl(preq_addr->s_addr)); DPRINTF(" req_addr=%08x\n", ntohl(preq_addr.s_addr));
else else
DPRINTF("\n"); DPRINTF("\n");
...@@ -175,10 +177,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) ...@@ -175,10 +177,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
memset(rbp, 0, sizeof(struct bootp_t)); memset(rbp, 0, sizeof(struct bootp_t));
if (dhcp_msg_type == DHCPDISCOVER) { if (dhcp_msg_type == DHCPDISCOVER) {
if (preq_addr) { if (preq_addr.s_addr != htonl(0L)) {
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) { if (bc) {
daddr.sin_addr = *preq_addr; daddr.sin_addr = preq_addr;
} }
} }
if (!bc) { if (!bc) {
...@@ -190,10 +192,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) ...@@ -190,10 +192,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
} }
} }
memcpy(bc->macaddr, slirp->client_ethaddr, 6); memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else if (preq_addr) { } else if (preq_addr.s_addr != htonl(0L)) {
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr); bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) { if (bc) {
daddr.sin_addr = *preq_addr; daddr.sin_addr = preq_addr;
memcpy(bc->macaddr, slirp->client_ethaddr, 6); memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else { } else {
daddr.sin_addr.s_addr = 0; daddr.sin_addr.s_addr = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册