netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 0/3] llc2 station handler fixes
@ 2012-08-13 12:48 Ben Hutchings
  2012-08-13 12:49 ` [PATCH net 1/3] llc2: Fix silent failure of llc_station_init() Ben Hutchings
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Ben Hutchings @ 2012-08-13 12:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

I was insprired by commit 91d27a8650d5359a7a320daeb35b88cdea15e3a8
('llc: free the right skb') to look into llc_station.c, and didn't like
what I saw.

These are *only* compile tested; hopefully you have some way to test
LLC.

Ben.

Ben Hutchings (3):
  llc2: Fix silent failure of llc_station_init()
  llc2: Call llc_station_exit() on llc2_init() failure path
  llc: Fix races between llc2 handler use and (un)registration

 include/net/llc.h     |    2 +-
 net/llc/af_llc.c      |    5 +++--
 net/llc/llc_input.c   |   21 +++++++++++++++++----
 net/llc/llc_station.c |   21 +++------------------
 4 files changed, 24 insertions(+), 25 deletions(-)



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH net 1/3] llc2: Fix silent failure of llc_station_init()
  2012-08-13 12:48 [PATCH net 0/3] llc2 station handler fixes Ben Hutchings
@ 2012-08-13 12:49 ` Ben Hutchings
  2012-08-14 23:52   ` David Miller
  2012-08-13 12:50 ` [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path Ben Hutchings
  2012-08-13 12:50 ` [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration Ben Hutchings
  2 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2012-08-13 12:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 2284 bytes --]

llc_station_init() creates and processes an event skb with no effect
other than to change the state from DOWN to UP.  Allocation failure is
reported, but then ignored by its caller, llc2_init().  Remove this
possibility by simply initialising the state as UP.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 include/net/llc.h     |    2 +-
 net/llc/llc_station.c |   19 ++-----------------
 2 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/include/net/llc.h b/include/net/llc.h
index 226c846..f2d0fc5 100644
--- a/include/net/llc.h
+++ b/include/net/llc.h
@@ -133,7 +133,7 @@ extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
 extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
 extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
 
-extern int llc_station_init(void);
+extern void llc_station_init(void);
 extern void llc_station_exit(void);
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index 6828e39..45ddbb9 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -687,12 +687,8 @@ static void llc_station_rcv(struct sk_buff *skb)
 	llc_station_state_process(skb);
 }
 
-int __init llc_station_init(void)
+void __init llc_station_init(void)
 {
-	int rc = -ENOBUFS;
-	struct sk_buff *skb;
-	struct llc_station_state_ev *ev;
-
 	skb_queue_head_init(&llc_main_station.mac_pdu_q);
 	skb_queue_head_init(&llc_main_station.ev_q.list);
 	spin_lock_init(&llc_main_station.ev_q.lock);
@@ -700,20 +696,9 @@ int __init llc_station_init(void)
 			(unsigned long)&llc_main_station);
 	llc_main_station.ack_timer.expires  = jiffies +
 						sysctl_llc_station_ack_timeout;
-	skb = alloc_skb(0, GFP_ATOMIC);
-	if (!skb)
-		goto out;
-	rc = 0;
 	llc_set_station_handler(llc_station_rcv);
-	ev = llc_station_ev(skb);
-	memset(ev, 0, sizeof(*ev));
 	llc_main_station.maximum_retry	= 1;
-	llc_main_station.state		= LLC_STATION_STATE_DOWN;
-	ev->type	= LLC_STATION_EV_TYPE_SIMPLE;
-	ev->prim_type	= LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
-	rc = llc_station_next_state(skb);
-out:
-	return rc;
+	llc_main_station.state		= LLC_STATION_STATE_UP;
 }
 
 void __exit llc_station_exit(void)



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path
  2012-08-13 12:48 [PATCH net 0/3] llc2 station handler fixes Ben Hutchings
  2012-08-13 12:49 ` [PATCH net 1/3] llc2: Fix silent failure of llc_station_init() Ben Hutchings
@ 2012-08-13 12:50 ` Ben Hutchings
  2012-08-14 23:52   ` David Miller
  2012-08-13 12:50 ` [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration Ben Hutchings
  2 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2012-08-13 12:50 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 811 bytes --]

Otherwise the station packet handler will remain registered even though
the module is unloaded.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/llc/af_llc.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index f6fe4d4..8c2919c 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -1206,7 +1206,7 @@ static int __init llc2_init(void)
 	rc = llc_proc_init();
 	if (rc != 0) {
 		printk(llc_proc_err_msg);
-		goto out_unregister_llc_proto;
+		goto out_station;
 	}
 	rc = llc_sysctl_init();
 	if (rc) {
@@ -1226,7 +1226,8 @@ out_sysctl:
 	llc_sysctl_exit();
 out_proc:
 	llc_proc_exit();
-out_unregister_llc_proto:
+out_station:
+	llc_station_exit();
 	proto_unregister(&llc_proto);
 	goto out;
 }



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration
  2012-08-13 12:48 [PATCH net 0/3] llc2 station handler fixes Ben Hutchings
  2012-08-13 12:49 ` [PATCH net 1/3] llc2: Fix silent failure of llc_station_init() Ben Hutchings
  2012-08-13 12:50 ` [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path Ben Hutchings
@ 2012-08-13 12:50 ` Ben Hutchings
  2012-08-14 23:52   ` David Miller
  2 siblings, 1 reply; 8+ messages in thread
From: Ben Hutchings @ 2012-08-13 12:50 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 3199 bytes --]

When registering the handlers, any state they rely on must be
completely initialised first.  When unregistering, we must wait until
they are definitely no longer running.  llc_rcv() must also avoid
reading the handler pointers again after checking for NULL.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 net/llc/llc_input.c   |   21 +++++++++++++++++----
 net/llc/llc_station.c |    2 +-
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index e32cab4..dd3e833 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -42,6 +42,7 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap,
 void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
 					    struct sk_buff *skb))
 {
+	smp_wmb(); /* ensure initialisation is complete before it's called */
 	if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
 		llc_type_handlers[type - 1] = handler;
 }
@@ -50,11 +51,19 @@ void llc_remove_pack(int type)
 {
 	if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
 		llc_type_handlers[type - 1] = NULL;
+	synchronize_net();
 }
 
 void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
 {
+	/* Ensure initialisation is complete before it's called */
+	if (handler)
+		smp_wmb();
+
 	llc_station_handler = handler;
+
+	if (!handler)
+		synchronize_net();
 }
 
 /**
@@ -150,6 +159,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 	int dest;
 	int (*rcv)(struct sk_buff *, struct net_device *,
 		   struct packet_type *, struct net_device *);
+	void (*sta_handler)(struct sk_buff *skb);
+	void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
 
 	if (!net_eq(dev_net(dev), &init_net))
 		goto drop;
@@ -182,7 +193,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 	 */
 	rcv = rcu_dereference(sap->rcv_func);
 	dest = llc_pdu_type(skb);
-	if (unlikely(!dest || !llc_type_handlers[dest - 1])) {
+	sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL;
+	if (unlikely(!sap_handler)) {
 		if (rcv)
 			rcv(skb, dev, pt, orig_dev);
 		else
@@ -193,7 +205,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 			if (cskb)
 				rcv(cskb, dev, pt, orig_dev);
 		}
-		llc_type_handlers[dest - 1](sap, skb);
+		sap_handler(sap, skb);
 	}
 	llc_sap_put(sap);
 out:
@@ -202,9 +214,10 @@ drop:
 	kfree_skb(skb);
 	goto out;
 handle_station:
-	if (!llc_station_handler)
+	sta_handler = ACCESS_ONCE(llc_station_handler);
+	if (!sta_handler)
 		goto drop;
-	llc_station_handler(skb);
+	sta_handler(skb);
 	goto out;
 }
 
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
index 45ddbb9..81da71a 100644
--- a/net/llc/llc_station.c
+++ b/net/llc/llc_station.c
@@ -696,9 +696,9 @@ void __init llc_station_init(void)
 			(unsigned long)&llc_main_station);
 	llc_main_station.ack_timer.expires  = jiffies +
 						sysctl_llc_station_ack_timeout;
-	llc_set_station_handler(llc_station_rcv);
 	llc_main_station.maximum_retry	= 1;
 	llc_main_station.state		= LLC_STATION_STATE_UP;
+	llc_set_station_handler(llc_station_rcv);
 }
 
 void __exit llc_station_exit(void)


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH net 1/3] llc2: Fix silent failure of llc_station_init()
  2012-08-13 12:49 ` [PATCH net 1/3] llc2: Fix silent failure of llc_station_init() Ben Hutchings
@ 2012-08-14 23:52   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-08-14 23:52 UTC (permalink / raw)
  To: ben; +Cc: acme, netdev

From: Ben Hutchings <ben@decadent.org.uk>
Date: Mon, 13 Aug 2012 13:49:59 +0100

> llc_station_init() creates and processes an event skb with no effect
> other than to change the state from DOWN to UP.  Allocation failure is
> reported, but then ignored by its caller, llc2_init().  Remove this
> possibility by simply initialising the state as UP.
> 
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

Applied.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path
  2012-08-13 12:50 ` [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path Ben Hutchings
@ 2012-08-14 23:52   ` David Miller
  2012-08-15  4:06     ` Ben Hutchings
  0 siblings, 1 reply; 8+ messages in thread
From: David Miller @ 2012-08-14 23:52 UTC (permalink / raw)
  To: ben; +Cc: acme, netdev

From: Ben Hutchings <ben@decadent.org.uk>
Date: Mon, 13 Aug 2012 13:50:43 +0100

> Otherwise the station packet handler will remain registered even though
> the module is unloaded.
> 
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

This will cause section mismatch errors, you'll need to remove
the __exit tag from llc_station_exit() if you want to start
invoking it from llc2_init() which is __init.

I took care of this when applying this patch to 'net'.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration
  2012-08-13 12:50 ` [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration Ben Hutchings
@ 2012-08-14 23:52   ` David Miller
  0 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2012-08-14 23:52 UTC (permalink / raw)
  To: ben; +Cc: acme, netdev

From: Ben Hutchings <ben@decadent.org.uk>
Date: Mon, 13 Aug 2012 13:50:55 +0100

> When registering the handlers, any state they rely on must be
> completely initialised first.  When unregistering, we must wait until
> they are definitely no longer running.  llc_rcv() must also avoid
> reading the handler pointers again after checking for NULL.
> 
> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>

Applied.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path
  2012-08-14 23:52   ` David Miller
@ 2012-08-15  4:06     ` Ben Hutchings
  0 siblings, 0 replies; 8+ messages in thread
From: Ben Hutchings @ 2012-08-15  4:06 UTC (permalink / raw)
  To: David Miller; +Cc: acme, netdev

[-- Attachment #1: Type: text/plain, Size: 844 bytes --]

On Tue, 2012-08-14 at 16:52 -0700, David Miller wrote:
> From: Ben Hutchings <ben@decadent.org.uk>
> Date: Mon, 13 Aug 2012 13:50:43 +0100
> 
> > Otherwise the station packet handler will remain registered even though
> > the module is unloaded.
> > 
> > Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
> 
> This will cause section mismatch errors, you'll need to remove
> the __exit tag from llc_station_exit() if you want to start
> invoking it from llc2_init() which is __init.
> 
> I took care of this when applying this patch to 'net'.

Thanks, David.

llc_station.c turns out to be mostly dead code, and I have some more
radical changes to remove that which I'll send after you next merge net
into net-next.

Ben.

-- 
Ben Hutchings
I say we take off; nuke the site from orbit.  It's the only way to be sure.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-08-15  4:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-13 12:48 [PATCH net 0/3] llc2 station handler fixes Ben Hutchings
2012-08-13 12:49 ` [PATCH net 1/3] llc2: Fix silent failure of llc_station_init() Ben Hutchings
2012-08-14 23:52   ` David Miller
2012-08-13 12:50 ` [PATCH net 2/3] llc2: Call llc_station_exit() on llc2_init() failure path Ben Hutchings
2012-08-14 23:52   ` David Miller
2012-08-15  4:06     ` Ben Hutchings
2012-08-13 12:50 ` [PATCH net 3/3] llc: Fix races between llc2 handler use and (un)registration Ben Hutchings
2012-08-14 23:52   ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).