resolv: Fix unaligned accesses to fields in HEADER struct The structure HEADER is normally aligned to a word boundary but sometimes it needs to be accessed when aligned on a byte boundary. This change defines a new typedef, UHEADER, with alignment 1. It is used to ensure the fields are accessed with byte loads and stores when necessary. V4: Change to res_mkquery.c deleted. Small whitespace fix. V5: Move UHEADER typedef to resolv/resolv-internal.h. Replace all HEADER usage with UHEADER in resolv/res_send.c. Dave --- diff --git a/resolv/res_query.c b/resolv/res_query.c index 5d0a68dc81..3b5c604261 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -112,8 +112,8 @@ __res_context_query (struct resolv_context *ctx, const char *name, int *nanswerp2, int *resplen2, int *answerp2_malloced) { struct __res_state *statp = ctx->resp; - HEADER *hp = (HEADER *) answer; - HEADER *hp2; + UHEADER *hp = (UHEADER *) answer; + UHEADER *hp2; int n, use_malloc = 0; size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; @@ -217,7 +217,7 @@ __res_context_query (struct resolv_context *ctx, const char *name, if (answerp != NULL) /* __res_context_send might have reallocated the buffer. */ - hp = (HEADER *) *answerp; + hp = (UHEADER *) *answerp; /* We simplify the following tests by assigning HP to HP2 or vice versa. It is easy to verify that this is the same as @@ -228,7 +228,7 @@ __res_context_query (struct resolv_context *ctx, const char *name, } else { - hp2 = (HEADER *) *answerp2; + hp2 = (UHEADER *) *answerp2; if (n < (int) sizeof (HEADER)) { hp = hp2; @@ -338,7 +338,7 @@ __res_context_search (struct resolv_context *ctx, { struct __res_state *statp = ctx->resp; const char *cp; - HEADER *hp = (HEADER *) answer; + UHEADER *hp = (UHEADER *) answer; char tmp[NS_MAXDNAME]; u_int dots; int trailing_dot, ret, saved_herrno; diff --git a/resolv/res_send.c b/resolv/res_send.c index 5d6be4b82d..d6c85fd7a2 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -245,7 +245,7 @@ static void mask_ad_bit (struct resolv_context *ctx, void *buf) { if (!(ctx->resp->options & RES_TRUSTAD)) - ((HEADER *) buf)->ad = 0; + ((UHEADER *) buf)->ad = 0; } int @@ -560,9 +560,9 @@ send_vc(res_state statp, int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) { - const HEADER *hp = (HEADER *) buf; - const HEADER *hp2 = (HEADER *) buf2; - HEADER *anhp = (HEADER *) *ansp; + const UHEADER *hp = (UHEADER *) buf; + const UHEADER *hp2 = (UHEADER *) buf2; + UHEADER *anhp = (UHEADER *) *ansp; struct sockaddr *nsap = __res_get_nsaddr (statp, ns); int truncating, connreset, n; /* On some architectures compiler might emit a warning indicating @@ -697,7 +697,7 @@ send_vc(res_state statp, thisansp = ansp2; thisresplenp = resplen2; } - anhp = (HEADER *) *thisansp; + anhp = (UHEADER *) *thisansp; *thisresplenp = rlen; /* Is the answer buffer too small? */ @@ -718,7 +718,7 @@ send_vc(res_state statp, *thisansp = newp; if (thisansp == ansp2) *ansp2_malloced = 1; - anhp = (HEADER *) newp; + anhp = (UHEADER *) newp; /* A uint16_t can't be larger than MAXPACKET thus it's safe to allocate MAXPACKET but read RLEN bytes instead. */ @@ -925,8 +925,8 @@ send_dg(res_state statp, int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) { - const HEADER *hp = (HEADER *) buf; - const HEADER *hp2 = (HEADER *) buf2; + const UHEADER *hp = (UHEADER *) buf; + const UHEADER *hp2 = (UHEADER *) buf2; struct timespec now, timeout, finish; struct pollfd pfd[1]; int ptimeout; @@ -1168,7 +1168,7 @@ send_dg(res_state statp, MSG_TRUNC which is only available on Linux. We can abstract out the Linux-specific feature in the future to detect truncation. */ - HEADER *anhp = (HEADER *) *thisansp; + UHEADER *anhp = (UHEADER *) *thisansp; socklen_t fromlen = sizeof(struct sockaddr_in6); assert (sizeof(from) <= fromlen); *thisresplenp = __recvfrom (pfd[0].fd, (char *) *thisansp, diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h index 2fa57d394f..9d2e832d68 100644 --- a/resolv/resolv-internal.h +++ b/resolv/resolv-internal.h @@ -27,6 +27,13 @@ #define RES_F_CONN 0x00000002 /* Socket is connected. */ #define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */ +/* The structure HEADER is normally aligned on a word boundary. In + some code, we need to access this structure when it may be aligned + on a byte boundary. To avoid unaligned accesses, we need a typedef + with alignment one. This ensures the fields are accessed with byte + loads and stores. */ +typedef HEADER __attribute__ ((__aligned__(1))) UHEADER; + /* Legacy function. This needs to be removed once all NSS modules have been adjusted. */ static inline bool