diff --git a/passt.c b/passt.c index 8ddd9b3..0246b04 100644 --- a/passt.c +++ b/passt.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef HAS_GETRANDOM +#include +#endif #include "util.h" #include "passt.h" @@ -103,6 +106,41 @@ static void post_handler(struct ctx *c, const struct timespec *now) #undef CALL_PROTO_HANDLER } +/** + * secret_init() - Create secret value for SipHash calculations + * @c: Execution context + */ +static void secret_init(struct ctx *c) +{ +#ifndef HAS_GETRANDOM + int dev_random = open("/dev/random", O_RDONLY); + unsigned int random_read = 0; + + while (dev_random && random_read < sizeof(c->hash_secret)) { + int ret = read(dev_random, + (uint8_t *)&c->hash_secret + random_read, + sizeof(c->hash_secret) - random_read); + + if (ret == -1 && errno == EINTR) + continue; + + if (ret <= 0) + break; + + random_read += ret; + } + if (dev_random >= 0) + close(dev_random); + if (random_read < sizeof(c->hash_secret)) { +#else + if (getrandom(&c->hash_secret, sizeof(c->hash_secret), + GRND_RANDOM) < 0) { +#endif /* !HAS_GETRANDOM */ + perror("TCP initial sequence getrandom"); + exit(EXIT_FAILURE); + } +} + /** * timer_init() - Set initial timestamp for timer runs to current time * @c: Execution context @@ -237,6 +275,8 @@ int main(int argc, char **argv) tap_sock_init(&c); + secret_init(&c); + clock_gettime(CLOCK_MONOTONIC, &now); if ((!c.no_udp && udp_init(&c)) || (!c.no_tcp && tcp_init(&c))) diff --git a/passt.h b/passt.h index 33b493f..c74887a 100644 --- a/passt.h +++ b/passt.h @@ -211,6 +211,7 @@ struct ip6_ctx { * @fd_tap: AF_UNIX socket, tuntap device, or pre-opened socket * @mac: Host MAC address * @mac_guest: MAC address of guest or namespace, seen or configured + * @hash_secret: 128-bit secret for siphash functions * @ifi4: Index of template interface for IPv4, 0 if IPv4 disabled * @ip: IPv4 configuration * @dns_search: DNS search list @@ -265,6 +266,7 @@ struct ctx { int fd_tap; unsigned char mac[ETH_ALEN]; unsigned char mac_guest[ETH_ALEN]; + uint64_t hash_secret[2]; unsigned int ifi4; struct ip4_ctx ip4; diff --git a/tcp.c b/tcp.c index 7e5f99d..40908b4 100644 --- a/tcp.c +++ b/tcp.c @@ -279,9 +279,6 @@ #include #include #include -#ifdef HAS_GETRANDOM -#include -#endif #include #include #include @@ -1172,7 +1169,7 @@ static int tcp_hash_match(const struct tcp_tap_conn *conn, static unsigned int tcp_hash(const struct ctx *c, const union inany_addr *faddr, in_port_t eport, in_port_t fport) { - struct siphash_state state = SIPHASH_INIT(c->tcp.hash_secret); + struct siphash_state state = SIPHASH_INIT(c->hash_secret); uint64_t hash; inany_siphash_feed(&state, faddr); @@ -1779,7 +1776,7 @@ static void tcp_tap_window_update(struct tcp_tap_conn *conn, unsigned wnd) static void tcp_seq_init(const struct ctx *c, struct tcp_tap_conn *conn, const struct timespec *now) { - struct siphash_state state = SIPHASH_INIT(c->tcp.hash_secret); + struct siphash_state state = SIPHASH_INIT(c->hash_secret); union inany_addr aany; uint64_t hash; uint32_t ns; @@ -3087,34 +3084,6 @@ static void tcp_sock_refill_init(const struct ctx *c) */ int tcp_init(struct ctx *c) { -#ifndef HAS_GETRANDOM - int dev_random = open("/dev/random", O_RDONLY); - unsigned int random_read = 0; - - while (dev_random && random_read < sizeof(c->tcp.hash_secret)) { - int ret = read(dev_random, - (uint8_t *)&c->tcp.hash_secret + random_read, - sizeof(c->tcp.hash_secret) - random_read); - - if (ret == -1 && errno == EINTR) - continue; - - if (ret <= 0) - break; - - random_read += ret; - } - if (dev_random >= 0) - close(dev_random); - if (random_read < sizeof(c->tcp.hash_secret)) { -#else - if (getrandom(&c->tcp.hash_secret, sizeof(c->tcp.hash_secret), - GRND_RANDOM) < 0) { -#endif /* !HAS_GETRANDOM */ - perror("TCP initial sequence getrandom"); - exit(EXIT_FAILURE); - } - if (c->ifi4) tcp_sock4_iov_init(c); diff --git a/tcp.h b/tcp.h index c8b738d..27b1166 100644 --- a/tcp.h +++ b/tcp.h @@ -52,7 +52,6 @@ union tcp_listen_epoll_ref { /** * struct tcp_ctx - Execution context for TCP routines - * @hash_secret: 128-bit secret for hash functions, ISN and hash table * @port_to_tap: Ports bound host-side, packets to tap or spliced * @fwd_in: Port forwarding configuration for inbound packets * @fwd_out: Port forwarding configuration for outbound packets @@ -61,7 +60,6 @@ union tcp_listen_epoll_ref { * @pipe_size: Size of pipes for spliced connections */ struct tcp_ctx { - uint64_t hash_secret[2]; struct port_fwd fwd_in; struct port_fwd fwd_out; struct timespec timer_run;