Skip to content

Commit

Permalink
IPVS: fix potential stack overflow with overly long protocol names
Browse files Browse the repository at this point in the history
When protocols use very long names, the sprintf calls might overflow
the on-stack buffer. No protocol in the kernel does this however.

Print the protocol name in the pr_debug statement directly to avoid
this.

Based on patch by Zhitong Wang <zhitong.wangzt@alibaba-inc.com>
Acked-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>
  • Loading branch information
Patrick McHardy committed Apr 8, 2010
1 parent 02e4eb7 commit 3d91c1a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 24 deletions.
28 changes: 12 additions & 16 deletions net/netfilter/ipvs/ip_vs_proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,26 +166,24 @@ ip_vs_tcpudp_debug_packet_v4(struct ip_vs_protocol *pp,

ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
if (ih == NULL)
sprintf(buf, "%s TRUNCATED", pp->name);
sprintf(buf, "TRUNCATED");
else if (ih->frag_off & htons(IP_OFFSET))
sprintf(buf, "%s %pI4->%pI4 frag",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "%pI4->%pI4 frag", &ih->saddr, &ih->daddr);
else {
__be16 _ports[2], *pptr
;
pptr = skb_header_pointer(skb, offset + ih->ihl*4,
sizeof(_ports), _ports);
if (pptr == NULL)
sprintf(buf, "%s TRUNCATED %pI4->%pI4",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "TRUNCATED %pI4->%pI4",
&ih->saddr, &ih->daddr);
else
sprintf(buf, "%s %pI4:%u->%pI4:%u",
pp->name,
sprintf(buf, "%pI4:%u->%pI4:%u",
&ih->saddr, ntohs(pptr[0]),
&ih->daddr, ntohs(pptr[1]));
}

pr_debug("%s: %s\n", msg, buf);
pr_debug("%s: %s %s\n", msg, pp->name, buf);
}

#ifdef CONFIG_IP_VS_IPV6
Expand All @@ -200,26 +198,24 @@ ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,

ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
if (ih == NULL)
sprintf(buf, "%s TRUNCATED", pp->name);
sprintf(buf, "TRUNCATED");
else if (ih->nexthdr == IPPROTO_FRAGMENT)
sprintf(buf, "%s %pI6->%pI6 frag",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "%pI6->%pI6 frag", &ih->saddr, &ih->daddr);
else {
__be16 _ports[2], *pptr;

pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
sizeof(_ports), _ports);
if (pptr == NULL)
sprintf(buf, "%s TRUNCATED %pI6->%pI6",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "TRUNCATED %pI6->%pI6",
&ih->saddr, &ih->daddr);
else
sprintf(buf, "%s %pI6:%u->%pI6:%u",
pp->name,
sprintf(buf, "%pI6:%u->%pI6:%u",
&ih->saddr, ntohs(pptr[0]),
&ih->daddr, ntohs(pptr[1]));
}

pr_debug("%s: %s\n", msg, buf);
pr_debug("%s: %s %s\n", msg, pp->name, buf);
}
#endif

Expand Down
14 changes: 6 additions & 8 deletions net/netfilter/ipvs/ip_vs_proto_ah_esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,11 @@ ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb,

ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
if (ih == NULL)
sprintf(buf, "%s TRUNCATED", pp->name);
sprintf(buf, "TRUNCATED");
else
sprintf(buf, "%s %pI4->%pI4",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "%pI4->%pI4", &ih->saddr, &ih->daddr);

pr_debug("%s: %s\n", msg, buf);
pr_debug("%s: %s %s\n", msg, pp->name, buf);
}

#ifdef CONFIG_IP_VS_IPV6
Expand All @@ -154,12 +153,11 @@ ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb,

ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
if (ih == NULL)
sprintf(buf, "%s TRUNCATED", pp->name);
sprintf(buf, "TRUNCATED");
else
sprintf(buf, "%s %pI6->%pI6",
pp->name, &ih->saddr, &ih->daddr);
sprintf(buf, "%pI6->%pI6", &ih->saddr, &ih->daddr);

pr_debug("%s: %s\n", msg, buf);
pr_debug("%s: %s %s\n", msg, pp->name, buf);
}
#endif

Expand Down

0 comments on commit 3d91c1a

Please sign in to comment.