udp: Don't prematurely (and incorrectly) set up automatic inbound forwards

For automated inbound port forwarding in pasta mode we scan bound ports
within the guest namespace via /proc and bind matching ports on the host to
listen for packets.  For UDP this is usually handled by udp_timer() which
calls port_fwd_scan_udp() followed by udp_port_rebind().  However there's
one initial scan before the the UDP timer is started: we call
port_fwd_scan_udp() from port_fwd_init(), and actually bind the resulting
ports in udp_sock_init_init() called from udp_init().

Unfortunately, the version in udp_sock_init_init() isn't correct.  It
unconditionally opens a new socket for every forwarded port, even if a
socket has already been explicit created with the -u option.  If the
explicitly forwarded ports have particular configuration (such as a
specific bound address address, or one implied by the -o option) those will
not be replicated in the new socket.  We essentially leak the original
correctly configured socket, replacing it with one which might not be
right.

We could make udp_sock_init_init() use udp_port_rebind() to get that right,
but there's actually no point doing so:
 * The initial bind was introduced by ccf6d2a7b4 ("udp: Actually bind
   detected namespace ports in init namespace") at which time we didn't
   periodically scan for bound UDP ports.  Periodic scanning was introduced
   in 457ff122e ("udp,pasta: Periodically scan for ports to automatically
   forward") making the bind from udp_init() redundant.
 * At the time of udp_init(), programs in the guest namespace are likely
   not to have started yet (unless attaching a pre-existing namespace) so
   there's likely not anything to scan for anyway.

So, simply remove the initial, broken socket create/bind, allowing
automatic port forwards to be created the first time udp_timer() runs.

Reported-by: Laurent Jacquot <jk@lutty.net>
Suggested-by: Laurent Jacquot <jk@lutty.net>
Link: https://bugs.passt.top/show_bug.cgi?id=79
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-02-12 17:06:57 +11:00 committed by Stefano Brivio
parent 9f57983886
commit 96ad5c5acd

17
udp.c
View file

@ -1041,22 +1041,6 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
return r4 < 0 ? r4 : r6;
}
/**
* udp_sock_init_init() - Bind sockets in init namespace for inbound connections
* @c: Execution context
*/
static void udp_sock_init_init(const struct ctx *c)
{
unsigned dst;
for (dst = 0; dst < NUM_PORTS; dst++) {
if (!bitmap_isset(c->udp.fwd_in.f.map, dst))
continue;
udp_sock_init(c, 0, AF_UNSPEC, NULL, NULL, dst);
}
}
/**
* udp_sock_init_ns() - Bind sockets in namespace for outbound connections
* @arg: Execution context
@ -1125,7 +1109,6 @@ int udp_init(struct ctx *c)
if (c->mode == MODE_PASTA) {
udp_splice_iov_init();
udp_sock_init_init(c);
NS_CALL(udp_sock_init_ns, c);
}