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

openvswitch: Prevent kernel-infoleak in ovs_ct_put_key()

ovs_ct_put_key() is potentially copying uninitialized kernel stack memory
into socket buffers, since the compiler may leave a 3-byte hole at the end
of `struct ovs_key_ct_tuple_ipv4` and `struct ovs_key_ct_tuple_ipv6`. Fix
it by initializing `orig` with memset().

Fixes: 9dd7f8907c37 ("openvswitch: Add original direction conntrack tuple to sw_flow_key.")
Suggested-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Peilin Ye <yepeilin.cs@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Peilin Ye and committed by
David S. Miller
9aba6c5b 038ebb1a

+20 -18
+20 -18
net/openvswitch/conntrack.c
··· 276 276 ovs_ct_update_key(skb, NULL, key, false, false); 277 277 } 278 278 279 - #define IN6_ADDR_INITIALIZER(ADDR) \ 280 - { (ADDR).s6_addr32[0], (ADDR).s6_addr32[1], \ 281 - (ADDR).s6_addr32[2], (ADDR).s6_addr32[3] } 282 - 283 279 int ovs_ct_put_key(const struct sw_flow_key *swkey, 284 280 const struct sw_flow_key *output, struct sk_buff *skb) 285 281 { ··· 297 301 298 302 if (swkey->ct_orig_proto) { 299 303 if (swkey->eth.type == htons(ETH_P_IP)) { 300 - struct ovs_key_ct_tuple_ipv4 orig = { 301 - output->ipv4.ct_orig.src, 302 - output->ipv4.ct_orig.dst, 303 - output->ct.orig_tp.src, 304 - output->ct.orig_tp.dst, 305 - output->ct_orig_proto, 306 - }; 304 + struct ovs_key_ct_tuple_ipv4 orig; 305 + 306 + memset(&orig, 0, sizeof(orig)); 307 + orig.ipv4_src = output->ipv4.ct_orig.src; 308 + orig.ipv4_dst = output->ipv4.ct_orig.dst; 309 + orig.src_port = output->ct.orig_tp.src; 310 + orig.dst_port = output->ct.orig_tp.dst; 311 + orig.ipv4_proto = output->ct_orig_proto; 312 + 307 313 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4, 308 314 sizeof(orig), &orig)) 309 315 return -EMSGSIZE; 310 316 } else if (swkey->eth.type == htons(ETH_P_IPV6)) { 311 - struct ovs_key_ct_tuple_ipv6 orig = { 312 - IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.src), 313 - IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.dst), 314 - output->ct.orig_tp.src, 315 - output->ct.orig_tp.dst, 316 - output->ct_orig_proto, 317 - }; 317 + struct ovs_key_ct_tuple_ipv6 orig; 318 + 319 + memset(&orig, 0, sizeof(orig)); 320 + memcpy(orig.ipv6_src, output->ipv6.ct_orig.src.s6_addr32, 321 + sizeof(orig.ipv6_src)); 322 + memcpy(orig.ipv6_dst, output->ipv6.ct_orig.dst.s6_addr32, 323 + sizeof(orig.ipv6_dst)); 324 + orig.src_port = output->ct.orig_tp.src; 325 + orig.dst_port = output->ct.orig_tp.dst; 326 + orig.ipv6_proto = output->ct_orig_proto; 327 + 318 328 if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6, 319 329 sizeof(orig), &orig)) 320 330 return -EMSGSIZE;