1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

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.

Signed-off-by: John David Anglin <dave.anglin@bell.net>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
John David Anglin
2022-03-22 17:35:54 +00:00
parent bc0d18d873
commit 05dec22d7b
3 changed files with 21 additions and 14 deletions

View File

@ -112,8 +112,8 @@ __res_context_query (struct resolv_context *ctx, const char *name,
int *nanswerp2, int *resplen2, int *answerp2_malloced) int *nanswerp2, int *resplen2, int *answerp2_malloced)
{ {
struct __res_state *statp = ctx->resp; struct __res_state *statp = ctx->resp;
HEADER *hp = (HEADER *) answer; UHEADER *hp = (UHEADER *) answer;
HEADER *hp2; UHEADER *hp2;
int n, use_malloc = 0; int n, use_malloc = 0;
size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; 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) if (answerp != NULL)
/* __res_context_send might have reallocated the buffer. */ /* __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 /* We simplify the following tests by assigning HP to HP2 or
vice versa. It is easy to verify that this is the same as 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 else
{ {
hp2 = (HEADER *) *answerp2; hp2 = (UHEADER *) *answerp2;
if (n < (int) sizeof (HEADER)) if (n < (int) sizeof (HEADER))
{ {
hp = hp2; hp = hp2;
@ -338,7 +338,7 @@ __res_context_search (struct resolv_context *ctx,
{ {
struct __res_state *statp = ctx->resp; struct __res_state *statp = ctx->resp;
const char *cp; const char *cp;
HEADER *hp = (HEADER *) answer; UHEADER *hp = (UHEADER *) answer;
char tmp[NS_MAXDNAME]; char tmp[NS_MAXDNAME];
u_int dots; u_int dots;
int trailing_dot, ret, saved_herrno; int trailing_dot, ret, saved_herrno;

View File

@ -245,7 +245,7 @@ static void
mask_ad_bit (struct resolv_context *ctx, void *buf) mask_ad_bit (struct resolv_context *ctx, void *buf)
{ {
if (!(ctx->resp->options & RES_TRUSTAD)) if (!(ctx->resp->options & RES_TRUSTAD))
((HEADER *) buf)->ad = 0; ((UHEADER *) buf)->ad = 0;
} }
int int
@ -560,9 +560,9 @@ send_vc(res_state statp,
int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2,
int *resplen2, int *ansp2_malloced) int *resplen2, int *ansp2_malloced)
{ {
const HEADER *hp = (HEADER *) buf; const UHEADER *hp = (UHEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2; const UHEADER *hp2 = (UHEADER *) buf2;
HEADER *anhp = (HEADER *) *ansp; UHEADER *anhp = (UHEADER *) *ansp;
struct sockaddr *nsap = __res_get_nsaddr (statp, ns); struct sockaddr *nsap = __res_get_nsaddr (statp, ns);
int truncating, connreset, n; int truncating, connreset, n;
/* On some architectures compiler might emit a warning indicating /* On some architectures compiler might emit a warning indicating
@ -697,7 +697,7 @@ send_vc(res_state statp,
thisansp = ansp2; thisansp = ansp2;
thisresplenp = resplen2; thisresplenp = resplen2;
} }
anhp = (HEADER *) *thisansp; anhp = (UHEADER *) *thisansp;
*thisresplenp = rlen; *thisresplenp = rlen;
/* Is the answer buffer too small? */ /* Is the answer buffer too small? */
@ -718,7 +718,7 @@ send_vc(res_state statp,
*thisansp = newp; *thisansp = newp;
if (thisansp == ansp2) if (thisansp == ansp2)
*ansp2_malloced = 1; *ansp2_malloced = 1;
anhp = (HEADER *) newp; anhp = (UHEADER *) newp;
/* A uint16_t can't be larger than MAXPACKET /* A uint16_t can't be larger than MAXPACKET
thus it's safe to allocate MAXPACKET but thus it's safe to allocate MAXPACKET but
read RLEN bytes instead. */ 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, int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced)
{ {
const HEADER *hp = (HEADER *) buf; const UHEADER *hp = (UHEADER *) buf;
const HEADER *hp2 = (HEADER *) buf2; const UHEADER *hp2 = (UHEADER *) buf2;
struct timespec now, timeout, finish; struct timespec now, timeout, finish;
struct pollfd pfd[1]; struct pollfd pfd[1];
int ptimeout; int ptimeout;
@ -1168,7 +1168,7 @@ send_dg(res_state statp,
MSG_TRUNC which is only available on Linux. We MSG_TRUNC which is only available on Linux. We
can abstract out the Linux-specific feature in the can abstract out the Linux-specific feature in the
future to detect truncation. */ future to detect truncation. */
HEADER *anhp = (HEADER *) *thisansp; UHEADER *anhp = (UHEADER *) *thisansp;
socklen_t fromlen = sizeof(struct sockaddr_in6); socklen_t fromlen = sizeof(struct sockaddr_in6);
assert (sizeof(from) <= fromlen); assert (sizeof(from) <= fromlen);
*thisresplenp = __recvfrom (pfd[0].fd, (char *) *thisansp, *thisresplenp = __recvfrom (pfd[0].fd, (char *) *thisansp,

View File

@ -27,6 +27,13 @@
#define RES_F_CONN 0x00000002 /* Socket is connected. */ #define RES_F_CONN 0x00000002 /* Socket is connected. */
#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */ #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 /* Legacy function. This needs to be removed once all NSS modules
have been adjusted. */ have been adjusted. */
static inline bool static inline bool