Skip to contentSkip to conversation

: Netfilter fixes

PATCH Applied Patrick McHardy 2 participants 7 messages Nov 13, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover : Netfilter fixes

Hi Dave,

these three patches fix a nf_nat memset error, leading to misbehaviour when unloading and reloading the NAT module, a regression from the bridge netfilter deferred hook removal causing double invocation of the POSTROUTING hook for packets forwarded between two bridge devices and consolidate the nf_sockopt code. I'll push the memset and bridge fixes to -stable once they hit Linus' tree.

Please apply, thanks.

 net/bridge/br_netfilter.c        |    3 +
 net/ipv4/netfilter/nf_nat_core.c |    2 +-
 net/netfilter/nf_sockopt.c       |  106 ++++++++++++++++----------------------
 3 files changed, 48 insertions(+), 63 deletions(-)

Li Zefan (1):
[NETFILTER]: nf_nat: fix memset error

Patrick McHardy (1):
[NETFILTER]: bridge: fix double POSTROUTING hook invocation

Pavel Emelyanov (1):
[NETFILTER]: Consolidate nf_sockopt and compat_nf_sockopt

#1 lore raw

PATCH 1/3 : nf_nat: fix memset error

[NETFILTER]: nf_nat: fix memset error

The size passing to memset is the size of a pointer.

---
commit dd9e04a6e68abf79470ef26e242ce516bba37b3d
tree 0d6b56e83d643661a9726931a577d6626a2cfb3f
parent 325d22df7b19e0116aff3391d3a03f73d0634ded
author Li Zefan <[email protected]> Tue, 13 Nov 2007 11:24:16 +0100 committer Patrick McHardy <[email protected]> Tue, 13 Nov 2007 11:24:16 +0100

 net/ipv4/netfilter/nf_nat_core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv4/netfilter/nf_nat_core.c +1 -1
index 56e93f6..70e7997 100644
@@ -681,7 +681,7 @@ static int clean_nat(struct nf_conn *i, void *data)
 
 	if (!nat)
 		return 0;
-	memset(nat, 0, sizeof(nat));
+	memset(nat, 0, sizeof(*nat));
 	i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
 	return 0;
 }
#3 lore raw

PATCH 2/3 : Consolidate nf_sockopt and compat_nf_sockopt

In reply to Patrick McHardy

[NETFILTER]: Consolidate nf_sockopt and compat_nf_sockopt

Both lookup the nf_sockopt_ops object to call the get/set callbacks from, but they perform it in a completely similar way.

Introduce the helper for finding the ops.

---
commit c94ac2cb9896fbed3065dc08216a7d13b98f0d92
tree 2e4bd21d850cef9bbc53be588dc7590636232a4b
parent dd9e04a6e68abf79470ef26e242ce516bba37b3d
author Pavel Emelyanov <[email protected]> Tue, 13 Nov 2007 11:24:17 +0100 committer Patrick McHardy <[email protected]> Tue, 13 Nov 2007 11:24:17 +0100

 net/netfilter/nf_sockopt.c |  106 ++++++++++++++++++--------------------------
 1 files changed, 44 insertions(+), 62 deletions(-)
net/netfilter/nf_sockopt.c +44 -62
index 2dfac32..87bc144 100644
@@ -60,46 +60,57 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
 }
 EXPORT_SYMBOL(nf_unregister_sockopt);
 
-/* Call get/setsockopt() */
-static int nf_sockopt(struct sock *sk, int pf, int val,
-		      char __user *opt, int *len, int get)
+static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, int pf,
+		int val, int get)
 {
 	struct nf_sockopt_ops *ops;
-	int ret;
 
 	if (sk->sk_net != &init_net)
-		return -ENOPROTOOPT;
+		return ERR_PTR(-ENOPROTOOPT);
 
 	if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
-		return -EINTR;
+		return ERR_PTR(-EINTR);
 
 	list_for_each_entry(ops, &nf_sockopts, list) {
 		if (ops->pf == pf) {
 			if (!try_module_get(ops->owner))
 				goto out_nosup;
+
 			if (get) {
-				if (val >= ops->get_optmin
-				    && val < ops->get_optmax) {
-					mutex_unlock(&nf_sockopt_mutex);
-					ret = ops->get(sk, val, opt, len);
+				if (val >= ops->get_optmin &&
+						val < ops->get_optmax)
 					goto out;
-				}
 			} else {
-				if (val >= ops->set_optmin
-				    && val < ops->set_optmax) {
-					mutex_unlock(&nf_sockopt_mutex);
-					ret = ops->set(sk, val, opt, *len);
+				if (val >= ops->set_optmin &&
+						val < ops->set_optmax)
 					goto out;
-				}
 			}
 			module_put(ops->owner);
 		}
 	}
- out_nosup:
+out_nosup:
+	ops = ERR_PTR(-ENOPROTOOPT);
+out:
 	mutex_unlock(&nf_sockopt_mutex);
-	return -ENOPROTOOPT;
+	return ops;
+}
+
+/* Call get/setsockopt() */
+static int nf_sockopt(struct sock *sk, int pf, int val,
+		      char __user *opt, int *len, int get)
+{
+	struct nf_sockopt_ops *ops;
+	int ret;
+
+	ops = nf_sockopt_find(sk, pf, val, get);
+	if (IS_ERR(ops))
+		return PTR_ERR(ops);
+
+	if (get)
+		ret = ops->get(sk, val, opt, len);
+	else
+		ret = ops->set(sk, val, opt, *len);
 
- out:
 	module_put(ops->owner);
 	return ret;
 }
@@ -124,51 +135,22 @@ static int compat_nf_sockopt(struct sock *sk, int pf, int val,
 	struct nf_sockopt_ops *ops;
 	int ret;
 
-	if (sk->sk_net != &init_net)
-		return -ENOPROTOOPT;
-
-
-	if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0)
-		return -EINTR;
-
-	list_for_each_entry(ops, &nf_sockopts, list) {
-		if (ops->pf == pf) {
-			if (!try_module_get(ops->owner))
-				goto out_nosup;
-
-			if (get) {
-				if (val >= ops->get_optmin
-				    && val < ops->get_optmax) {
-					mutex_unlock(&nf_sockopt_mutex);
-					if (ops->compat_get)
-						ret = ops->compat_get(sk,
-							val, opt, len);
-					else
-						ret = ops->get(sk,
-							val, opt, len);
-					goto out;
-				}
-			} else {
-				if (val >= ops->set_optmin
-				    && val < ops->set_optmax) {
-					mutex_unlock(&nf_sockopt_mutex);
-					if (ops->compat_set)
-						ret = ops->compat_set(sk,
-							val, opt, *len);
-					else
-						ret = ops->set(sk,
-							val, opt, *len);
-					goto out;
-				}
-			}
-			module_put(ops->owner);
-		}
+	ops = nf_sockopt_find(sk, pf, val, get);
+	if (IS_ERR(ops))
+		return PTR_ERR(ops);
+
+	if (get) {
+		if (ops->compat_get)
+			ret = ops->compat_get(sk, val, opt, len);
+		else
+			ret = ops->get(sk, val, ops, len);
+	} else {
+		if (ops->compat_set)
+			ret = ops->compat_set(sk, val, ops, *len);
+		else
+			ret = ops->set(sk, val, ops, *len);
 	}
- out_nosup:
-	mutex_unlock(&nf_sockopt_mutex);
-	return -ENOPROTOOPT;
 
- out:
 	module_put(ops->owner);
 	return ret;
 }
maintainer Applied
#4 lore raw

Re: [NETFILTER 02/03]: Consolidate nf_sockopt and compat_nf_sockopt

From: Patrick McHardy <[email protected]>
Date: Tue, 13 Nov 2007 11:55:42 +0100 (MET)

Quoted 9 lines

[NETFILTER]: Consolidate nf_sockopt and compat_nf_sockopt

Both lookup the nf_sockopt_ops object to call the get/set callbacks from, but they perform it in a completely similar way.

Introduce the helper for finding the ops.

Applied.

#5 lore raw

PATCH 3/3 : bridge: fix double POSTROUTING hook invocation

In reply to Patrick McHardy

[NETFILTER]: bridge: fix double POSTROUTING hook invocation

Packets routed between bridges have the POST_ROUTING hook invoked twice since bridging mistakes them for bridged packets because they have skb->nf_bridge set.

---
commit 87a1cd0a4fc1f5ac17e2e752668ae324c595b1fd
tree 38c7fdb13f7232bf77fb78ce4292a4bb1cdd5dfd
parent c94ac2cb9896fbed3065dc08216a7d13b98f0d92
author Patrick McHardy <[email protected]> Tue, 13 Nov 2007 11:24:18 +0100 committer Patrick McHardy <[email protected]> Tue, 13 Nov 2007 11:24:18 +0100

 net/bridge/br_netfilter.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
net/bridge/br_netfilter.c +3 -0
index da22f90..c1757c7 100644
@@ -766,6 +766,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb,
 	if (!nf_bridge)
 		return NF_ACCEPT;
 
+	if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT)))
+		return NF_ACCEPT;
+
 	if (!realoutdev)
 		return NF_DROP;
 
maintainer
#6 lore raw

Re: [NETFILTER 03/03]: bridge: fix double POSTROUTING hook invocation

From: Patrick McHardy <[email protected]>
Date: Tue, 13 Nov 2007 11:55:44 +0100 (MET)

Quoted 7 lines

[NETFILTER]: bridge: fix double POSTROUTING hook invocation

Packets routed between bridges have the POST_ROUTING hook invoked twice since bridging mistakes them for bridged packets because they have skb->nf_bridge set.

Also applied, thanks Patrick.