Re: [PATCH v2 5/6] platform/x86: intel_tdx_attest: Add TDX Guest attestation interface driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Hans,

On 4/4/22 3:07 AM, Hans de Goede wrote:
+static int __init tdx_attest_init(void)
+{
+	dma_addr_t handle;
+	long ret = 0;
+
+	mutex_lock(&attestation_lock);
+
+	ret = misc_register(&tdx_attest_device);
+	if (ret) {
+		pr_err("misc device registration failed\n");
+		mutex_unlock(&attestation_lock);
+		return ret;
+	}
Why not do this as the last thing of the probe?

We need misc device reference in dma_alloc_coherent() and
dma_set_coherent_mask() calls. This is the reason for keeping
misc_register() at the beginining of the init function.


That will avoid the need to unregister this again in all
the error-exit paths and also fixes a possible deadlock.


Agree. But, unless we create another device locally, I don't
think we can avoid this. Do you prefer this approach?

Right now you possibly have:

1. probe() locks attestation_lock
2. probe() registers misc-device
3. userspace calls tdx_attest_ioctl
4. tdx_attest_ioctl blocks waiting for attestastion_lock
5. Something goes wrong in probe, probe calls
    misc_deregister()
6. misc_deregister waits for the ioctl to finish
7. deadlock

I'm not sure about 6, but if 6 does not happen then
instead we now have tdx_attest_ioctl running
after the misc_deregister, with tdquote_data and
tdreport_data as NULL, or pointing to free-ed memory
leading to various crash scenarios.

Makes sense. But as I have mentioned above, we have reason
for keeping the misc_register() at the begining of the
init function.

One way to avoid this deadlock is to use global initalization
check.

--- a/drivers/platform/x86/intel/tdx/intel_tdx_attest.c
+++ b/drivers/platform/x86/intel/tdx/intel_tdx_attest.c
@@ -48,6 +48,8 @@ static void *tdreport_data;
 /* DMA handle used to allocate and free tdquote DMA buffer */
 dma_addr_t tdquote_dma_handle;

+static bool device_initialized;
+
 static void attestation_callback_handler(void)
 {
        complete(&attestation_done);
@@ -60,6 +62,9 @@ static long tdx_attest_ioctl(struct file *file, unsigned int cmd,
        struct tdx_gen_quote tdquote_req;
        long ret = 0;

+       if (!device_initialized)
+               return -ENODEV;
+
        mutex_lock(&attestation_lock);

        switch (cmd) {
@@ -191,6 +196,8 @@ static int __init tdx_attest_init(void)

        mutex_unlock(&attestation_lock);

+       device_initialized = true;
+
        pr_debug("module initialization success\n");

        return 0;

Please let me know your comment on above solution.


TL;DR: you must always delay registering any
interfaces for userspace until your code is
ready to deal with userspace calls.

Regards,

Hans

p.s.

As I mentioned with v1:



--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer



[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux