From nobody Tue Jun 30 17:20:08 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gqVJn37pzz6jXfS for ; Tue, 30 Jun 2026 17:20:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gqVJm5N6Jz3q1r for ; Tue, 30 Jun 2026 17:20:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782840008; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=WDZDuL9iae35XeFgaXA3qhCDIkhTZGlHZlL3SlFBrFg=; b=JxpEJGJ+VIpuC/4WrJC7GYpvV2bTGVhOqEp8gFSoW7P9K6hBlwzLUTX7UCSm7pQ9a28a/0 bw5u9ldQfFzvleVHHSSmzg82AM9IphL5zHeJTY+gOkfdxzx5o8cICF0/yYnnoIx+HFn/gp SUyATxK5KkJ0Jv5WtpmDXQOVwG/aE9N2Z8NgtnJ+oX3KqbvqdmV2YyFywPiYovfUKnfi3F NWAWgPLLwvAD87SmvWKYKASelPuQVaUw33TWmsKYsUFVkWb3XfFSJHc6qnb0uRcr67VfPm aPhIFmlPU7BWYsnmmgsMCG8xyGFpDz4sIjSTW15RTBXxTXniCIB5B2t3wW3Fqg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782840008; a=rsa-sha256; cv=none; b=JpId2VY/a0fEc7JjdCqmqTtMGePAyP0EyVAiSmNhl5tW7iObfOk6HHVQrHleQBNOBbIXg7 WqO5WJZbUdXMtZHOGZ1bGo+Kl1cZOJGA+dmfMri8uyklEzXD/HxXIxS5u6Ah1pvJ9fc2lM nM0wkHuJjFbi5caQ50ixC7I0uB/izDccI4NKFWaSgj5CJmzlfRKiJnx7SJJz3baccK+9nt HqBF0JTRyHeqOi7TmWPNizOf+nCpmbA6j44lAmhA1tcZAb73EmdMCVop3xTe7M17iE8xnH 5dZlOsDHemYXmXcdL+HqskPuxjpGs8Owmlk7DhjmpR21zTF2p248CcC/4gy5tw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782840008; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=WDZDuL9iae35XeFgaXA3qhCDIkhTZGlHZlL3SlFBrFg=; b=vM0/1OY4hto4voZwWqNc/pUCTmoc5A6yl6jBsro9gUi9MC0NI9soh+RERXaFSRTkPxS8ON TvH0sznCqMGxkv0mlmEisz+iYua18EpovTjZYKWomk8Y+RGtNa1W7B0CIZYnetyq9HaGh0 vi7n/WGOdXRqHkhzNnXwWXWBwYObZLLHjVlJxiletmBXAdn44K+a+GAIFmcbOstovw5rhL 57Gs6HEv3ekqv56Q+IkN7lfH0XL76DbGMgfiHUI6UgXJeaHgK/vjGEkkFf5d0JITwgNBHQ YmmJnRfB149RR1mh0JxYCqjr3cJgBBBdxh7rnPkTWhLNGBwJzumfsbYa/uI5Og== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gqVJm4K7zztXN for ; Tue, 30 Jun 2026 17:20:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 4588c by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 30 Jun 2026 17:20:08 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav From: Mark Johnston Subject: git: cb5f47a761fe - stable/15 - libalias: Fix buffer overflow in RTSP aliasing List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: cb5f47a761fefaf9b86ed500e5563d872f23f2cd Auto-Submitted: auto-generated Date: Tue, 30 Jun 2026 17:20:08 +0000 Message-Id: <6a43fac8.4588c.4253db3b@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=cb5f47a761fefaf9b86ed500e5563d872f23f2cd commit cb5f47a761fefaf9b86ed500e5563d872f23f2cd Author: Dag-Erling Smørgrav AuthorDate: 2026-06-28 22:10:40 +0000 Commit: Mark Johnston CommitDate: 2026-06-30 17:00:27 +0000 libalias: Fix buffer overflow in RTSP aliasing In alias_rtsp_out(), we construct a new packet in a fixed-length buffer before copying it back into the original buffer. We never checked if the data we were writing to this temporary buffer fit in it, nor if the result fit in the original buffer. * Use a dynamically sized allocated buffer instead of a fixed-length stack buffer. * Check for overflow before appending to our temporary buffer. * Check for overflow before copying the data back to the packet buffer. * While here, use size_t for sizes and bool for booleans. Approved by: so Security: FreeBSD-SA-26:41.libalias Security: CVE-2026-49420 MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D57753 --- sys/netinet/libalias/alias_smedia.c | 156 ++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 67 deletions(-) diff --git a/sys/netinet/libalias/alias_smedia.c b/sys/netinet/libalias/alias_smedia.c index badd75a45c61..cbfe30940596 100644 --- a/sys/netinet/libalias/alias_smedia.c +++ b/sys/netinet/libalias/alias_smedia.c @@ -104,8 +104,9 @@ #include #include #else -#include #include +#include +#include #include #include #endif @@ -128,9 +129,9 @@ #define RTSP_CONTROL_PORT_NUMBER_2 7070 #define TFTP_PORT_NUMBER 69 -static void -AliasHandleRtspOut(struct libalias *, struct ip *, struct alias_link *, - int maxpacketsize); +static void AliasHandleRtspOut(struct libalias *, struct ip *, + struct alias_link *, size_t); + static int fingerprint(struct libalias *la, struct alias_data *ah) { @@ -154,7 +155,8 @@ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) if (ntohs(*ah->dport) == TFTP_PORT_NUMBER) FindRtspOut(la, pip->ip_src, pip->ip_dst, *ah->sport, *ah->aport, IPPROTO_UDP); - else AliasHandleRtspOut(la, pip, ah->lnk, ah->maxpktsize); + else + AliasHandleRtspOut(la, pip, ah->lnk, ah->maxpktsize); return (0); } @@ -208,13 +210,15 @@ MODULE_DEPEND(alias_smedia, libalias, 1, 1, 1); #define ISDIGIT(a) (((a) >= '0') && ((a) <= '9')) -static int -search_string(char *data, int dlen, const char *search_str) +static ssize_t +search_string(char *data, size_t dlen, const char *search_str) { - int i, j, k; - int search_str_len; + size_t i, j, k; + size_t search_str_len; search_str_len = strlen(search_str); + if (search_str_len > dlen) + return (-1); for (i = 0; i < dlen - search_str_len; i++) { for (j = i, k = 0; j < dlen - search_str_len; j++, k++) { if (data[j] != search_str[k] && @@ -230,18 +234,21 @@ search_string(char *data, int dlen, const char *search_str) static int alias_rtsp_out(struct libalias *la, struct ip *pip, struct alias_link *lnk, - char *data, + char *data, size_t maxlen, const char *port_str) { - int hlen, tlen, dlen; + size_t hlen, tlen, dlen; + size_t i, j; struct tcphdr *tc; - int i, j, pos, state, port_dlen, new_dlen, delta; + int delta, state; + ssize_t pos, slen; + size_t new_dlen, port_dlen, port_slen; u_short p[2], new_len; u_short sport, eport, base_port; u_short salias = 0, ealias = 0, base_alias = 0; const char *transport_str = "transport:"; - char newdata[2048], *port_data, *port_newdata, stemp[80]; - int links_created = 0, pkt_updated = 0; + char *newdata, *port_data; + bool links_created = false, pkt_updated = false; struct alias_link *rtsp_lnk = NULL; struct in_addr null_addr; @@ -250,6 +257,9 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, hlen = (pip->ip_hl + tc->th_off) << 2; tlen = ntohs(pip->ip_len); dlen = tlen - hlen; + if (hlen > tlen || tlen > maxlen) + return (-1); + port_slen = strlen(port_str); /* Find keyword, "Transport: " */ pos = search_string(data, dlen, transport_str); @@ -259,17 +269,21 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, port_data = data + pos; port_dlen = dlen - pos; + /* Allocate temporary buffer */ + maxlen -= hlen; + if ((newdata = malloc(maxlen)) == NULL) + return (-1); memcpy(newdata, data, pos); - port_newdata = newdata + pos; + new_dlen = pos; - while (port_dlen > (int)strlen(port_str)) { + while (port_dlen > port_slen) { /* Find keyword, appropriate port string */ pos = search_string(port_data, port_dlen, port_str); - if (pos < 0) + if (pos < 0 || (size_t)pos + 1 > maxlen - new_dlen) break; - memcpy(port_newdata, port_data, pos + 1); - port_newdata += (pos + 1); + memcpy(newdata + new_dlen, port_data, pos + 1); + new_dlen += pos + 1; p[0] = p[1] = 0; sport = eport = 0; @@ -300,7 +314,7 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, eport = htons(p[1]); if (!links_created) { - links_created = 1; + links_created = true; /* * Find an even numbered port * number base that satisfies the @@ -349,24 +363,30 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, ealias = htons(base_alias + (RTSP_PORT_GROUP - 1)); } if (salias && rtsp_lnk) { - pkt_updated = 1; + pkt_updated = true; /* Copy into IP packet */ - sprintf(stemp, "%d", ntohs(salias)); - memcpy(port_newdata, stemp, strlen(stemp)); - port_newdata += strlen(stemp); + slen = snprintf(newdata + new_dlen, + maxlen - new_dlen, "%d", ntohs(salias)); + if (slen < 0 || slen >= maxlen - new_dlen) + goto fail; + new_dlen += slen; if (eport != 0) { - *port_newdata = '-'; - port_newdata++; + if (new_dlen == maxlen) + goto fail; + newdata[new_dlen++] = '-'; /* Copy into IP packet */ - sprintf(stemp, "%d", ntohs(ealias)); - memcpy(port_newdata, stemp, strlen(stemp)); - port_newdata += strlen(stemp); + slen = snprintf(newdata + new_dlen, + maxlen - new_dlen, "%d", ntohs(ealias)); + if (slen < 0 || slen >= maxlen - new_dlen) + goto fail; + new_dlen += slen; } - *port_newdata = ';'; - port_newdata++; + if (new_dlen == maxlen) + goto fail; + newdata[new_dlen++] = ';'; } state++; break; @@ -380,20 +400,20 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, } if (!pkt_updated) - return (-1); - - memcpy(port_newdata, port_data, port_dlen); - port_newdata += port_dlen; - *port_newdata = '\0'; + goto fail; /* Create new packet */ - new_dlen = port_newdata - newdata; + if (new_dlen + port_dlen > maxlen) + goto fail; + memmove(data + new_dlen, port_data, port_dlen); memcpy(data, newdata, new_dlen); + new_dlen += port_dlen; + free(newdata); SetAckModified(lnk); tc = (struct tcphdr *)ip_next(pip); delta = GetDeltaSeqOut(tc->th_seq, lnk); - AddSeq(lnk, delta + new_dlen - dlen, pip->ip_hl, pip->ip_len, + AddSeq(lnk, delta + (int)(new_dlen - dlen), pip->ip_hl, pip->ip_len, tc->th_seq, tc->th_off); new_len = htons(hlen + new_dlen); @@ -407,6 +427,9 @@ alias_rtsp_out(struct libalias *la, struct ip *pip, tc->th_sum = TcpChecksum(pip); #endif return (0); +fail: + free(newdata); + return (-1); } /* Support the protocol used by early versions of RealPlayer */ @@ -415,13 +438,13 @@ static int alias_pna_out(struct libalias *la, struct ip *pip, struct alias_link *lnk, char *data, - int dlen) + size_t dlen) { struct alias_link *pna_links; - u_short msg_id, msg_len; char *work; - u_short alias_port, port; struct tcphdr *tc; + u_short msg_id, msg_len; + u_short alias_port, port; work = data; work += 5; @@ -433,7 +456,7 @@ alias_pna_out(struct libalias *la, struct ip *pip, if (ntohs(msg_id) == 0) /* end of options */ return (0); - if ((ntohs(msg_id) == 1) || (ntohs(msg_id) == 7)) { + if (ntohs(msg_id) == 1 || ntohs(msg_id) == 7) { memcpy(&port, work, 2); (void)FindUdpTcpOut(la, pip->ip_src, GetDestAddress(lnk), port, 0, IPPROTO_UDP, 1, &pna_links); @@ -462,22 +485,23 @@ alias_pna_out(struct libalias *la, struct ip *pip, } static void -AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, int maxpacketsize) +AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, + size_t maxlen) { - int hlen, tlen, dlen; struct tcphdr *tc; char *data; const char *setup = "SETUP", *pna = "PNA", *str200 = "200"; const char *okstr = "OK", *client_port_str = "client_port"; const char *server_port_str = "server_port"; - int i, parseOk; - - (void)maxpacketsize; + size_t hlen, tlen, dlen; + size_t i; tc = (struct tcphdr *)ip_next(pip); hlen = (pip->ip_hl + tc->th_off) << 2; tlen = ntohs(pip->ip_len); dlen = tlen - hlen; + if (hlen > tlen || tlen > maxlen) + return; data = (char *)pip; data += hlen; @@ -485,13 +509,14 @@ AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, /* When aliasing a client, check for the SETUP request */ if ((ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1) || (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2)) { - if (dlen >= (int)strlen(setup) && + if (dlen >= strlen(setup) && memcmp(data, setup, strlen(setup)) == 0) { - alias_rtsp_out(la, pip, lnk, data, client_port_str); + alias_rtsp_out(la, pip, lnk, data, maxlen, + client_port_str); return; } - if (dlen >= (int)strlen(pna) && + if (dlen >= strlen(pna) && memcmp(data, pna, strlen(pna)) == 0) alias_pna_out(la, pip, lnk, data, dlen); } else { @@ -499,24 +524,21 @@ AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, * When aliasing a server, check for the 200 reply * Accommodate varying number of blanks between 200 & OK */ - - if (dlen >= (int)strlen(str200)) { - for (parseOk = 0, i = 0; - i <= dlen - (int)strlen(str200); - i++) - if (memcmp(&data[i], str200, strlen(str200)) == 0) { - parseOk = 1; - break; - } - - if (parseOk) { - i += strlen(str200); /* skip string found */ - while (data[i] == ' ') /* skip blank(s) */ + if (dlen < strlen(str200) + 1 + strlen(okstr)) + return; + for (i = 0; i <= dlen - strlen(str200) - 1; i++) { + if (memcmp(&data[i], str200, strlen(str200)) == 0 && + data[i + strlen(str200)] == ' ') { + i += strlen(str200); /* skip 200 */ + while (i < dlen && data[i] == ' ') /* skip blank(s) */ i++; - - if ((dlen - i) >= (int)strlen(okstr)) - if (memcmp(&data[i], okstr, strlen(okstr)) == 0) - alias_rtsp_out(la, pip, lnk, data, server_port_str); + if (dlen - i >= strlen(okstr)) { + if (memcmp(&data[i], okstr, strlen(okstr)) == 0) { + alias_rtsp_out(la, pip, lnk, data, + maxlen, server_port_str); + break; + } + } } } }