From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202602 header.b=FCmVIPF8; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 67FB45A026E for ; Tue, 21 Apr 2026 08:25:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1776752718; bh=Pybp1kYv7dLWafFcu0ehllT7iGjnPYtT0Wh0eoocsQQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FCmVIPF8PJ2pRYDGsYHMKzwYgmrA9D3nRnJoEW1/NBnbn2KGhM8HMpTH1a5w48ufK hr13xEgpj/oVgTnIRcDawfCXo3lE3mv8JGu+T/y1hPb0nezfwgWbeKvO/8f4ZZMg7I Dfcz29i0rEwbEt+FcfdlYY1VVPe7c9VxQ9HcudSOoKq6Hg11mwnnO5jfRvW4zqpyth R2Op40U06B9bzDjaNzWJHYzwyDa7pGmsXOElTZREcLxySMAztlAvkjfMpeaEkCGYOF 7G4gMbdN7+ILd3dTBSN92UjpekvynPK0qZi172PJSjmqUDdhn/x87pXl5kXIr8F9HY 4uUA1EnsT6yqQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4g0C5V2dqsz4wJf; Tue, 21 Apr 2026 16:25:18 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH v5 08/18] tap, repair: Use SOCK_NONBLOCK and SOCK_CLOEXEC on Unix sockets Date: Tue, 21 Apr 2026 16:25:06 +1000 Message-ID: <20260421062516.2601204-9-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260421062516.2601204-1-david@gibson.dropbear.id.au> References: <20260421062516.2601204-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: BIG5KTJDU4YQ676WR6A4EQ427EK66VHT X-Message-ID-Hash: BIG5KTJDU4YQ676WR6A4EQ427EK66VHT X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: sock_unix(), which creates a listening Unix socket, doesn't set the SOCK_NONBLOCK flag. Generally, this doesn't matter because we only accept() once we've received an epoll event awaiting a connection. However we will need non-blocking accept() for the upcoming control/configuration socket. Always add SOCK_NONBLOCK, which is more robust and in keeping with the normal non-blocking style of passt. In tap.c, always set SOCK_NONBLOCK and SOCK_CLOEXEC on the accept()ed sockets as well, which we weren't doing in all cases before. According to accept(2), in Linux accepted sockets do *not* inherit these flags from the listening socket. Also check for failures of accept, discarding EAGAIN silently (a spurious epoll event) and warning for other errors. In repair.c, similarly always add CLOEXEC. Use NONBLOCK for discard sockets, but *not* for the final repair socket, since we want blocking transactions during migration. Signed-off-by: David Gibson --- repair.c | 9 +++++++-- tap.c | 12 ++++++++++-- util.c | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/repair.c b/repair.c index 69c53077..6c338da6 100644 --- a/repair.c +++ b/repair.c @@ -87,7 +87,7 @@ int repair_listen_handler(struct ctx *c, uint32_t events) /* Another client is already connected: accept and close right away. */ if (c->fd_repair != -1) { int discard = accept4(c->fd_repair_listen, NULL, NULL, - SOCK_NONBLOCK); + SOCK_CLOEXEC | SOCK_NONBLOCK); if (discard == -1) return errno; @@ -99,7 +99,12 @@ int repair_listen_handler(struct ctx *c, uint32_t events) return EEXIST; } - if ((c->fd_repair = accept4(c->fd_repair_listen, NULL, NULL, 0)) < 0) { + /* We deliberately *don't* set SOCK_NONBLOCK on the accepted socket, + * because repair transactions happen during migration, when everything + * is blocked anyway. + */ + if ((c->fd_repair = accept4(c->fd_repair_listen, NULL, NULL, + SOCK_CLOEXEC)) < 0) { rc = errno; debug_perror("accept4() on TCP_REPAIR helper listening socket"); return rc; diff --git a/tap.c b/tap.c index 7d06189d..87acd531 100644 --- a/tap.c +++ b/tap.c @@ -1415,7 +1415,7 @@ void tap_listen_handler(struct ctx *c, uint32_t events) /* Another client is already connected: accept and close right away. */ if (c->fd_tap != -1) { int discard = accept4(c->fd_tap_listen, NULL, NULL, - SOCK_NONBLOCK); + SOCK_NONBLOCK | SOCK_CLOEXEC); if (discard == -1) return; @@ -1428,7 +1428,15 @@ void tap_listen_handler(struct ctx *c, uint32_t events) return; } - c->fd_tap = accept4(c->fd_tap_listen, NULL, NULL, 0); + c->fd_tap = accept4(c->fd_tap_listen, NULL, NULL, + SOCK_NONBLOCK | SOCK_CLOEXEC); + if (c->fd_tap == -1) { + /* EAGAIN means a harmless spurious event */ + if (errno != EAGAIN) { + warn_perror("Unable to accept tap client"); + } + return; + } if (!getsockopt(c->fd_tap, SOL_SOCKET, SO_PEERCRED, &ucred, &len)) info("accepted connection from PID %i", ucred.pid); diff --git a/util.c b/util.c index 73c9d51d..204391c7 100644 --- a/util.c +++ b/util.c @@ -238,7 +238,7 @@ int sock_l4_dualstack_any(const struct ctx *c, enum epoll_type type, */ int sock_unix(char *sock_path) { - int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); struct sockaddr_un addr = { .sun_family = AF_UNIX, }; -- 2.53.0