Commit 9aba6c5b authored by Peilin Ye's avatar Peilin Ye Committed by David S. Miller
Browse files

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: 9dd7f890 ("openvswitch: Add original direction conntrack tuple to sw_flow_key.")
Suggested-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarPeilin Ye <yepeilin.cs@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 038ebb1a
Loading
Loading
Loading
Loading
+20 −18
Original line number Diff line number Diff line
@@ -276,10 +276,6 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
	ovs_ct_update_key(skb, NULL, key, false, false);
}

#define IN6_ADDR_INITIALIZER(ADDR) \
	{ (ADDR).s6_addr32[0], (ADDR).s6_addr32[1], \
	  (ADDR).s6_addr32[2], (ADDR).s6_addr32[3] }

int ovs_ct_put_key(const struct sw_flow_key *swkey,
		   const struct sw_flow_key *output, struct sk_buff *skb)
{
@@ -301,24 +297,30 @@ int ovs_ct_put_key(const struct sw_flow_key *swkey,

	if (swkey->ct_orig_proto) {
		if (swkey->eth.type == htons(ETH_P_IP)) {
			struct ovs_key_ct_tuple_ipv4 orig = {
				output->ipv4.ct_orig.src,
				output->ipv4.ct_orig.dst,
				output->ct.orig_tp.src,
				output->ct.orig_tp.dst,
				output->ct_orig_proto,
			};
			struct ovs_key_ct_tuple_ipv4 orig;

			memset(&orig, 0, sizeof(orig));
			orig.ipv4_src = output->ipv4.ct_orig.src;
			orig.ipv4_dst = output->ipv4.ct_orig.dst;
			orig.src_port = output->ct.orig_tp.src;
			orig.dst_port = output->ct.orig_tp.dst;
			orig.ipv4_proto = output->ct_orig_proto;

			if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
				    sizeof(orig), &orig))
				return -EMSGSIZE;
		} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
			struct ovs_key_ct_tuple_ipv6 orig = {
				IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.src),
				IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.dst),
				output->ct.orig_tp.src,
				output->ct.orig_tp.dst,
				output->ct_orig_proto,
			};
			struct ovs_key_ct_tuple_ipv6 orig;

			memset(&orig, 0, sizeof(orig));
			memcpy(orig.ipv6_src, output->ipv6.ct_orig.src.s6_addr32,
			       sizeof(orig.ipv6_src));
			memcpy(orig.ipv6_dst, output->ipv6.ct_orig.dst.s6_addr32,
			       sizeof(orig.ipv6_dst));
			orig.src_port = output->ct.orig_tp.src;
			orig.dst_port = output->ct.orig_tp.dst;
			orig.ipv6_proto = output->ct_orig_proto;

			if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
				    sizeof(orig), &orig))
				return -EMSGSIZE;