tpm: vtpm_proxy: conditionally call tpm_chip_unregister
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>
Sat, 19 Nov 2016 18:32:55 +0000 (11:32 -0700)
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Sun, 27 Nov 2016 23:31:33 +0000 (01:31 +0200)
If tpm_chip_register fails vtpm must not call tpm_chip_unregister:

> [   58.271017]  [<ffffffff8155bd32>] dpm_sysfs_remove+0x22/0x60
> [   58.271017]  [<ffffffff8154e438>] device_del+0x58/0x280
> [   58.271017]  [<ffffffffa024c020>] tpm_chip_unregister+0x40/0xb0 [tpm]
> [   58.271017]  [<ffffffffa0292360>] vtpm_proxy_fops_release+0x40/0x60 [tpm_vtpm_proxy]

[jarkko.sakkinen@linux.intel.com: cleaned up unneeded goto away]

Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
drivers/char/tpm/tpm_vtpm_proxy.c

index 3d6f6ca..5463b58 100644 (file)
@@ -42,6 +42,7 @@ struct proxy_dev {
        long state;                  /* internal state */
 #define STATE_OPENED_FLAG        BIT(0)
 #define STATE_WAIT_RESPONSE_FLAG BIT(1)  /* waiting for emulator response */
+#define STATE_REGISTERED_FLAG   BIT(2)
 
        size_t req_len;              /* length of queued TPM request */
        size_t resp_len;             /* length of queued TPM response */
@@ -370,12 +371,9 @@ static void vtpm_proxy_work(struct work_struct *work)
 
        rc = tpm_chip_register(proxy_dev->chip);
        if (rc)
-               goto err;
-
-       return;
-
-err:
-       vtpm_proxy_fops_undo_open(proxy_dev);
+               vtpm_proxy_fops_undo_open(proxy_dev);
+       else
+               proxy_dev->state |= STATE_REGISTERED_FLAG;
 }
 
 /*
@@ -516,7 +514,8 @@ static void vtpm_proxy_delete_device(struct proxy_dev *proxy_dev)
         */
        vtpm_proxy_fops_undo_open(proxy_dev);
 
-       tpm_chip_unregister(proxy_dev->chip);
+       if (proxy_dev->state & STATE_REGISTERED_FLAG)
+               tpm_chip_unregister(proxy_dev->chip);
 
        vtpm_proxy_delete_proxy_dev(proxy_dev);
 }