Skip to content

Commit

Permalink
virt/csv-guest: Provide interface for request of CSV3 attestation report
Browse files Browse the repository at this point in the history
hygon inclusion
category: feature
CVE: NA

---------------------------

This change allows user in the CSV3 guest to get attestation report.

Currently, the input from user-space for CSV3 attestation report is
same as that for CSV attestation report.

Signed-off-by: hanliyang <[email protected]>
  • Loading branch information
hanliyang committed Nov 14, 2024
1 parent 09b8f52 commit 83b4ebd
Showing 1 changed file with 122 additions and 5 deletions.
127 changes: 122 additions & 5 deletions drivers/virt/coco/csv-guest/csv-guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,28 @@
#include <linux/slab.h>
#include <linux/cc_platform.h>
#include <linux/cacheflush.h>
#include <linux/psp-hygon.h>

#include <uapi/linux/kvm_para.h>

#include <asm/csv.h>

#include "csv-guest.h"

static long csv_get_report(void __user *argp)
/* Mutex to serialize the command handling. */
static DEFINE_MUTEX(csv_cmd_mutex);

static int csv_get_report(unsigned long arg)
{
u8 *csv_report;
long ret;
struct csv_report_req req;

if (copy_from_user(&req, argp, sizeof(struct csv_report_req)))
if (copy_from_user(&req, (void __user *)arg,
sizeof(struct csv_report_req)))
return -EFAULT;

if (req.len < CSV_REPORT_INPUT_DATA_LEN)
if (req.len < CSV_REPORT_INPUT_DATA_LEN || !req.report_data)
return -EINVAL;

csv_report = kzalloc(req.len, GFP_KERNEL);
Expand Down Expand Up @@ -54,14 +61,124 @@ static long csv_get_report(void __user *argp)
return ret;
}

static int csv3_get_report(unsigned long arg)
{
struct csv_report_req input;
struct page *page = NULL;
struct csv3_data_attestation_report *cmd_buff = NULL;
void *req_buff = NULL;
void *resp_buff = NULL;
int ret;

if (copy_from_user(&input, (void __user *)arg, sizeof(input)))
return -EFAULT;

if (!input.len || !input.report_data)
return -EINVAL;

/* Use alloc_page for alignment */
page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
if (!page)
return -ENOMEM;
cmd_buff = (struct csv3_data_attestation_report *)page_address(page);

/*
* Query the firmware to get minimum length of request buffer and
* respond buffer.
*/
ret = csv3_issue_request_report(__pa(cmd_buff), sizeof(*cmd_buff));

/*
* The input.len must be the maxinum length of the req and resp buffer
* at least, otherwise return with error.
*/
if (input.len < max(cmd_buff->req_len, cmd_buff->resp_len)) {
ret = -EINVAL;
goto err;
}

/* Use alloc_page for alignment */
page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
if (!page) {
ret = -ENOMEM;
goto err;
}
req_buff = page_address(page);

/* Use alloc_page for alignment */
page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
if (!page) {
ret = -ENOMEM;
goto err;
}
resp_buff = page_address(page);

/* Copy user's input data */
if (copy_from_user(req_buff, input.report_data, cmd_buff->req_len)) {
ret = -EFAULT;
goto err;
}

/*
* The req_len and resp_len fields has already been filled by firmware
* when we query the lengths from firmware.
*/
cmd_buff->req_gpa = __pa(req_buff);
cmd_buff->resp_gpa = __pa(resp_buff);

ret = csv3_issue_request_report(__pa(cmd_buff), sizeof(*cmd_buff));
if (ret || (!ret && cmd_buff->fw_error_code)) {
pr_err("%s: fail to generate report, fw_error:%#x ret:%d\n",
__func__, cmd_buff->fw_error_code, ret);
ret = -EIO;
goto err;
}

/* Copy attestation report to user */
if (copy_to_user(input.report_data, resp_buff, cmd_buff->resp_len))
ret = -EFAULT;

err:
if (resp_buff)
free_page((unsigned long)resp_buff);
if (req_buff)
free_page((unsigned long)req_buff);
if (cmd_buff)
free_page((unsigned long)cmd_buff);

return ret;
}

static int get_report(unsigned long arg)
{
int ret = -ENOTTY;

lockdep_assert_held(&csv_cmd_mutex);

if (csv3_active())
ret = csv3_get_report(arg);
else if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
ret = csv_get_report(arg);
return ret;
}

static long csv_guest_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = -ENOTTY;

mutex_lock(&csv_cmd_mutex);

switch (cmd) {
case CSV_CMD_GET_REPORT:
return csv_get_report((void __user *)arg);
ret = get_report(arg);
break;
default:
return -ENOTTY;
break;
}

mutex_unlock(&csv_cmd_mutex);

return ret;
}

static const struct file_operations csv_guest_fops = {
Expand Down

0 comments on commit 83b4ebd

Please sign in to comment.