Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aef89f21 authored by Szymon Janc's avatar Szymon Janc Committed by Gustavo Padovan
Browse files

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: default avatarSzymon Janc <szymon.janc@tieto.com>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 36acbb1a
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -3788,7 +3788,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq)
	}
}

static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
{
	struct srej_list *new;
	u32 control;
@@ -3799,6 +3799,9 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq)
		l2cap_send_sframe(chan, control);

		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
		if (!new)
			return -ENOMEM;

		new->tx_seq = chan->expected_tx_seq;

		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)
	}

	chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq);

	return 0;
}

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
					return 0;
				}
			}
			l2cap_send_srejframe(chan, tx_seq);

			err = l2cap_send_srejframe(chan, tx_seq);
			if (err < 0) {
				l2cap_send_disconn_req(chan->conn, chan, -err);
				return err;
			}
		}
	} else {
		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

		set_bit(CONN_SEND_PBIT, &chan->conn_state);

		l2cap_send_srejframe(chan, tx_seq);
		err = l2cap_send_srejframe(chan, tx_seq);
		if (err < 0) {
			l2cap_send_disconn_req(chan->conn, chan, -err);
			return err;
		}

		__clear_ack_timer(chan);
	}