1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-08 05:57:51 +03:00

ctdb-common: Fix aliasing issue in IPv6 checksum

Since commit 9c51b278b1700cd5f3e2addc19b7c711cc2ea10b the compiler has
been able to inline the affected call to uint16_checksum().  Given
that the data (phdr) is being accessed by an incompatible
pointer (data) there is an aliasing problem when the call is inlined.
This results in incorrect behaviour with -O2/-O3 when compiling with
at least GCC 6, 7, and 8.

Fix this by making the types compatible.

Also fixes CID 1437604 (Reliance on integer endianness).  This is a
false positive because the uint16_checksum doesn't depend on the order
of the input uint16_t items.

https://bugzilla.samba.org/show_bug.cgi?id=13588

Pair-programmed-with: Amitay Isaacs <amitay@gmail.com>
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
(cherry picked from commit 48335725deecdbdb24a9176cf31e9611c9deda49)
This commit is contained in:
Martin Schwenke 2018-08-13 12:18:51 +10:00 committed by Karolin Seeger
parent 3fd839aeba
commit 7e38e9503a

View File

@ -270,16 +270,20 @@ static uint16_t ip_checksum(uint16_t *data, size_t n, struct ip *ip)
static uint16_t ip6_checksum(uint16_t *data, size_t n, struct ip6_hdr *ip6)
{
uint32_t phdr[2];
uint16_t phdr[3];
uint32_t sum = 0;
uint16_t sum2;
uint32_t len;
sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16);
sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16);
phdr[0] = htonl(n);
phdr[1] = htonl(ip6->ip6_nxt);
sum += uint16_checksum((uint16_t *)phdr, 8);
len = htonl(n);
phdr[0] = len & UINT16_MAX;
phdr[1] = (len >> 16) & UINT16_MAX;
/* ip6_nxt is only 8 bits, so fits comfortably into a uint16_t */
phdr[2] = htons(ip6->ip6_nxt);
sum += uint16_checksum(phdr, sizeof(phdr));
sum += uint16_checksum(data, n);