diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2011-11-16 03:32:18 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-11-16 15:28:37 -0500 |
commit | aef89f214e4306153c7913b9854456595153f5d8 (patch) | |
tree | 9554255ce07c4dc773ef058cd4f56ed8ac51df0b | |
parent | 36acbb1adadf1ba300f14ee904a7d3f23120e0d6 (diff) |
Bluetooth: Fix possible NULL pointer derefence in l2cap code
Due to ERTM reliability L2CAP channel needs to be disconnected if
adding to srej list failed.
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | net/bluetooth/l2cap_core.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 1790ce3230bb..276817a90f59 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -3788,7 +3788,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) | |||
3788 | } | 3788 | } |
3789 | } | 3789 | } |
3790 | 3790 | ||
3791 | static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | 3791 | static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) |
3792 | { | 3792 | { |
3793 | struct srej_list *new; | 3793 | struct srej_list *new; |
3794 | u32 control; | 3794 | u32 control; |
@@ -3799,6 +3799,9 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | |||
3799 | l2cap_send_sframe(chan, control); | 3799 | l2cap_send_sframe(chan, control); |
3800 | 3800 | ||
3801 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); | 3801 | new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); |
3802 | if (!new) | ||
3803 | return -ENOMEM; | ||
3804 | |||
3802 | new->tx_seq = chan->expected_tx_seq; | 3805 | new->tx_seq = chan->expected_tx_seq; |
3803 | 3806 | ||
3804 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 3807 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); |
@@ -3807,6 +3810,8 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) | |||
3807 | } | 3810 | } |
3808 | 3811 | ||
3809 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); | 3812 | chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); |
3813 | |||
3814 | return 0; | ||
3810 | } | 3815 | } |
3811 | 3816 | ||
3812 | static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) | 3817 | static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) |
@@ -3877,7 +3882,12 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont | |||
3877 | return 0; | 3882 | return 0; |
3878 | } | 3883 | } |
3879 | } | 3884 | } |
3880 | l2cap_send_srejframe(chan, tx_seq); | 3885 | |
3886 | err = l2cap_send_srejframe(chan, tx_seq); | ||
3887 | if (err < 0) { | ||
3888 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
3889 | return err; | ||
3890 | } | ||
3881 | } | 3891 | } |
3882 | } else { | 3892 | } else { |
3883 | expected_tx_seq_offset = __seq_offset(chan, | 3893 | expected_tx_seq_offset = __seq_offset(chan, |
@@ -3899,7 +3909,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont | |||
3899 | 3909 | ||
3900 | set_bit(CONN_SEND_PBIT, &chan->conn_state); | 3910 | set_bit(CONN_SEND_PBIT, &chan->conn_state); |
3901 | 3911 | ||
3902 | l2cap_send_srejframe(chan, tx_seq); | 3912 | err = l2cap_send_srejframe(chan, tx_seq); |
3913 | if (err < 0) { | ||
3914 | l2cap_send_disconn_req(chan->conn, chan, -err); | ||
3915 | return err; | ||
3916 | } | ||
3903 | 3917 | ||
3904 | __clear_ack_timer(chan); | 3918 | __clear_ack_timer(chan); |
3905 | } | 3919 | } |