Commit 7e039984 authored by Xin Long's avatar Xin Long Committed by Pablo Neira Ayuso
Browse files

netfilter: nft_tunnel: add the missing nla_nest_cancel()



When nla_put_xxx() fails under nla_nest_start_noflag(),
nla_nest_cancel() should be called, so that the skb can
be trimmed properly.

Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 73239bd9
Loading
Loading
Loading
Loading
+26 −12
Original line number Diff line number Diff line
@@ -443,10 +443,15 @@ static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info)
		if (!nest)
			return -1;

		if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC, &info->key.u.ipv6.src) < 0 ||
		    nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST, &info->key.u.ipv6.dst) < 0 ||
		    nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL, info->key.label))
		if (nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_SRC,
				     &info->key.u.ipv6.src) < 0 ||
		    nla_put_in6_addr(skb, NFTA_TUNNEL_KEY_IP6_DST,
				     &info->key.u.ipv6.dst) < 0 ||
		    nla_put_be32(skb, NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
				 info->key.label)) {
			nla_nest_cancel(skb, nest);
			return -1;
		}

		nla_nest_end(skb, nest);
	} else {
@@ -454,9 +459,13 @@ static int nft_tunnel_ip_dump(struct sk_buff *skb, struct ip_tunnel_info *info)
		if (!nest)
			return -1;

		if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC, info->key.u.ipv4.src) < 0 ||
		    nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST, info->key.u.ipv4.dst) < 0)
		if (nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_SRC,
				    info->key.u.ipv4.src) < 0 ||
		    nla_put_in_addr(skb, NFTA_TUNNEL_KEY_IP_DST,
				    info->key.u.ipv4.dst) < 0) {
			nla_nest_cancel(skb, nest);
			return -1;
		}

		nla_nest_end(skb, nest);
	}
@@ -477,37 +486,42 @@ static int nft_tunnel_opts_dump(struct sk_buff *skb,
	if (opts->flags & TUNNEL_VXLAN_OPT) {
		inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_VXLAN);
		if (!inner)
			return -1;
			goto failure;
		if (nla_put_be32(skb, NFTA_TUNNEL_KEY_VXLAN_GBP,
				 htonl(opts->u.vxlan.gbp)))
			return -1;
			goto inner_failure;
		nla_nest_end(skb, inner);
	} else if (opts->flags & TUNNEL_ERSPAN_OPT) {
		inner = nla_nest_start_noflag(skb, NFTA_TUNNEL_KEY_OPTS_ERSPAN);
		if (!inner)
			return -1;
			goto failure;
		if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_VERSION,
				 htonl(opts->u.erspan.version)))
			return -1;
			goto inner_failure;
		switch (opts->u.erspan.version) {
		case ERSPAN_VERSION:
			if (nla_put_be32(skb, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
					 opts->u.erspan.u.index))
				return -1;
				goto inner_failure;
			break;
		case ERSPAN_VERSION2:
			if (nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
				       get_hwid(&opts->u.erspan.u.md2)) ||
			    nla_put_u8(skb, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
				       opts->u.erspan.u.md2.dir))
				return -1;
				goto inner_failure;
			break;
		}
		nla_nest_end(skb, inner);
	}
	nla_nest_end(skb, nest);

	return 0;

inner_failure:
	nla_nest_cancel(skb, inner);
failure:
	nla_nest_cancel(skb, nest);
	return -1;
}

static int nft_tunnel_ports_dump(struct sk_buff *skb,