Commit f9bcdcec authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Pablo Neira Ayuso says:

====================
Netfilter fixes for net

1) Set on IPS_CONFIRMED before change_status() otherwise EBUSY is
   bogusly hit. This bug was introduced in the 6.3 release cycle.

2) Fix nfnetlink_queue conntrack support: Set/dump timeout
   accordingly for unconfirmed conntrack entries. Make sure this
   is done after IPS_CONFIRMED is set on. This is an old bug, it
   happens since the introduction of this feature.

* tag 'nf-23-04-21' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  netfilter: conntrack: fix wrong ct->timeout value
  netfilter: conntrack: restore IPS_CONFIRMED out of nf_conntrack_hash_check_insert()
====================

Link: https://lore.kernel.org/r/20230421105700.325438-1-pablo@netfilter.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e375b503 73db1b8f
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -89,7 +89,11 @@ static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
{
	if (timeout > INT_MAX)
		timeout = INT_MAX;

	if (nf_ct_is_confirmed(ct))
		WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout);
	else
		ct->timeout = (u32)timeout;
}

int __nf_ct_change_timeout(struct nf_conn *ct, u64 cta_timeout);
+1 −0
Original line number Diff line number Diff line
@@ -381,6 +381,7 @@ __bpf_kfunc struct nf_conn *bpf_ct_insert_entry(struct nf_conn___init *nfct_i)
	struct nf_conn *nfct = (struct nf_conn *)nfct_i;
	int err;

	nfct->status |= IPS_CONFIRMED;
	err = nf_conntrack_hash_check_insert(nfct);
	if (err < 0) {
		nf_conntrack_free(nfct);
+0 −1
Original line number Diff line number Diff line
@@ -932,7 +932,6 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
		goto out;
	}

	ct->status |= IPS_CONFIRMED;
	smp_wmb();
	/* The caller holds a reference to this object */
	refcount_set(&ct->ct_general.use, 2);
+12 −4
Original line number Diff line number Diff line
@@ -176,7 +176,12 @@ static int ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
static int ctnetlink_dump_timeout(struct sk_buff *skb, const struct nf_conn *ct,
				  bool skip_zero)
{
	long timeout = nf_ct_expires(ct) / HZ;
	long timeout;

	if (nf_ct_is_confirmed(ct))
		timeout = nf_ct_expires(ct) / HZ;
	else
		timeout = ct->timeout / HZ;

	if (skip_zero && timeout == 0)
		return 0;
@@ -2253,9 +2258,6 @@ ctnetlink_create_conntrack(struct net *net,
	if (!cda[CTA_TIMEOUT])
		goto err1;

	timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
	__nf_ct_set_timeout(ct, timeout);

	rcu_read_lock();
 	if (cda[CTA_HELP]) {
		char *helpname = NULL;
@@ -2316,6 +2318,12 @@ ctnetlink_create_conntrack(struct net *net,
	nfct_seqadj_ext_add(ct);
	nfct_synproxy_ext_add(ct);

	/* we must add conntrack extensions before confirmation. */
	ct->status |= IPS_CONFIRMED;

	timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ;
	__nf_ct_set_timeout(ct, timeout);

	if (cda[CTA_STATUS]) {
		err = ctnetlink_change_status(ct, cda);
		if (err < 0)