diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2025-02-07 01:55:08 +0100 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2025-02-07 10:35:17 +0100 |
commit | 0f009ea598707c5978846387d716f4a612d07b36 (patch) | |
tree | e1a7ffb2a4f8221cfb0a58a562678366d31d4c40 | |
parent | a0b7f56b3a3c220b3d8065d7cfdd83a6e3919467 (diff) | |
download | passt-0f009ea598707c5978846387d716f4a612d07b36.tar passt-0f009ea598707c5978846387d716f4a612d07b36.tar.gz passt-0f009ea598707c5978846387d716f4a612d07b36.tar.bz2 passt-0f009ea598707c5978846387d716f4a612d07b36.tar.lz passt-0f009ea598707c5978846387d716f4a612d07b36.tar.xz passt-0f009ea598707c5978846387d716f4a612d07b36.tar.zst passt-0f009ea598707c5978846387d716f4a612d07b36.zip |
passt-repair: Fix calculation of payload length from cmsg_len
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 <sbrivio@redhat.com>
-rw-r--r-- | passt-repair.c | 18 |
1 files 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 && |