mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michael Thalmeier <michael.thalmeier@hale.at>
To: Samuel Ortiz <sameo@linux.intel.com>,
	Lauro Ramos Venancio <lauro.venancio@openbossa.org>,
	Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
Cc: linux-kernel@vger.kernel.org, linux-nfc@ml01.01.org,
	michael@thalmeier.at
Subject: [RFC 2/4] NFC: pn533: fix deadlock when socket is closed while processing command
Date: Fri, 25 Mar 2016 15:46:52 +0100	[thread overview]
Message-ID: <1458917214-10693-3-git-send-email-michael.thalmeier@hale.at> (raw)
In-Reply-To: <1458917214-10693-1-git-send-email-michael.thalmeier@hale.at>

A deadlock can occur when the NFC raw socket is closed while the driver is
processing a command.

Following is the call graph of the affected situation:

send data via raw_sock:
-------------
rawsock_tx_work
  sock_hold                                             => socket refcnt++
  nfc_data_exchange                                     => cb = rawsock_data_exchange_complete
    ops->im_transceive = pn533_transceive               => arg->cb = db = rawsock_data_exchange_complete
      pn533_send_data_async                             => cb = pn533_data_exchange_complete
        __pn533_send_async                              => cmd->complete_cb = cb = pn533_data_exchange_complete
          if_ops->send_frame_async

response:
--------
pn533_recv_response
  queue_work(priv->wq, &priv->cmd_complete_work)

pn533_wq_cmd_complete
  pn533_send_async_complete
    cmd->complete_cb() = pn533_data_exchange_complete()
      arg->cb() = rawsock_data_exchange_complete()
        sock_put                                                         => socket refcnt-- => If the corresponding socket gets closed in the meantime socket will be destructed
          sk_free
            __sk_free
              sk->sk_destruct = rawsock_destruct
                nfc_deactivate_target
                  ops->deactivate_target = pn533_deactivate_target
                    pn533_send_cmd_sync
                      pn533_send_cmd_async
                        __pn533_send_async
                          list_add_tail(&cmd->queue, &dev->cmd_queue)    => add to command list because a command is currently processed
                        wait_for_completion                              => the workqueue thread waits here because it is the one processing the commands => deadlock

To fix the deadlock pn533_deactivate_target is changed to issue the
PN533_CMD_IN_RELEASE command in async mode. This way nothing blocks and the
release command is executed after the current command.

Signed-off-by: Michael Thalmeier <michael.thalmeier@hale.at>
---
 drivers/nfc/pn533.c | 40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index a85830f..074f1e4 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -2263,12 +2263,35 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev,
 	return 0;
 }
 
+static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg,
+			     struct sk_buff *resp)
+{
+	int rc = 0;
+
+	dev_dbg(&dev->interface->dev, "%s\n", __func__);
+
+	if (IS_ERR(resp)) {
+		rc = PTR_ERR(resp);
+
+		nfc_err(&dev->interface->dev, "Target release error %d\n", rc);
+
+		return rc;
+	}
+
+	rc = resp->data[0] & PN533_CMD_RET_MASK;
+	if (rc != PN533_CMD_RET_SUCCESS)
+		nfc_err(&dev->interface->dev,
+			"Error 0x%x when releasing the target\n", rc);
+
+	dev_kfree_skb(resp);
+	return rc;
+}
+
 static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
 				    struct nfc_target *target, u8 mode)
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
 	struct sk_buff *skb;
-	struct sk_buff *resp;
 	int rc;
 
 	dev_dbg(&dev->interface->dev, "%s\n", __func__);
@@ -2287,16 +2310,13 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
 
 	*skb_put(skb, 1) = 1; /* TG*/
 
-	resp = pn533_send_cmd_sync(dev, PN533_CMD_IN_RELEASE, skb);
-	if (IS_ERR(resp))
-		return;
-
-	rc = resp->data[0] & PN533_CMD_RET_MASK;
-	if (rc != PN533_CMD_RET_SUCCESS)
-		nfc_err(&dev->interface->dev,
-			"Error 0x%x when releasing the target\n", rc);
+	rc = pn533_send_cmd_async(dev, PN533_CMD_IN_RELEASE, skb,
+				  pn533_deactivate_target_complete, NULL);
+	if (rc < 0) {
+		dev_kfree_skb(skb);
+		nfc_err(&dev->interface->dev, "Target release error %d\n", rc);
+	}
 
-	dev_kfree_skb(resp);
 	return;
 }
 
-- 
2.5.5

  parent reply	other threads:[~2016-03-25 14:56 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-25 14:46 [RFC 0/4] NFC: pn533: support for pn532 via I2C Michael Thalmeier
2016-03-25 14:46 ` [RFC 1/4] NFC: pn533: Send ATR_REQ only if NFC_PROTO_NFC_DEP bit is set in poll_protocols Michael Thalmeier
2016-03-25 14:46 ` Michael Thalmeier [this message]
2016-03-25 14:46 ` [RFC 3/4] NFC: pn533: Separate pn533 driver in HW dependant and independant parts Michael Thalmeier
2016-03-25 14:46 ` [RFC 4/4] NFC: pn533: add I2C phy driver Michael Thalmeier
2016-04-09 21:45   ` Samuel Ortiz
2016-04-11 14:36     ` [PATCH] nfc: pn533: Add device tree documentation for i2c phy Michael Thalmeier
2016-05-01 21:36       ` Samuel Ortiz
2016-05-04 15:22   ` [RFC 4/4] NFC: pn533: add I2C phy driver Olliver Schinagl
2016-04-09 21:45 ` [RFC 0/4] NFC: pn533: support for pn532 via I2C Samuel Ortiz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1458917214-10693-3-git-send-email-michael.thalmeier@hale.at \
    --to=michael.thalmeier@hale.at \
    --cc=aloisio.almeida@openbossa.org \
    --cc=lauro.venancio@openbossa.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfc@ml01.01.org \
    --cc=michael@thalmeier.at \
    --cc=sameo@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®