In h4_recv(), if h4_recv_buf() returns error and h4_recv() is
asynchronously called again before setting rx_skb to NULL, ERR_PTR will
be dereferenced in h4_recv_buf(). Check return value in a local variable
before writing to rx_skb.

Reported-by: [email protected]
Signed-off-by: Myungho Jung <[email protected]>
---
 drivers/bluetooth/hci_h4.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index fb97a3bf069b..fa30ec9cebd4 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -124,19 +124,22 @@ static const struct h4_recv_pkt h4_recv_pkts[] = {
 static int h4_recv(struct hci_uart *hu, const void *data, int count)
 {
        struct h4_struct *h4 = hu->priv;
+       struct sk_buff *skb;
 
        if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
                return -EUNATCH;
 
-       h4->rx_skb = h4_recv_buf(hu->hdev, h4->rx_skb, data, count,
-                                h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
-       if (IS_ERR(h4->rx_skb)) {
-               int err = PTR_ERR(h4->rx_skb);
+       skb = h4_recv_buf(hu->hdev, h4->rx_skb, data, count,
+                         h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
+       if (IS_ERR(skb)) {
+               int err = PTR_ERR(skb);
                bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
                h4->rx_skb = NULL;
                return err;
        }
 
+       h4->rx_skb = skb;
+
        return count;
 }
 
-- 
2.17.1

Reply via email to