diff options
author | David S. Miller <davem@davemloft.net> | 2011-05-08 16:45:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-08 16:45:20 -0400 |
commit | 6af88da14ee284aaad6e4326da09a89191ab6165 (patch) | |
tree | bde47277368279454abff9a860be9292556c7089 /net/l2tp | |
parent | 2f16270f41e1499e23e6be25c51be87d950ffc91 (diff) |
l2tp: Fix locking in l2tp_core.c
l2tp_xmit_skb() must take the socket lock. It makes use of ip_queue_xmit()
which expects to execute in a socket atomic context.
Since we execute this function in software interrupts, we cannot use the
usual lock_sock()/release_sock() sequence, instead we have to use
bh_lock_sock() and see if a user has the socket locked, and if so drop
the packet.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp')
-rw-r--r-- | net/l2tp/l2tp_core.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c64ce0a0bb03..78530299ae38 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1060,6 +1060,12 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1060 | IPSKB_REROUTED); | 1060 | IPSKB_REROUTED); |
1061 | nf_reset(skb); | 1061 | nf_reset(skb); |
1062 | 1062 | ||
1063 | bh_lock_sock(sk); | ||
1064 | if (sock_owned_by_user(sk)) { | ||
1065 | dev_kfree_skb(skb); | ||
1066 | goto out_unlock; | ||
1067 | } | ||
1068 | |||
1063 | /* Get routing info from the tunnel socket */ | 1069 | /* Get routing info from the tunnel socket */ |
1064 | skb_dst_drop(skb); | 1070 | skb_dst_drop(skb); |
1065 | skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); | 1071 | skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); |
@@ -1106,6 +1112,8 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1106 | l2tp_skb_set_owner_w(skb, sk); | 1112 | l2tp_skb_set_owner_w(skb, sk); |
1107 | 1113 | ||
1108 | l2tp_xmit_core(session, skb, data_len); | 1114 | l2tp_xmit_core(session, skb, data_len); |
1115 | out_unlock: | ||
1116 | bh_unlock_sock(sk); | ||
1109 | 1117 | ||
1110 | abort: | 1118 | abort: |
1111 | return 0; | 1119 | return 0; |