Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

netfilter: conntrack: remove sprintf usage

Replace it with scnprintf, the buffer sizes are expected to be large enough
to hold the result, no need for snprintf+overflow check.

Increase buffer size in mangle_content_len() while at it.

BUG: KASAN: stack-out-of-bounds in vsnprintf+0xea5/0x1270
Write of size 1 at addr [..]
vsnprintf+0xea5/0x1270
sprintf+0xb1/0xe0
mangle_content_len+0x1ac/0x280
nf_nat_sdp_session+0x1cc/0x240
process_sdp+0x8f8/0xb80
process_invite_request+0x108/0x2b0
process_sip_msg+0x5da/0xf50
sip_help_tcp+0x45e/0x780
nf_confirm+0x34d/0x990
[..]

Fixes: 9fafcd7b2032 ("[NETFILTER]: nf_conntrack/nf_nat: add SIP helper port")
Reported-by: Yiming Qian <yimingqian591@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
6e7066bd 2195574d

+19 -16
+1 -1
net/netfilter/nf_nat_amanda.c
··· 50 50 return NF_DROP; 51 51 } 52 52 53 - sprintf(buffer, "%u", port); 53 + snprintf(buffer, sizeof(buffer), "%u", port); 54 54 if (!nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, 55 55 protoff, matchoff, matchlen, 56 56 buffer, strlen(buffer))) {
+18 -15
net/netfilter/nf_nat_sip.c
··· 68 68 } 69 69 70 70 static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer, 71 + size_t size, 71 72 const union nf_inet_addr *addr, bool delim) 72 73 { 73 74 if (nf_ct_l3num(ct) == NFPROTO_IPV4) 74 - return sprintf(buffer, "%pI4", &addr->ip); 75 + return scnprintf(buffer, size, "%pI4", &addr->ip); 75 76 else { 76 77 if (delim) 77 - return sprintf(buffer, "[%pI6c]", &addr->ip6); 78 + return scnprintf(buffer, size, "[%pI6c]", &addr->ip6); 78 79 else 79 - return sprintf(buffer, "%pI6c", &addr->ip6); 80 + return scnprintf(buffer, size, "%pI6c", &addr->ip6); 80 81 } 81 82 } 82 83 83 84 static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer, 85 + size_t size, 84 86 const union nf_inet_addr *addr, u16 port) 85 87 { 86 88 if (nf_ct_l3num(ct) == NFPROTO_IPV4) 87 - return sprintf(buffer, "%pI4:%u", &addr->ip, port); 89 + return scnprintf(buffer, size, "%pI4:%u", &addr->ip, port); 88 90 else 89 - return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port); 91 + return scnprintf(buffer, size, "[%pI6c]:%u", &addr->ip6, port); 90 92 } 91 93 92 94 static int map_addr(struct sk_buff *skb, unsigned int protoff, ··· 121 119 if (nf_inet_addr_cmp(&newaddr, addr) && newport == port) 122 120 return 1; 123 121 124 - buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport)); 122 + buflen = sip_sprintf_addr_port(ct, buffer, sizeof(buffer), &newaddr, ntohs(newport)); 125 123 return mangle_packet(skb, protoff, dataoff, dptr, datalen, 126 124 matchoff, matchlen, buffer, buflen); 127 125 } ··· 214 212 &addr, true) > 0 && 215 213 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) && 216 214 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) { 217 - buflen = sip_sprintf_addr(ct, buffer, 215 + buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), 218 216 &ct->tuplehash[!dir].tuple.dst.u3, 219 217 true); 220 218 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, ··· 231 229 &addr, false) > 0 && 232 230 nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) && 233 231 !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) { 234 - buflen = sip_sprintf_addr(ct, buffer, 232 + buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), 235 233 &ct->tuplehash[!dir].tuple.src.u3, 236 234 false); 237 235 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, ··· 249 247 htons(n) == ct->tuplehash[dir].tuple.dst.u.udp.port && 250 248 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { 251 249 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; 252 - buflen = sprintf(buffer, "%u", ntohs(p)); 250 + buflen = scnprintf(buffer, sizeof(buffer), "%u", ntohs(p)); 253 251 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 254 252 poff, plen, buffer, buflen)) { 255 253 nf_ct_helper_log(skb, ct, "cannot mangle rport"); ··· 420 418 421 419 if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || 422 420 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { 423 - buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); 421 + buflen = sip_sprintf_addr_port(ct, buffer, sizeof(buffer), 422 + &newaddr, port); 424 423 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 425 424 matchoff, matchlen, buffer, buflen)) { 426 425 nf_ct_helper_log(skb, ct, "cannot mangle packet"); ··· 441 438 { 442 439 enum ip_conntrack_info ctinfo; 443 440 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 441 + char buffer[sizeof("4294967295")]; 444 442 unsigned int matchoff, matchlen; 445 - char buffer[sizeof("65536")]; 446 443 int buflen, c_len; 447 444 448 445 /* Get actual SDP length */ ··· 457 454 &matchoff, &matchlen) <= 0) 458 455 return 0; 459 456 460 - buflen = sprintf(buffer, "%u", c_len); 457 + buflen = scnprintf(buffer, sizeof(buffer), "%u", c_len); 461 458 return mangle_packet(skb, protoff, dataoff, dptr, datalen, 462 459 matchoff, matchlen, buffer, buflen); 463 460 } ··· 494 491 char buffer[INET6_ADDRSTRLEN]; 495 492 unsigned int buflen; 496 493 497 - buflen = sip_sprintf_addr(ct, buffer, addr, false); 494 + buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), addr, false); 498 495 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, 499 496 sdpoff, type, term, buffer, buflen)) 500 497 return 0; ··· 512 509 char buffer[sizeof("nnnnn")]; 513 510 unsigned int buflen; 514 511 515 - buflen = sprintf(buffer, "%u", port); 512 + buflen = scnprintf(buffer, sizeof(buffer), "%u", port); 516 513 if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, 517 514 matchoff, matchlen, buffer, buflen)) 518 515 return 0; ··· 532 529 unsigned int buflen; 533 530 534 531 /* Mangle session description owner and contact addresses */ 535 - buflen = sip_sprintf_addr(ct, buffer, addr, false); 532 + buflen = sip_sprintf_addr(ct, buffer, sizeof(buffer), addr, false); 536 533 if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff, 537 534 SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen)) 538 535 return 0;