* [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).