diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 1dac28136e6a..e071cb15bce2 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -145,6 +145,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device, static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) { + struct nfc_dev *d; + + d = nfc_get_device(local->dev->idx); + if (!d) + return NULL; + kref_get(&local->ref); return local; @@ -180,6 +186,7 @@ int nfc_llcp_local_put(struct nfc_llcp_local *local) if (local == NULL) return 0; + nfc_put_device(local->dev); return kref_put(&local->ref, local_release); } @@ -959,8 +966,17 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, } new_sock = nfc_llcp_sock(new_sk); - new_sock->dev = local->dev; + new_sock->local = nfc_llcp_local_get(local); + if (!new_sock->local) { + reason = LLCP_DM_REJ; + release_sock(&sock->sk); + sock_put(&sock->sk); + sock_put(&new_sock->sk); + goto fail; + } + + new_sock->dev = local->dev; new_sock->rw = sock->rw; new_sock->miux = sock->miux; new_sock->nfc_protocol = sock->nfc_protocol; @@ -1597,7 +1613,11 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) if (local == NULL) return -ENOMEM; - local->dev = ndev; + /* Hold a reference to the device. */ + local->dev = nfc_get_device(ndev->idx); + if (!local->dev) + return -ENODEV; + INIT_LIST_HEAD(&local->list); kref_init(&local->ref); mutex_init(&local->sdp_lock);