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

Commit 2df01200 authored by David Herrmann's avatar David Herrmann Committed by Gustavo Padovan
Browse files

Bluetooth: hidp: handle kernel_sendmsg() errors correctly



We shouldn't push back the skbs if kernel_sendmsg() fails. Instead, we
terminate the connection and drop the skb. Only on EAGAIN we push it back
and return.
l2cap doesn't return EAGAIN, yet, but this guarantees we're safe if it
will at some time in the future.

Signed-off-by: default avatarDavid Herrmann <dh.herrmann@gmail.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo.padovan@collabora.co.uk>
parent 5205185d
Loading
Loading
Loading
Loading
+14 −2
Original line number Original line Diff line number Diff line
@@ -639,13 +639,19 @@ static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
static void hidp_process_intr_transmit(struct hidp_session *session)
static void hidp_process_intr_transmit(struct hidp_session *session)
{
{
	struct sk_buff *skb;
	struct sk_buff *skb;
	int ret;


	BT_DBG("session %p", session);
	BT_DBG("session %p", session);


	while ((skb = skb_dequeue(&session->intr_transmit))) {
	while ((skb = skb_dequeue(&session->intr_transmit))) {
		if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
		ret = hidp_send_frame(session->intr_sock, skb->data, skb->len);
		if (ret == -EAGAIN) {
			skb_queue_head(&session->intr_transmit, skb);
			skb_queue_head(&session->intr_transmit, skb);
			break;
			break;
		} else if (ret < 0) {
			hidp_session_terminate(session);
			kfree_skb(skb);
			break;
		}
		}


		hidp_set_timer(session);
		hidp_set_timer(session);
@@ -656,13 +662,19 @@ static void hidp_process_intr_transmit(struct hidp_session *session)
static void hidp_process_ctrl_transmit(struct hidp_session *session)
static void hidp_process_ctrl_transmit(struct hidp_session *session)
{
{
	struct sk_buff *skb;
	struct sk_buff *skb;
	int ret;


	BT_DBG("session %p", session);
	BT_DBG("session %p", session);


	while ((skb = skb_dequeue(&session->ctrl_transmit))) {
	while ((skb = skb_dequeue(&session->ctrl_transmit))) {
		if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
		ret = hidp_send_frame(session->ctrl_sock, skb->data, skb->len);
		if (ret == -EAGAIN) {
			skb_queue_head(&session->ctrl_transmit, skb);
			skb_queue_head(&session->ctrl_transmit, skb);
			break;
			break;
		} else if (ret < 0) {
			hidp_session_terminate(session);
			kfree_skb(skb);
			break;
		}
		}


		hidp_set_timer(session);
		hidp_set_timer(session);