linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sathyanarayanan Kuppuswamy  <sathyanarayanan.kuppuswamy@linux.intel.com>
To: Dave Hansen <dave.hansen@intel.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	x86@kernel.org
Cc: "H . Peter Anvin" <hpa@zytor.com>,
	"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
	Tony Luck <tony.luck@intel.com>, Andi Kleen <ak@linux.intel.com>,
	Kai Huang <kai.huang@intel.com>,
	Wander Lairson Costa <wander@redhat.com>,
	Isaku Yamahata <isaku.yamahata@gmail.com>,
	marcelo.cerri@canonical.com, tim.gardner@canonical.com,
	khalid.elmously@canonical.com, philip.cox@canonical.com,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v8 1/5] x86/tdx: Add TDX Guest attestation interface driver
Date: Thu, 30 Jun 2022 16:50:47 -0700	[thread overview]
Message-ID: <ca73d2bd-5d40-d385-aeb0-8c04811690ff@linux.intel.com> (raw)
In-Reply-To: <f26f88ee-1226-3e32-77cc-fc86bc65e0b7@intel.com>

Hi,

On 6/27/22 10:24 AM, Dave Hansen wrote:
> On 6/27/22 07:50, Sathyanarayanan Kuppuswamy wrote:

>>> Second, how can someone test this code?  It appears that they need to
>>> assemble a veritable Rube Goldberg machine.  The least we could do is
>>> have a selftest that just calls the ioctl() and makes sure that
>>> something halfway sane comes out of it.
>>
>> My initial submission included a test app. But I removed it later to
>> reduce the review load. I thought to submit the test app once feature
>> support patches are merged.
>>
>> https://lore.kernel.org/all/9247fade9db5ae6eb183b2f92fdedb898282376a.1648664666.git.sathyanarayanan.kuppuswamy@intel.com/
>>
>> If you prefer, I can add it back to the next submission with the latest changes.
> 
> I doubt anyone will ever run a "test app".  Why not just make this a
> selftest?

Fine with me. I can change it into selftest.

> 
>>>> In such
>>>> case, since REPORTDATA is a secret, using sysfs to share it is insecure
>>>> compared to sending it via IOCTL.
>>>
>>> Huh?  How is sysfs "insecure"?
>>
>> REPORTDATA (input) we pass to the Module call might come from attestation
>> service as a per session unique ID.  If it is shared via sysfs, there is
>> a possibility for untrusted software to read it and trigger some form of
>> reply attack. So in this context, sysfs is insecure compared to IOCTL
>> approach. You can find the related discussion in,
>>
>> https://lore.kernel.org/lkml/b8eadd3079101a2cf93ee87d36dbedf93d8a2725.camel@intel.com/
> 
> I still don't get it.
> 
> How is a 400 sysfs file "insecure"?  This sounds "if the filesystem
> permissions are broken" paranoia.  In other words, you're protecting
> against a malicious root user.

AFAIK, root is not the only user of the attestation interface. General users can
also use it (For example, in a use case like pytorch, attestation may be requested
by server before passing the training data). So if the permission is not "root
only", then other users or application in TD can access the sysfs file to read
its contents. 

Also, the security concern mentioned is just an additional point. Following are
the main reasons for choosing IOCTL over sysfs.

1. Sysfs is generally used for config purposes. Not for request/response kind of
   use case (Attestation falls under this category).
2. If we only use sysfs model for GetReport, the design might look like below: 

    /sys/kernel/../report/input
    /sys/kernel/../report/subtype
    /sys/kernel/../report/input_len
    /sys/kernel/../report/output
    /sys/kernel/../report/output_len
    /sys/kernel/../report/status
    /sys/kernel/../report/trigger

We might need similar files for GetQuote use case as well. IMO, such a design is 
more complicated than using IOCTL.

> 
> In other words, I don't think the ABI here has been well thought out.
> 
> Also, this is basically a:
> 
> 	Inputs:
> 
> 		* nonce
> 		* report type
> 
> 	Outputs:
> 
> 		* report
> 
> I have to wonder how hard it would be to have this be:
> 
> 	fd = open("/dev/foo");
> 	ioctl(fd, REPORT, type, flags??);
> 	write(fd, &inputs, inputs_len);
> 	read(fd,  &output, outputs_len);
> 

It is not hard to implement it this way. But I don't see it being
very different from just using IOCTL. config/{read/write} model is
usually preferred for applications in which you have a requirement to do
multiple read/writes after one time config (use cases like serial
port read, printer write or reading temperature, etc). But in our case
we will mostly use it once after every config. 

Also, splitting input over IOCTL and write system call will require us
to add additional code to store the state.

I have attempted a sample implementation (untested) for reference. But I
feel our current code is simpler. It handles allocation and input/output
validation in one place compared to spreading it across multiple handlers. 

struct report_req {
        int subtype;
        void *reportdata;
        int reportdata_len;
};

struct tdx_attest_req {
        unsigned int cmd;
        void *data;
};


static long tdx_attest_ioctl(struct file *file, unsigned int cmd,
                             unsigned long arg)
{
        void __user *argp = (void __user *)arg;
        struct tdx_attest_req *areq = file->private_data;
        struct report_req *rep_data = NULL;
        struct tdx_report_req user_req;
        long ret = -EINVAL;

        switch (cmd) {
        case TDX_CMD_GET_REPORT:
                /* Allocate space for TDREPORT request */
                rep_data = kmalloc(sizeof(struct report_req), GFP_KERNEL);
                if (!rep_data)
                        return -ENOMEM;

                /* Copy user request data */
                if (copy_from_user(&user_req, argp, sizeof(user_req))) {
                        kfree(rep_data);
                        return -EFAULT;
                }

                /* Copy user request details to areq->data */
                rep_data->subtype = user_req.subtype;
                areq->cmd = cmd;
                areq->data = rep_data;

                ret = 0;
                break;
        default:
                pr_debug("cmd %d not supported\n", cmd);
                break;
        }

        return ret;
}

static ssize_t tdx_attest_read(struct file *filp, char __user *buffer,
                                size_t length, loff_t *offset)
{
        struct tdx_attest_req *areq = filp->private_data;
        struct report_req *rep_data;
        void *tdreport;
        long ret;

        if (!areq)
                return -EINVAL;

        switch (areq->cmd) {
        case TDX_CMD_GET_REPORT:

                /* Check for valid length and offset */
                if (length != TDX_REPORT_LEN || offset != 0)
                        return -EINVAL;

                rep_data = areq->data;

                /* Make sure we have valid reportdata */
                if (!rep_data->reportdata)
                        return -EINVAL;

                /* Allocate space for output data */
                tdreport = kzalloc(length, GFP_KERNEL);
                if (!tdreport)
                        return -ENOMEM;
                /*
                 * Generate TDREPORT using "TDG.MR.REPORT" TDCALL.
                 *
                 * Get the TDREPORT using REPORTDATA as input. Refer to
                 * section 22.3.3 TDG.MR.REPORT leaf in the TDX Module 1.0
                 * Specification for detailed information.
                 */
                ret = __tdx_module_call(TDX_GET_REPORT, virt_to_phys(tdreport),
                                virt_to_phys(rep_data->reportdata), 0, 0, NULL);
                if (ret) {
                        pr_debug("TDREPORT TDCALL failed, status:%lx\n", ret);
                       kfree(tdreport);
                        return -EIO;
                }

                /* Copy REPORTDATA from the user buffer */
                if (copy_to_user(buffer, tdreport, length)) {
                        kfree(tdreport);
                        return -EFAULT;
                }

                return length;
        default:
                pr_debug("cmd %d not supported\n", areq->cmd);
                break;
        }

        return 0;
}

static ssize_t tdx_attest_write(struct file *filp, const char __user *buffer,
                                size_t length, loff_t *offset)
{
        struct tdx_attest_req *areq = filp->private_data;
        struct report_req *rep_data;

        if (!areq)
                return -EINVAL;

        switch (areq->cmd) {
        case TDX_CMD_GET_REPORT:

                /* Check for valid length and offset */
                if (length != TDX_REPORTDATA_LEN || offset != 0)
                        return -EINVAL;

                rep_data = areq->data;

                /* Allocate space to store REPORTDATA */
                rep_data->reportdata = kzalloc(length, GFP_KERNEL);
                if (!rep_data->reportdata)
                        return -ENOMEM;

                /* Copy REPORTDATA from the user buffer */
                if (copy_from_user(rep_data->reportdata, buffer, length)) {
                        kfree(rep_data->reportdata);
                        rep_data->reportdata = NULL;
                        return -EFAULT;
                }

                rep_data->reportdata_len = length;

                return length;
        default:
                pr_debug("cmd %d not supported\n", areq->cmd);
                break;
        }

        return 0;
}


static int tdx_attest_open(struct inode *inode, struct file *filp)
{
        struct tdx_attest_req *areq;

        /* Allocate space to track attestation request */
        areq = kmalloc(sizeof(*areq), GFP_KERNEL);
        if (!areq)
                return -ENOMEM;

        filp->private_data = areq;

        return 0;
}

static int tdx_attest_release(struct inode *inode, struct file *filp)
{
        kfree(filp->private_data);
        filp->private_data = NULL;

        return 0;
}

static const struct file_operations tdx_attest_fops = {
        .owner          = THIS_MODULE,
        .open           = tdx_attest_open,
        .read           = tdx_attest_read,
        .write          = tdx_attest_write,
        .unlocked_ioctl = tdx_attest_ioctl,
        .release        = tdx_attest_release,
        .llseek         = no_llseek,
};

>>> How many of these "drivers" are we going to need which are thinly veiled
>>> ioctl()s that are only TDX module call wrappers?
> 
> This is actually a really big question.  This code is obviously just
> trying to do one thing very narrowly and not thinking about the future
> at all.  Can we please consider what the future will be like and try to
> *architect* this instead of having the kernel just play a glorified game
> of telephone?

I am not very clear about other possible use cases. 

Kirill/Kai/Isaku, Do you think we might need similar infrastructure for any
other TDX Module calls or TDVMCALLs?


-- 
Sathyanarayanan Kuppuswamy
Linux Kernel Developer

  reply	other threads:[~2022-06-30 23:51 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-09  2:52 [PATCH v8 0/5] Add TDX Guest Attestation support Kuppuswamy Sathyanarayanan
2022-06-09  2:52 ` [PATCH v8 1/5] x86/tdx: Add TDX Guest attestation interface driver Kuppuswamy Sathyanarayanan
2022-06-24 16:51   ` Dave Hansen
2022-06-27 14:50     ` Sathyanarayanan Kuppuswamy
2022-06-27 17:24       ` Dave Hansen
2022-06-30 23:50         ` Sathyanarayanan Kuppuswamy [this message]
2022-07-05 12:07           ` Kai Huang
2022-07-05 18:45             ` Sathyanarayanan Kuppuswamy
2022-07-05 18:52               ` Dave Hansen
2022-07-05 21:21                 ` Sathyanarayanan Kuppuswamy
2022-07-05 22:31                   ` Kai Huang
2022-07-06 22:27                     ` Sathyanarayanan Kuppuswamy
2022-07-06 22:59                       ` Kai Huang
2022-07-18 22:52                       ` Sathyanarayanan Kuppuswamy
2022-06-09  2:52 ` [PATCH v8 2/5] x86/tdx: Add TDX Guest event notify interrupt support Kuppuswamy Sathyanarayanan
2022-06-20 12:33   ` Kai Huang
2022-06-20 15:44     ` Sathyanarayanan Kuppuswamy
2022-06-23  9:46       ` Kai Huang
2022-06-23 10:24       ` Kai Huang
2022-06-24 22:23       ` Sathyanarayanan Kuppuswamy
2022-06-24 23:41       ` Nakajima, Jun
2022-06-25  3:35         ` Yao, Jiewen
2022-06-27 11:21           ` Kai Huang
2022-06-27 14:56             ` Sathyanarayanan Kuppuswamy
2022-07-14  0:46             ` Sathyanarayanan Kuppuswamy
2022-07-14 10:42               ` Kai Huang
2022-07-14 20:55                 ` Sathyanarayanan Kuppuswamy
2022-07-14 23:58                   ` Kai Huang
2022-06-09  2:52 ` [PATCH v8 3/5] x86/mm: Make tdx_enc_status_changed() vmalloc address compatible Kuppuswamy Sathyanarayanan
2022-06-09  2:52 ` [PATCH v8 4/5] x86/mm: Add noalias variants of set_memory_*crypted() functions Kuppuswamy Sathyanarayanan
2022-06-24 13:19   ` Dave Hansen
2022-06-27 15:12     ` Kirill A. Shutemov
2022-06-27 18:24       ` Dave Hansen
2022-06-28  1:15         ` Kai Huang
2022-07-05 15:29           ` Kirill A. Shutemov
2022-07-18 14:22             ` Sathyanarayanan Kuppuswamy
2022-07-19 16:13               ` Kirill A. Shutemov
2022-07-19 17:10                 ` Sathyanarayanan Kuppuswamy
2022-07-19 21:55                   ` Kirill A. Shutemov
2022-07-20 14:56                     ` Sathyanarayanan Kuppuswamy
2022-07-20 16:17                       ` Kirill A. Shutemov
2022-07-20 16:58                         ` Sathyanarayanan Kuppuswamy
2022-06-09  2:52 ` [PATCH v8 5/5] x86/tdx: Add Quote generation support Kuppuswamy Sathyanarayanan
2022-06-14 12:30   ` Wander Lairson Costa
2022-06-14 12:58     ` Sathyanarayanan Kuppuswamy
2022-07-21 16:08   ` Dave Hansen
2022-07-21 16:42     ` Sathyanarayanan Kuppuswamy
2022-07-21 16:49       ` Dave Hansen
2022-07-21 16:54         ` Sathyanarayanan Kuppuswamy
2022-07-21 17:02           ` Dave Hansen
2022-07-21 17:16             ` Sathyanarayanan Kuppuswamy
2022-07-21 17:19               ` Dave Hansen
2022-07-21 18:31                 ` Sathyanarayanan Kuppuswamy
2022-07-21 18:42                 ` Isaku Yamahata
2022-07-21 18:52                   ` Dave Hansen
2022-07-21 18:57                     ` Sathyanarayanan Kuppuswamy
2022-07-21 19:23                       ` Dave Hansen
2022-07-21 22:08                         ` Sathyanarayanan Kuppuswamy
2022-07-21 23:16                         ` Kai Huang
2022-07-21 23:32     ` Kai Huang
2022-07-22  0:27   ` Dave Hansen
2022-07-22 19:05     ` Isaku Yamahata
2022-07-22 19:13       ` Dave Hansen
2022-07-22 21:18         ` Sathyanarayanan Kuppuswamy
2022-07-22 21:24           ` Dave Hansen
2022-07-25 20:19           ` Nakajima, Jun
2022-07-25 20:23             ` Dave Hansen
2022-07-25 21:56               ` Nakajima, Jun
2022-07-25 22:06                 ` Sathyanarayanan Kuppuswamy
2022-08-09  6:20               ` Guorui Yu
2022-11-21  2:04                 ` Guorui Yu
2022-11-21  2:26                   ` Dave Hansen
2023-01-07  0:58                     ` Erdem Aktas
2022-07-25 11:05         ` Kai Huang
2022-06-24 18:24 ` [PATCH v8 0/5] Add TDX Guest Attestation support Dave Hansen
2022-06-27 14:51   ` Sathyanarayanan Kuppuswamy
2022-06-27 18:51     ` Dave Hansen

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=ca73d2bd-5d40-d385-aeb0-8c04811690ff@linux.intel.com \
    --to=sathyanarayanan.kuppuswamy@linux.intel.com \
    --cc=ak@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=isaku.yamahata@gmail.com \
    --cc=kai.huang@intel.com \
    --cc=khalid.elmously@canonical.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marcelo.cerri@canonical.com \
    --cc=mingo@redhat.com \
    --cc=philip.cox@canonical.com \
    --cc=tglx@linutronix.de \
    --cc=tim.gardner@canonical.com \
    --cc=tony.luck@intel.com \
    --cc=wander@redhat.com \
    --cc=x86@kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).