aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Janc <szymon.janc@tieto.com>2011-11-16 03:32:18 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-11-16 15:28:37 -0500
commitaef89f214e4306153c7913b9854456595153f5d8 (patch)
tree9554255ce07c4dc773ef058cd4f56ed8ac51df0b
parent36acbb1adadf1ba300f14ee904a7d3f23120e0d6 (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.c20
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
3791static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) 3791static 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
3812static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) 3817static 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 }