aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-04-06 20:28:48 +0200
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-04-17 03:03:59 -0300
commit2df012001d36e56cd92dab0255cf4bce3f5b16bc (patch)
tree2257b013b811f00187fbbeb9f8ea223b6a9f2ac4
parent5205185d461d5902325e457ca80bd421127b7308 (diff)
downloadbluetooth-next-2df012001d36e56cd92dab0255cf4bce3f5b16bc.tar.gz
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: David Herrmann <dh.herrmann@gmail.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r--net/bluetooth/hidp/core.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 481bbb8c7220a..3f6ef0630a8e6 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -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)
{
struct sk_buff *skb;
+ int ret;
BT_DBG("session %p", session);
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);
break;
+ } else if (ret < 0) {
+ hidp_session_terminate(session);
+ kfree_skb(skb);
+ break;
}
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)
{
struct sk_buff *skb;
+ int ret;
BT_DBG("session %p", session);
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);
break;
+ } else if (ret < 0) {
+ hidp_session_terminate(session);
+ kfree_skb(skb);
+ break;
}
hidp_set_timer(session);