From: Guy Harris Date: Thu, 16 Jan 2014 02:12:06 +0000 (-0800) Subject: Move safememcpy() to util.c so it doesn't get inlined. X-Git-Tag: tcpdump-4.6.0~278 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/00cef632b48468bec911c7c66f4812ab36cad4bb Move safememcpy() to util.c so it doesn't get inlined. It appears that some C compilers will inline safememcpy() *and* will, as a result, optimize to assume alignment it if it's passed a putatively-aligned pointer. As the pointers in question are not guaranteed to be aligned, that can cause crashes on, for example, SPARC. Also, rename the function to unaligned_memcpy(), to clarify what's "safe" about it, and change some direct memcpy() calls to use it as well. --- diff --git a/interface.h b/interface.h index f551752f..8ed4a4a8 100644 --- a/interface.h +++ b/interface.h @@ -158,6 +158,8 @@ extern char *copy_argv(char **); extern void safeputchar(int); extern void safeputs(const char *, int); +extern void unaligned_memcpy(void *, const void *, size_t); + extern const char *isonsap_string(const u_char *, register u_int); extern const char *protoid_string(const u_char *); extern const char *ipxsap_string(u_short); diff --git a/netdissect.h b/netdissect.h index 8369eda6..0b194c95 100644 --- a/netdissect.h +++ b/netdissect.h @@ -270,6 +270,8 @@ extern char *copy_argv(netdissect_options *, char **); extern void safeputchar(int); extern void safeputs(const char *, int); +extern void unaligned_memcpy(void *, const void *, size_t); + #define PLURAL_SUFFIX(n) \ (((n) != 1) ? "s" : "") diff --git a/print-isakmp.c b/print-isakmp.c index e2dbf7d3..194a2837 100644 --- a/print-isakmp.c +++ b/print-isakmp.c @@ -645,7 +645,6 @@ static const u_char *ikev2_sub_print(netdissect_options *ndo, static char *numstr(int); -static void safememcpy(void *, const void *, size_t); static void ikev1_print(netdissect_options *ndo, @@ -808,13 +807,13 @@ cookie_record(cookie_t *in, const u_char *bp2) sin->sin_len = sizeof(struct sockaddr_in); #endif sin->sin_family = AF_INET; - memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); + unaligned_memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); sin = (struct sockaddr_in *)&cookiecache[ninitiator].raddr; #ifdef HAVE_SOCKADDR_SA_LEN sin->sin_len = sizeof(struct sockaddr_in); #endif sin->sin_family = AF_INET; - memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)); + unaligned_memcpy(&sin->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)); break; #ifdef INET6 case 6: @@ -829,19 +828,19 @@ cookie_record(cookie_t *in, const u_char *bp2) sin6->sin6_len = sizeof(struct sockaddr_in6); #endif sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); + unaligned_memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); sin6 = (struct sockaddr_in6 *)&cookiecache[ninitiator].raddr; #ifdef HAVE_SOCKADDR_SA_LEN sin6->sin6_len = sizeof(struct sockaddr_in6); #endif sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); + unaligned_memcpy(&sin6->sin6_addr, &ip6->ip6_dst, sizeof(ip6->ip6_dst)); break; #endif default: return; } - memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in)); + unaligned_memcpy(&cookiecache[ninitiator].initiator, in, sizeof(*in)); ninitiator = (ninitiator + 1) % MAXINITIATORS; } @@ -869,7 +868,7 @@ cookie_sidecheck(int i, const u_char *bp2, int initiator) sin->sin_len = sizeof(struct sockaddr_in); #endif sin->sin_family = AF_INET; - memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); + unaligned_memcpy(&sin->sin_addr, &ip->ip_src, sizeof(ip->ip_src)); break; #ifdef INET6 case 6: @@ -879,7 +878,7 @@ cookie_sidecheck(int i, const u_char *bp2, int initiator) sin6->sin6_len = sizeof(struct sockaddr_in6); #endif sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); + unaligned_memcpy(&sin6->sin6_addr, &ip6->ip6_src, sizeof(ip6->ip6_src)); break; #endif default: @@ -1072,7 +1071,7 @@ ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_sa *)ext; ND_TCHECK(*p); - safememcpy(&sa, ext, sizeof(sa)); + unaligned_memcpy(&sa, ext, sizeof(sa)); doi = ntohl(sa.doi); sit = ntohl(sa.sit); if (doi != 1) { @@ -1098,7 +1097,7 @@ ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_, np = (u_char *)ext + sizeof(sa); if (sit != 0x01) { ND_TCHECK2(*(ext + 1), sizeof(ident)); - safememcpy(&ident, ext + 1, sizeof(ident)); + unaligned_memcpy(&ident, ext + 1, sizeof(ident)); ND_PRINT((ndo," ident=%u", (u_int32_t)ntohl(ident))); np += sizeof(ident); } @@ -1129,7 +1128,7 @@ ikev1_p_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_p *)ext; ND_TCHECK(*p); - safememcpy(&prop, ext, sizeof(prop)); + unaligned_memcpy(&prop, ext, sizeof(prop)); ND_PRINT((ndo," #%d protoid=%s transform=%d", prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t)); if (prop.spi_size) { @@ -1296,7 +1295,7 @@ ikev1_t_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_t *)ext; ND_TCHECK(*p); - safememcpy(&t, ext, sizeof(t)); + unaligned_memcpy(&t, ext, sizeof(t)); switch (proto) { case 1: @@ -1358,7 +1357,7 @@ ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_KE))); ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_PRINT((ndo," key len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { ND_PRINT((ndo," ")); @@ -1395,7 +1394,7 @@ ikev1_id_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_id *)ext; ND_TCHECK(*p); - safememcpy(&id, ext, sizeof(id)); + unaligned_memcpy(&id, ext, sizeof(id)); if (sizeof(*p) < item_len) { data = (u_char *)(p + 1); len = item_len - sizeof(*p); @@ -1428,7 +1427,7 @@ ikev1_id_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ipsecdoi_id *)ext; ND_TCHECK(*p); - safememcpy(&id, ext, sizeof(id)); + unaligned_memcpy(&id, ext, sizeof(id)); ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.type, ipsecidtypestr))); if (id.proto_id) { #ifndef WIN32 @@ -1569,7 +1568,7 @@ ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_cert *)ext; ND_TCHECK(*p); - safememcpy(&cert, ext, sizeof(cert)); + unaligned_memcpy(&cert, ext, sizeof(cert)); ND_PRINT((ndo," len=%d", item_len - 4)); ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr))); if (2 < ndo->ndo_vflag && 4 < item_len) { @@ -1601,7 +1600,7 @@ ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_cert *)ext; ND_TCHECK(*p); - safememcpy(&cert, ext, sizeof(cert)); + unaligned_memcpy(&cert, ext, sizeof(cert)); ND_PRINT((ndo," len=%d", item_len - 4)); ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr))); if (2 < ndo->ndo_vflag && 4 < item_len) { @@ -1626,7 +1625,7 @@ ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_HASH))); ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { ND_PRINT((ndo," ")); @@ -1650,7 +1649,7 @@ ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SIG))); ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { ND_PRINT((ndo," ")); @@ -1676,7 +1675,7 @@ ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_NONCE))); ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_PRINT((ndo," n len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { ND_PRINT((ndo," ")); @@ -1754,7 +1753,7 @@ ikev1_n_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_n *)ext; ND_TCHECK(*p); - safememcpy(&n, ext, sizeof(n)); + unaligned_memcpy(&n, ext, sizeof(n)); doi = ntohl(n.doi); proto = n.prot_id; if (doi != 1) { @@ -1851,7 +1850,7 @@ ikev1_d_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev1_pl_d *)ext; ND_TCHECK(*p); - safememcpy(&d, ext, sizeof(d)); + unaligned_memcpy(&d, ext, sizeof(d)); doi = ntohl(d.doi); proto = d.prot_id; if (doi != 1) { @@ -1890,7 +1889,7 @@ ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_VID))); ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { ND_PRINT((ndo," ")); @@ -1922,7 +1921,7 @@ ikev2_gen_print(netdissect_options *ndo, u_char tpay, struct isakmp_gen e; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ikev2_pay_print(ndo, NPSTR(tpay), e.critical); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); @@ -1954,7 +1953,7 @@ ikev2_t_print(netdissect_options *ndo, u_char tpay _U_, int pcount, p = (struct ikev2_t *)ext; ND_TCHECK(*p); - safememcpy(&t, ext, sizeof(t)); + unaligned_memcpy(&t, ext, sizeof(t)); ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), t.h.critical); t_id = ntohs(t.t_id); @@ -2027,7 +2026,7 @@ ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_, p = (struct ikev2_p *)ext; ND_TCHECK(*p); - safememcpy(&prop, ext, sizeof(prop)); + unaligned_memcpy(&prop, ext, sizeof(prop)); ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), prop.h.critical); ND_PRINT((ndo," #%u protoid=%s transform=%d len=%u", @@ -2062,7 +2061,7 @@ ikev2_sa_print(netdissect_options *ndo, u_char tpay, int osa_length, sa_length; ND_TCHECK(*ext1); - safememcpy(&e, ext1, sizeof(e)); + unaligned_memcpy(&e, ext1, sizeof(e)); ikev2_pay_print(ndo, "sa", e.critical); osa_length= ntohs(e.len); @@ -2091,7 +2090,7 @@ ikev2_ke_print(netdissect_options *ndo, u_char tpay, k = (struct ikev2_ke *)ext; ND_TCHECK(*ext); - safememcpy(&ke, ext, sizeof(ke)); + unaligned_memcpy(&ke, ext, sizeof(ke)); ikev2_pay_print(ndo, NPSTR(tpay), ke.h.critical); ND_PRINT((ndo," len=%u group=%s", ntohs(ke.h.len) - 8, @@ -2121,7 +2120,7 @@ ikev2_ID_print(netdissect_options *ndo, u_char tpay, unsigned char *typedata; ND_TCHECK(*ext); - safememcpy(&id, ext, sizeof(id)); + unaligned_memcpy(&id, ext, sizeof(id)); ikev2_pay_print(ndo, NPSTR(tpay), id.h.critical); id_len = ntohs(id.h.len); @@ -2224,7 +2223,7 @@ ikev2_auth_print(netdissect_options *ndo, u_char tpay, unsigned int len; ND_TCHECK(*ext); - safememcpy(&a, ext, sizeof(a)); + unaligned_memcpy(&a, ext, sizeof(a)); ikev2_pay_print(ndo, NPSTR(tpay), a.h.critical); len = ntohs(a.h.len); @@ -2256,7 +2255,7 @@ ikev2_nonce_print(netdissect_options *ndo, u_char tpay, struct isakmp_gen e; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ikev2_pay_print(ndo, "nonce", e.critical); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); @@ -2291,7 +2290,7 @@ ikev2_n_print(netdissect_options *ndo, u_char tpay _U_, p = (struct ikev2_n *)ext; ND_TCHECK(*p); - safememcpy(&n, ext, sizeof(n)); + unaligned_memcpy(&n, ext, sizeof(n)); ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), n.h.critical); showspi = 1; @@ -2505,7 +2504,7 @@ ikev2_vid_print(netdissect_options *ndo, u_char tpay, int i, len; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ikev2_pay_print(ndo, NPSTR(tpay), e.critical); ND_PRINT((ndo," len=%d vid=", ntohs(e.len) - 4)); @@ -2568,7 +2567,7 @@ ikev2_e_print(netdissect_options *ndo, volatile int dlen; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ikev2_pay_print(ndo, NPSTR(tpay), e.critical); dlen = ntohs(e.len)-4; @@ -2640,7 +2639,7 @@ ike_sub0_print(netdissect_options *ndo, cp = (u_char *)ext; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); /* * Since we can't have a payload length of less than 4 bytes, @@ -2683,7 +2682,7 @@ ikev1_sub_print(netdissect_options *ndo, while (np) { ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_TCHECK2(*ext, ntohs(e.len)); @@ -2718,17 +2717,6 @@ numstr(int x) return buf; } -/* - * some compiler tries to optimize memcpy(), using the alignment constraint - * on the argument pointer type. by using this function, we try to avoid the - * optimization. - */ -static void -safememcpy(void *p, const void *q, size_t l) -{ - memcpy(p, q, l); -} - static void ikev1_print(netdissect_options *ndo, const u_char *bp, u_int length, @@ -2815,7 +2803,7 @@ ikev2_sub0_print(netdissect_options *ndo, struct isakmp *base, cp = (u_char *)ext; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); /* * Since we can't have a payload length of less than 4 bytes, @@ -2871,7 +2859,7 @@ ikev2_sub_print(netdissect_options *ndo, pcount++; ND_TCHECK(*ext); - safememcpy(&e, ext, sizeof(e)); + unaligned_memcpy(&e, ext, sizeof(e)); ND_TCHECK2(*ext, ntohs(e.len)); @@ -2983,7 +2971,7 @@ isakmp_print(netdissect_options *ndo, return; } - safememcpy(&base, p, sizeof(base)); + unaligned_memcpy(&base, p, sizeof(base)); ND_PRINT((ndo,"isakmp")); major = (base.vers & ISAKMP_VERS_MAJOR) diff --git a/util.c b/util.c index d7aa1fa7..f93ed437 100644 --- a/util.c +++ b/util.c @@ -601,3 +601,14 @@ safeputchar(int c) else printf("\\0x%02x", ch); } + +/* + * some compiler tries to optimize memcpy(), using the alignment constraint + * on the argument pointer type. by using this function, we try to avoid the + * optimization. + */ +void +unaligned_memcpy(void *p, const void *q, size_t l) +{ + memcpy(p, q, l); +}