From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by passt.top (Postfix, from userid 1000) id D28385A0274; Fri, 07 Feb 2025 01:57:48 +0100 (CET) From: Stefano Brivio To: passt-dev@passt.top Subject: [PATCH] passt-repair: Fix calculation of payload length from cmsg_len Date: Fri, 7 Feb 2025 01:57:48 +0100 Message-ID: <20250207005748.3118476-1-sbrivio@redhat.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: NWRTUNWGNJ2RKHGG65TLO2DWZYYRPOJ7 X-Message-ID-Hash: NWRTUNWGNJ2RKHGG65TLO2DWZYYRPOJ7 X-MailFrom: sbrivio@passt.top 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: There's no inverse function for CMSG_LEN(), so we need to loop over SCM_MAX_FD (253) possible input values. The previous calculation is clearly wrong, as not every int takes CMSG_LEN(sizeof(int)) in cmsg data. Signed-off-by: Stefano Brivio --- passt-repair.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/passt-repair.c b/passt-repair.c index d137a18..5ad5c9c 100644 --- a/passt-repair.c +++ b/passt-repair.c @@ -57,7 +57,7 @@ int main(int argc, char **argv) char buf[CMSG_SPACE(sizeof(int) * SCM_MAX_FD)] __attribute__ ((aligned(__alignof__(struct cmsghdr)))); struct sockaddr_un a = { AF_UNIX, "" }; - int fds[SCM_MAX_FD], s, ret, i, n; + int fds[SCM_MAX_FD], s, ret, i, n = 0; struct sock_fprog prog; int8_t cmd = INT8_MAX; struct cmsghdr *cmsg; @@ -127,7 +127,21 @@ loop: _exit(1); } - n = cmsg->cmsg_len / CMSG_LEN(sizeof(int)); + /* No inverse formula for CMSG_LEN(x), and building one with CMSG_LEN(0) + * works but there's no guarantee it does. Search the whole domain. + */ + for (i = 1; i < SCM_MAX_FD; i++) { + if (CMSG_LEN(sizeof(int) * i) == cmsg->cmsg_len) { + n = i; + break; + } + } + if (!n) { + fprintf(stderr, "Invalid ancillary data length %zu from peer\n", + cmsg->cmsg_len); + _exit(1); + } + memcpy(fds, CMSG_DATA(cmsg), sizeof(int) * n); if (cmd != TCP_REPAIR_ON && cmd != TCP_REPAIR_OFF && -- 2.43.0