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

Commit 916f6efa authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: never get/set skb->tstamp



setting net.netfilter.nf_conntrack_timestamp=1 breaks xmit with fq
scheduler.  skb->tstamp might be "refreshed" using ktime_get_real(),
but fq expects CLOCK_MONOTONIC.

This patch removes all places in netfilter that check/set skb->tstamp:

1. To fix the bogus "start" time seen with conntrack timestamping for
   outgoing packets, never use skb->tstamp and always use current time.
2. In nfqueue and nflog, only use skb->tstamp for incoming packets,
   as determined by current hook (prerouting, input, forward).
3. xt_time has to use system clock as well rather than skb->tstamp.
   We could still use skb->tstamp for prerouting/input/foward, but
   I see no advantage to make this conditional.

Fixes: fb420d5d ("tcp/fq: move back to CLOCK_MONOTONIC")
Cc: Eric Dumazet <edumazet@google.com>
Reported-by: default avatarMichal Soltys <soltys@ziu.info>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 7caa56f0
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -1017,12 +1017,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)

	/* set conntrack timestamp, if enabled. */
	tstamp = nf_conn_tstamp_find(ct);
	if (tstamp) {
		if (skb->tstamp == 0)
			__net_timestamp(skb);
	if (tstamp)
		tstamp->start = ktime_get_real_ns();

		tstamp->start = ktime_to_ns(skb->tstamp);
	}
	/* Since the lookup is lockless, hash insertion must be done after
	 * starting the timer and setting the CONFIRMED bit. The RCU barriers
	 * guarantee that no other CPU can find the conntrack before the above
+1 −1
Original line number Diff line number Diff line
@@ -540,7 +540,7 @@ __build_packet_message(struct nfnl_log_net *log,
			goto nla_put_failure;
	}

	if (skb->tstamp) {
	if (hooknum <= NF_INET_FORWARD && skb->tstamp) {
		struct nfulnl_msg_packet_timestamp ts;
		struct timespec64 kts = ktime_to_timespec64(skb->tstamp);
		ts.sec = cpu_to_be64(kts.tv_sec);
+1 −1
Original line number Diff line number Diff line
@@ -582,7 +582,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
	if (nfqnl_put_bridge(entry, skb) < 0)
		goto nla_put_failure;

	if (entskb->tstamp) {
	if (entry->state.hook <= NF_INET_FORWARD && entskb->tstamp) {
		struct nfqnl_msg_packet_timestamp ts;
		struct timespec64 kts = ktime_to_timespec64(entskb->tstamp);

+14 −9
Original line number Diff line number Diff line
@@ -163,19 +163,24 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
	s64 stamp;

	/*
	 * We cannot use get_seconds() instead of __net_timestamp() here.
	 * We need real time here, but we can neither use skb->tstamp
	 * nor __net_timestamp().
	 *
	 * skb->tstamp and skb->skb_mstamp_ns overlap, however, they
	 * use different clock types (real vs monotonic).
	 *
	 * Suppose you have two rules:
	 *	1. match before 13:00
	 *	2. match after 13:00
	 *
	 * If you match against processing time (get_seconds) it
	 * may happen that the same packet matches both rules if
	 * it arrived at the right moment before 13:00.
	 * it arrived at the right moment before 13:00, so it would be
	 * better to check skb->tstamp and set it via __net_timestamp()
	 * if needed.  This however breaks outgoing packets tx timestamp,
	 * and causes them to get delayed forever by fq packet scheduler.
	 */
	if (skb->tstamp == 0)
		__net_timestamp((struct sk_buff *)skb);

	stamp = ktime_to_ns(skb->tstamp);
	stamp = div_s64(stamp, NSEC_PER_SEC);
	stamp = get_seconds();

	if (info->flags & XT_TIME_LOCAL_TZ)
		/* Adjust for local timezone */