Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd58bcd9 authored by Jan Engelhardt's avatar Jan Engelhardt Committed by Patrick McHardy
Browse files

netfilter: xt_TEE: have cloned packet travel through Xtables too



Since Xtables is now reentrant/nestable, the cloned packet can also go
through Xtables and be subject to rules itself.

Signed-off-by: default avatarJan Engelhardt <jengelh@medozas.de>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent f3c5c1bf
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -309,7 +309,6 @@ int ip_output(struct sk_buff *skb)
			    ip_finish_output,
			    !(IPCB(skb)->flags & IPSKB_REROUTED));
}
EXPORT_SYMBOL_GPL(ip_output);

int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
{
+0 −1
Original line number Diff line number Diff line
@@ -176,7 +176,6 @@ int ip6_output(struct sk_buff *skb)
			    ip6_finish_output,
			    !(IP6CB(skb)->flags & IP6SKB_REROUTED));
}
EXPORT_SYMBOL_GPL(ip6_output);

/*
 *	xmit an sk_buff (used by TCP)
+18 −22
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */
#include <linux/ip.h>
#include <linux/module.h>
#include <linux/percpu.h>
#include <linux/route.h>
#include <linux/skbuff.h>
#include <net/checksum.h>
@@ -32,6 +33,7 @@
#endif

static const union nf_inet_addr tee_zero_address;
static DEFINE_PER_CPU(bool, tee_active);

static struct net *pick_net(struct sk_buff *skb)
{
@@ -91,6 +93,8 @@ tee_tg4(struct sk_buff *skb, const struct xt_target_param *par)
	const struct xt_tee_tginfo *info = par->targinfo;
	struct iphdr *iph;

	if (percpu_read(tee_active))
		return XT_CONTINUE;
	/*
	 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for
	 * the original skb, which should continue on its way as if nothing has
@@ -125,24 +129,13 @@ tee_tg4(struct sk_buff *skb, const struct xt_target_param *par)
		--iph->ttl;
	ip_send_check(iph);

	/*
	 * Xtables is not reentrant currently, so a choice has to be made:
	 * 1. return absolute verdict for the original and let the cloned
	 *    packet travel through the chains
	 * 2. let the original continue travelling and not pass the clone
	 *    to Xtables.
	 * #2 is chosen. Normally, we would use ip_local_out for the clone.
	 * Because iph->check is already correct and we don't pass it to
	 * Xtables anyway, a shortcut to dst_output [forwards to ip_output] can
	 * be taken. %IPSKB_REROUTED needs to be set so that ip_output does not
	 * invoke POSTROUTING on the cloned packet.
	 */
	IPCB(skb)->flags |= IPSKB_REROUTED;
	if (tee_tg_route4(skb, info))
		ip_output(skb);
	else
	if (tee_tg_route4(skb, info)) {
		percpu_write(tee_active, true);
		ip_local_out(skb);
		percpu_write(tee_active, false);
	} else {
		kfree_skb(skb);

	}
	return XT_CONTINUE;
}

@@ -177,6 +170,8 @@ tee_tg6(struct sk_buff *skb, const struct xt_target_param *par)
{
	const struct xt_tee_tginfo *info = par->targinfo;

	if (percpu_read(tee_active))
		return XT_CONTINUE;
	skb = pskb_copy(skb, GFP_ATOMIC);
	if (skb == NULL)
		return XT_CONTINUE;
@@ -192,12 +187,13 @@ tee_tg6(struct sk_buff *skb, const struct xt_target_param *par)
		struct ipv6hdr *iph = ipv6_hdr(skb);
		--iph->hop_limit;
	}
	IP6CB(skb)->flags |= IP6SKB_REROUTED;
	if (tee_tg_route6(skb, info))
		ip6_output(skb);
	else
	if (tee_tg_route6(skb, info)) {
		percpu_write(tee_active, true);
		ip6_local_out(skb);
		percpu_write(tee_active, false);
	} else {
		kfree_skb(skb);

	}
	return XT_CONTINUE;
}
#endif /* WITH_IPV6 */