passt: Relicense to GPL 2.0, or any later version
In practical terms, passt doesn't benefit from the additional
protection offered by the AGPL over the GPL, because it's not
suitable to be executed over a computer network.
Further, restricting the distribution under the version 3 of the GPL
wouldn't provide any practical advantage either, as long as the passt
codebase is concerned, and might cause unnecessary compatibility
dilemmas.
Change licensing terms to the GNU General Public License Version 2,
or any later version, with written permission from all current and
past contributors, namely: myself, David Gibson, Laine Stump, Andrea
Bolognani, Paul Holzinger, Richard W.M. Jones, Chris Kuhn, Florian
Weimer, Giuseppe Scrivano, Stefan Hajnoczi, and Vasiliy Ulyanov.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2023-04-05 20:11:44 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2021-03-17 10:57:36 +01:00
|
|
|
|
|
|
|
/* PASST - Plug A Simple Socket Transport
|
passt: Add PASTA mode, major rework
PASTA (Pack A Subtle Tap Abstraction) provides quasi-native host
connectivity to an otherwise disconnected, unprivileged network
and user namespace, similarly to slirp4netns. Given that the
implementation is largely overlapping with PASST, no separate binary
is built: 'pasta' (and 'passt4netns' for clarity) both link to
'passt', and the mode of operation is selected depending on how the
binary is invoked. Usage example:
$ unshare -rUn
# echo $$
1871759
$ ./pasta 1871759 # From another terminal
# udhcpc -i pasta0 2>/dev/null
# ping -c1 pasta.pizza
PING pasta.pizza (64.190.62.111) 56(84) bytes of data.
64 bytes from 64.190.62.111 (64.190.62.111): icmp_seq=1 ttl=255 time=34.6 ms
--- pasta.pizza ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 34.575/34.575/34.575/0.000 ms
# ping -c1 spaghetti.pizza
PING spaghetti.pizza(2606:4700:3034::6815:147a (2606:4700:3034::6815:147a)) 56 data bytes
64 bytes from 2606:4700:3034::6815:147a (2606:4700:3034::6815:147a): icmp_seq=1 ttl=255 time=29.0 ms
--- spaghetti.pizza ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 28.967/28.967/28.967/0.000 ms
This entails a major rework, especially with regard to the storage of
tracked connections and to the semantics of epoll(7) references.
Indexing TCP and UDP bindings merely by socket proved to be
inflexible and unsuitable to handle different connection flows: pasta
also provides Layer-2 to Layer-2 socket mapping between init and a
separate namespace for local connections, using a pair of splice()
system calls for TCP, and a recvmmsg()/sendmmsg() pair for UDP local
bindings. For instance, building on the previous example:
# ip link set dev lo up
# iperf3 -s
$ iperf3 -c ::1 -Z -w 32M -l 1024k -P2 | tail -n4
[SUM] 0.00-10.00 sec 52.3 GBytes 44.9 Gbits/sec 283 sender
[SUM] 0.00-10.43 sec 52.3 GBytes 43.1 Gbits/sec receiver
iperf Done.
epoll(7) references now include a generic part in order to
demultiplex data to the relevant protocol handler, using 24
bits for the socket number, and an opaque portion reserved for
usage by the single protocol handlers, in order to track sockets
back to corresponding connections and bindings.
A number of fixes pertaining to TCP state machine and congestion
window handling are also included here.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
2021-07-17 08:34:53 +02:00
|
|
|
* for qemu/UNIX domain socket mode
|
|
|
|
*
|
|
|
|
* PASTA - Pack A Subtle Tap Abstraction
|
|
|
|
* for network namespace/tap device mode
|
2021-03-17 10:57:36 +01:00
|
|
|
*
|
|
|
|
* siphash.c - SipHash routines
|
|
|
|
*
|
|
|
|
* Copyright (c) 2020-2021 Red Hat GmbH
|
|
|
|
* Author: Stefano Brivio <sbrivio@redhat.com>
|
|
|
|
*
|
|
|
|
* This is an implementation of the SipHash-2-4-64 functions needed for TCP
|
|
|
|
* initial sequence numbers and socket lookup table hash for IPv4 and IPv6, see:
|
|
|
|
*
|
|
|
|
* Aumasson, J.P. and Bernstein, D.J., 2012, December. SipHash: a fast
|
|
|
|
* short-input PRF. In International Conference on Cryptology in India
|
|
|
|
* (pp. 489-508). Springer, Berlin, Heidelberg.
|
|
|
|
*
|
|
|
|
* http://cr.yp.to/siphash/siphash-20120918.pdf
|
|
|
|
*
|
|
|
|
* This includes code from the reference SipHash implementation at
|
2021-10-19 12:43:28 +02:00
|
|
|
* https://github.com/veorq/SipHash/ originally licensed as follows:
|
2021-03-17 10:57:36 +01:00
|
|
|
*
|
|
|
|
* --
|
|
|
|
* SipHash reference C implementation
|
|
|
|
*
|
|
|
|
* Copyright (c) 2012-2021 Jean-Philippe Aumasson
|
|
|
|
* <jeanphilippe.aumasson@gmail.com>
|
|
|
|
* Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
|
|
|
|
*
|
|
|
|
* To the extent possible under law, the author(s) have dedicated all copyright
|
|
|
|
* and related and neighboring rights to this software to the public domain
|
|
|
|
* worldwide. This software is distributed without any warranty.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the CC0 Public Domain Dedication along
|
|
|
|
* with
|
|
|
|
* this software. If not, see
|
|
|
|
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
|
|
* --
|
|
|
|
*
|
2021-10-19 12:43:28 +02:00
|
|
|
* and from the Linux kernel implementation (lib/siphash.c), originally licensed
|
|
|
|
* as follows:
|
2021-03-17 10:57:36 +01:00
|
|
|
*
|
|
|
|
* --
|
|
|
|
* Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* This file is provided under a dual BSD/GPLv2 license.
|
|
|
|
* --
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
#include <stddef.h>
|
2021-03-17 10:57:36 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "siphash.h"
|
|
|
|
|
|
|
|
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
#define PREAMBLE \
|
2021-03-17 10:57:36 +01:00
|
|
|
uint64_t v[4] = { 0x736f6d6570736575ULL, 0x646f72616e646f6dULL, \
|
|
|
|
0x6c7967656e657261ULL, 0x7465646279746573ULL }; \
|
|
|
|
int __i; \
|
|
|
|
\
|
|
|
|
do { \
|
2021-10-21 09:41:13 +02:00
|
|
|
for (__i = sizeof(v) / sizeof(v[0]) - 1; __i >= 0; __i--) \
|
2023-09-28 03:20:57 +02:00
|
|
|
v[__i] ^= k[__i % 2]; \
|
2021-03-17 10:57:36 +01:00
|
|
|
} while (0)
|
|
|
|
|
2023-09-28 03:20:54 +02:00
|
|
|
/**
|
|
|
|
* sipround() - Perform rounds of SipHash scrambling
|
|
|
|
* @v: siphash state (4 x 64-bit integers)
|
|
|
|
* @n: Number of rounds to apply
|
|
|
|
*/
|
|
|
|
static inline void sipround(uint64_t *v, int n)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
v[0] += v[1];
|
|
|
|
v[1] = ROTL(v[1], 13) ^ v[0];
|
|
|
|
v[0] = ROTL(v[0], 32);
|
|
|
|
v[2] += v[3];
|
|
|
|
v[3] = ROTL(v[3], 16) ^ v[2];
|
|
|
|
v[0] += v[3];
|
|
|
|
v[3] = ROTL(v[3], 21) ^ v[0];
|
|
|
|
v[2] += v[1];
|
|
|
|
v[1] = ROTL(v[1], 17) ^ v[2];
|
|
|
|
v[2] = ROTL(v[2], 32);
|
|
|
|
}
|
|
|
|
}
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:55 +02:00
|
|
|
/**
|
|
|
|
* siphash_feed() - Fold 64-bits of data into the hash state
|
|
|
|
* @v: siphash state (4 x 64-bit integers)
|
|
|
|
* @in: New value to fold into hash
|
|
|
|
*/
|
|
|
|
static inline void siphash_feed(uint64_t *v, uint64_t in)
|
|
|
|
{
|
|
|
|
v[3] ^= in;
|
|
|
|
sipround(v, 2);
|
|
|
|
v[0] ^= in;
|
|
|
|
}
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
/**
|
|
|
|
* siphash_final - Finalize SipHash calculations
|
|
|
|
* @v: siphash state (4 x 64-bit integers)
|
|
|
|
* @len: Total length of input data
|
|
|
|
* @tail: Final data for the hash (<= 7 bytes)
|
|
|
|
*/
|
|
|
|
static inline uint64_t siphash_final(uint64_t *v, size_t len, uint64_t tail)
|
|
|
|
{
|
|
|
|
uint64_t b = (uint64_t)(len) << 56 | tail;
|
|
|
|
|
|
|
|
siphash_feed(v, b);
|
|
|
|
v[2] ^= 0xff;
|
|
|
|
sipround(v, 4);
|
|
|
|
return v[0] ^ v[1] ^ v[2] ^ v[3];
|
|
|
|
}
|
2021-03-17 10:57:36 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* siphash_8b() - Table index or timestamp offset for TCP over IPv4 (8 bytes in)
|
|
|
|
* @in: Input data (remote address and two ports, or two addresses)
|
|
|
|
* @k: Hash function key, 128 bits
|
|
|
|
*
|
|
|
|
* Return: the 64-bit hash output
|
|
|
|
*/
|
treewide: Disable gcc strict aliasing rules as needed, drop workarounds
Recently, commit 4ddbcb9c0c55 ("tcp: Disable optimisations
for tcp_hash()") worked around yet another issue we hit with gcc 12
and '-flto -O2': some stores affecting the input data to siphash_20b()
were omitted altogether, and tcp_hash() wouldn't get the correct hash
for incoming connections.
Digging further into this revealed that, at least according to gcc's
interpretation of C99 aliasing rules, passing pointers to functions
with different types compared to the effective type of the object
(for example, a uint8_t pointer to an anonymous struct, as it happens
in tcp_hash()), doesn't guarantee that stores are not reordered
across the function call.
This means that, in general, our checksum and hash functions might
not see parts of input data that was intended to be provided by
callers.
Not even switching from uint8_t to character types, which should be
appropriate here, according to C99 (ISO/IEC 9899, TC3, draft N1256),
section 6.5, "Expressions", paragraph 7:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
[...]
— a character type.
does the trick. I guess this is also subject to interpretation:
casting passed pointers to character types, and then using those as
different types, might still violate (dubious) aliasing rules.
Disable gcc strict aliasing rules for potentially affected functions,
which, in turn, disables gcc's Type-Based Alias Analysis (TBAA)
optimisations based on those function arguments.
Drop the existing workarounds. Also the (seemingly?) bogus
'maybe-uninitialized' warning on the tcp_tap_handler() > tcp_hash() >
siphash_20b() path goes away with -fno-strict-aliasing on
siphash_20b().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 01:57:36 +01:00
|
|
|
/* Type-Based Alias Analysis (TBAA) optimisation in gcc 11 and 12 (-flto -O2)
|
|
|
|
* makes these functions essentially useless by allowing reordering of stores of
|
|
|
|
* input data across function calls. Not even declaring @in as char pointer is
|
|
|
|
* enough: disable gcc's interpretation of strict aliasing altogether. See also:
|
|
|
|
*
|
|
|
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106706
|
|
|
|
* https://stackoverflow.com/questions/2958633/gcc-strict-aliasing-and-horror-stories
|
|
|
|
* https://lore.kernel.org/all/alpine.LFD.2.00.0901121128080.6528__33422.5328093909$1232291247$gmane$org@localhost.localdomain/
|
|
|
|
*/
|
|
|
|
/* NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) */
|
|
|
|
__attribute__((optimize("-fno-strict-aliasing")))
|
2022-11-17 06:58:56 +01:00
|
|
|
/* cppcheck-suppress unusedFunction */
|
2021-03-17 10:57:36 +01:00
|
|
|
uint64_t siphash_8b(const uint8_t *in, const uint64_t *k)
|
|
|
|
{
|
2023-09-28 03:20:56 +02:00
|
|
|
PREAMBLE;
|
2023-09-28 03:20:55 +02:00
|
|
|
siphash_feed(v, *(uint64_t *)in);
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
|
|
|
|
return siphash_final(v, 8, 0);
|
2021-03-17 10:57:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* siphash_12b() - Initial sequence number for TCP over IPv4 (12 bytes in)
|
|
|
|
* @in: Input data (two addresses, two ports)
|
|
|
|
* @k: Hash function key, 128 bits
|
|
|
|
*
|
2023-09-28 03:20:53 +02:00
|
|
|
* Return: the 64-bit hash output
|
2021-03-17 10:57:36 +01:00
|
|
|
*/
|
treewide: Disable gcc strict aliasing rules as needed, drop workarounds
Recently, commit 4ddbcb9c0c55 ("tcp: Disable optimisations
for tcp_hash()") worked around yet another issue we hit with gcc 12
and '-flto -O2': some stores affecting the input data to siphash_20b()
were omitted altogether, and tcp_hash() wouldn't get the correct hash
for incoming connections.
Digging further into this revealed that, at least according to gcc's
interpretation of C99 aliasing rules, passing pointers to functions
with different types compared to the effective type of the object
(for example, a uint8_t pointer to an anonymous struct, as it happens
in tcp_hash()), doesn't guarantee that stores are not reordered
across the function call.
This means that, in general, our checksum and hash functions might
not see parts of input data that was intended to be provided by
callers.
Not even switching from uint8_t to character types, which should be
appropriate here, according to C99 (ISO/IEC 9899, TC3, draft N1256),
section 6.5, "Expressions", paragraph 7:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
[...]
— a character type.
does the trick. I guess this is also subject to interpretation:
casting passed pointers to character types, and then using those as
different types, might still violate (dubious) aliasing rules.
Disable gcc strict aliasing rules for potentially affected functions,
which, in turn, disables gcc's Type-Based Alias Analysis (TBAA)
optimisations based on those function arguments.
Drop the existing workarounds. Also the (seemingly?) bogus
'maybe-uninitialized' warning on the tcp_tap_handler() > tcp_hash() >
siphash_20b() path goes away with -fno-strict-aliasing on
siphash_20b().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 01:57:36 +01:00
|
|
|
/* NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) */
|
|
|
|
__attribute__((optimize("-fno-strict-aliasing"))) /* See siphash_8b() */
|
2022-11-17 06:58:59 +01:00
|
|
|
/* cppcheck-suppress unusedFunction */
|
2023-09-28 03:20:53 +02:00
|
|
|
uint64_t siphash_12b(const uint8_t *in, const uint64_t *k)
|
2021-03-17 10:57:36 +01:00
|
|
|
{
|
|
|
|
uint32_t *in32 = (uint32_t *)in;
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
PREAMBLE;
|
2023-09-28 03:20:55 +02:00
|
|
|
siphash_feed(v, (uint64_t)(*(in32 + 1)) << 32 | *in32);
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
return siphash_final(v, 12, *(in32 + 2));
|
2021-03-17 10:57:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* siphash_20b() - Table index for TCP over IPv6 (20 bytes in)
|
|
|
|
* @in: Input data (remote address, two ports)
|
|
|
|
* @k: Hash function key, 128 bits
|
|
|
|
*
|
|
|
|
* Return: the 64-bit hash output
|
|
|
|
*/
|
treewide: Disable gcc strict aliasing rules as needed, drop workarounds
Recently, commit 4ddbcb9c0c55 ("tcp: Disable optimisations
for tcp_hash()") worked around yet another issue we hit with gcc 12
and '-flto -O2': some stores affecting the input data to siphash_20b()
were omitted altogether, and tcp_hash() wouldn't get the correct hash
for incoming connections.
Digging further into this revealed that, at least according to gcc's
interpretation of C99 aliasing rules, passing pointers to functions
with different types compared to the effective type of the object
(for example, a uint8_t pointer to an anonymous struct, as it happens
in tcp_hash()), doesn't guarantee that stores are not reordered
across the function call.
This means that, in general, our checksum and hash functions might
not see parts of input data that was intended to be provided by
callers.
Not even switching from uint8_t to character types, which should be
appropriate here, according to C99 (ISO/IEC 9899, TC3, draft N1256),
section 6.5, "Expressions", paragraph 7:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
[...]
— a character type.
does the trick. I guess this is also subject to interpretation:
casting passed pointers to character types, and then using those as
different types, might still violate (dubious) aliasing rules.
Disable gcc strict aliasing rules for potentially affected functions,
which, in turn, disables gcc's Type-Based Alias Analysis (TBAA)
optimisations based on those function arguments.
Drop the existing workarounds. Also the (seemingly?) bogus
'maybe-uninitialized' warning on the tcp_tap_handler() > tcp_hash() >
siphash_20b() path goes away with -fno-strict-aliasing on
siphash_20b().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 01:57:36 +01:00
|
|
|
/* NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) */
|
|
|
|
__attribute__((optimize("-fno-strict-aliasing"))) /* See siphash_8b() */
|
2021-03-17 10:57:36 +01:00
|
|
|
uint64_t siphash_20b(const uint8_t *in, const uint64_t *k)
|
|
|
|
{
|
|
|
|
uint32_t *in32 = (uint32_t *)in;
|
|
|
|
int i;
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
PREAMBLE;
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:55 +02:00
|
|
|
for (i = 0; i < 2; i++, in32 += 2)
|
|
|
|
siphash_feed(v, (uint64_t)(*(in32 + 1)) << 32 | *in32);
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
return siphash_final(v, 20, *in32);
|
2021-03-17 10:57:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* siphash_32b() - Timestamp offset for TCP over IPv6 (32 bytes in)
|
|
|
|
* @in: Input data (two addresses)
|
|
|
|
* @k: Hash function key, 128 bits
|
|
|
|
*
|
|
|
|
* Return: the 64-bit hash output
|
|
|
|
*/
|
treewide: Disable gcc strict aliasing rules as needed, drop workarounds
Recently, commit 4ddbcb9c0c55 ("tcp: Disable optimisations
for tcp_hash()") worked around yet another issue we hit with gcc 12
and '-flto -O2': some stores affecting the input data to siphash_20b()
were omitted altogether, and tcp_hash() wouldn't get the correct hash
for incoming connections.
Digging further into this revealed that, at least according to gcc's
interpretation of C99 aliasing rules, passing pointers to functions
with different types compared to the effective type of the object
(for example, a uint8_t pointer to an anonymous struct, as it happens
in tcp_hash()), doesn't guarantee that stores are not reordered
across the function call.
This means that, in general, our checksum and hash functions might
not see parts of input data that was intended to be provided by
callers.
Not even switching from uint8_t to character types, which should be
appropriate here, according to C99 (ISO/IEC 9899, TC3, draft N1256),
section 6.5, "Expressions", paragraph 7:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
[...]
— a character type.
does the trick. I guess this is also subject to interpretation:
casting passed pointers to character types, and then using those as
different types, might still violate (dubious) aliasing rules.
Disable gcc strict aliasing rules for potentially affected functions,
which, in turn, disables gcc's Type-Based Alias Analysis (TBAA)
optimisations based on those function arguments.
Drop the existing workarounds. Also the (seemingly?) bogus
'maybe-uninitialized' warning on the tcp_tap_handler() > tcp_hash() >
siphash_20b() path goes away with -fno-strict-aliasing on
siphash_20b().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 01:57:36 +01:00
|
|
|
/* NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) */
|
|
|
|
__attribute__((optimize("-fno-strict-aliasing"))) /* See siphash_8b() */
|
2022-09-28 06:33:38 +02:00
|
|
|
/* cppcheck-suppress unusedFunction */
|
2023-09-28 03:20:53 +02:00
|
|
|
uint64_t siphash_32b(const uint8_t *in, const uint64_t *k)
|
2021-03-17 10:57:36 +01:00
|
|
|
{
|
|
|
|
uint64_t *in64 = (uint64_t *)in;
|
|
|
|
int i;
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
PREAMBLE;
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:55 +02:00
|
|
|
for (i = 0; i < 4; i++, in64++)
|
|
|
|
siphash_feed(v, *in64);
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
return siphash_final(v, 32, 0);
|
2021-03-17 10:57:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* siphash_36b() - Initial sequence number for TCP over IPv6 (36 bytes in)
|
|
|
|
* @in: Input data (two addresses, two ports)
|
|
|
|
* @k: Hash function key, 128 bits
|
|
|
|
*
|
2023-09-28 03:20:53 +02:00
|
|
|
* Return: the 64-bit hash output
|
2021-03-17 10:57:36 +01:00
|
|
|
*/
|
treewide: Disable gcc strict aliasing rules as needed, drop workarounds
Recently, commit 4ddbcb9c0c55 ("tcp: Disable optimisations
for tcp_hash()") worked around yet another issue we hit with gcc 12
and '-flto -O2': some stores affecting the input data to siphash_20b()
were omitted altogether, and tcp_hash() wouldn't get the correct hash
for incoming connections.
Digging further into this revealed that, at least according to gcc's
interpretation of C99 aliasing rules, passing pointers to functions
with different types compared to the effective type of the object
(for example, a uint8_t pointer to an anonymous struct, as it happens
in tcp_hash()), doesn't guarantee that stores are not reordered
across the function call.
This means that, in general, our checksum and hash functions might
not see parts of input data that was intended to be provided by
callers.
Not even switching from uint8_t to character types, which should be
appropriate here, according to C99 (ISO/IEC 9899, TC3, draft N1256),
section 6.5, "Expressions", paragraph 7:
An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:
[...]
— a character type.
does the trick. I guess this is also subject to interpretation:
casting passed pointers to character types, and then using those as
different types, might still violate (dubious) aliasing rules.
Disable gcc strict aliasing rules for potentially affected functions,
which, in turn, disables gcc's Type-Based Alias Analysis (TBAA)
optimisations based on those function arguments.
Drop the existing workarounds. Also the (seemingly?) bogus
'maybe-uninitialized' warning on the tcp_tap_handler() > tcp_hash() >
siphash_20b() path goes away with -fno-strict-aliasing on
siphash_20b().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
2023-02-27 01:57:36 +01:00
|
|
|
/* NOLINTNEXTLINE(clang-diagnostic-unknown-attributes) */
|
|
|
|
__attribute__((optimize("-fno-strict-aliasing"))) /* See siphash_8b() */
|
2023-09-28 03:20:53 +02:00
|
|
|
uint64_t siphash_36b(const uint8_t *in, const uint64_t *k)
|
2021-03-17 10:57:36 +01:00
|
|
|
{
|
|
|
|
uint32_t *in32 = (uint32_t *)in;
|
|
|
|
int i;
|
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
PREAMBLE;
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:55 +02:00
|
|
|
for (i = 0; i < 4; i++, in32 += 2)
|
|
|
|
siphash_feed(v, (uint64_t)(*(in32 + 1)) << 32 | *in32);
|
2021-03-17 10:57:36 +01:00
|
|
|
|
2023-09-28 03:20:56 +02:00
|
|
|
return siphash_final(v, 36, *in32);
|
2021-03-17 10:57:36 +01:00
|
|
|
}
|