Skip to content

Commit 2df2135

Browse files
committed
virt: sevguest: Prep for kernel internal get_ext_report()
In preparation for using the configs-tsm facility to convey attestation blobs to userspace, switch to using the 'sockptr' api for copying payloads to provided buffers where 'sockptr' handles user vs kernel buffers. While configfs-tsm is meant to replace existing confidential computing ioctl() implementations for attestation report retrieval the old ioctl() path needs to stick around for a deprecation period. No behavior change intended. Cc: Borislav Petkov <bp@alien8.de> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Dionna Glaze <dionnaglaze@google.com> Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 70e6f7e commit 2df2135

File tree

1 file changed

+32
-12
lines changed

1 file changed

+32
-12
lines changed

drivers/virt/coco/sev-guest/sev-guest.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <crypto/aead.h>
2020
#include <linux/scatterlist.h>
2121
#include <linux/psp-sev.h>
22+
#include <linux/sockptr.h>
2223
#include <uapi/linux/sev-guest.h>
2324
#include <uapi/linux/psp-sev.h>
2425

@@ -475,6 +476,11 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code,
475476
return 0;
476477
}
477478

479+
struct snp_req_resp {
480+
sockptr_t req_data;
481+
sockptr_t resp_data;
482+
};
483+
478484
static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
479485
{
480486
struct snp_guest_crypto *crypto = snp_dev->crypto;
@@ -555,31 +561,39 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
555561
return rc;
556562
}
557563

558-
static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
564+
static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg,
565+
struct snp_req_resp *io)
566+
559567
{
560568
struct snp_ext_report_req *req = &snp_dev->req.ext_report;
561569
struct snp_guest_crypto *crypto = snp_dev->crypto;
562570
struct snp_report_resp *resp;
563571
int ret, npages = 0, resp_len;
572+
sockptr_t certs_address;
564573

565574
lockdep_assert_held(&snp_cmd_mutex);
566575

567-
if (!arg->req_data || !arg->resp_data)
576+
if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
568577
return -EINVAL;
569578

570-
if (copy_from_user(req, (void __user *)arg->req_data, sizeof(*req)))
579+
if (copy_from_sockptr(req, io->req_data, sizeof(*req)))
571580
return -EFAULT;
572581

573-
/* userspace does not want certificate data */
582+
/* caller does not want certificate data */
574583
if (!req->certs_len || !req->certs_address)
575584
goto cmd;
576585

577586
if (req->certs_len > SEV_FW_BLOB_MAX_SIZE ||
578587
!IS_ALIGNED(req->certs_len, PAGE_SIZE))
579588
return -EINVAL;
580589

581-
if (!access_ok((const void __user *)req->certs_address, req->certs_len))
582-
return -EFAULT;
590+
if (sockptr_is_kernel(io->resp_data)) {
591+
certs_address = KERNEL_SOCKPTR((void *)req->certs_address);
592+
} else {
593+
certs_address = USER_SOCKPTR((void __user *)req->certs_address);
594+
if (!access_ok(certs_address.user, req->certs_len))
595+
return -EFAULT;
596+
}
583597

584598
/*
585599
* Initialize the intermediate buffer with all zeros. This buffer
@@ -609,21 +623,19 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
609623
if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {
610624
req->certs_len = snp_dev->input.data_npages << PAGE_SHIFT;
611625

612-
if (copy_to_user((void __user *)arg->req_data, req, sizeof(*req)))
626+
if (copy_to_sockptr(io->req_data, req, sizeof(*req)))
613627
ret = -EFAULT;
614628
}
615629

616630
if (ret)
617631
goto e_free;
618632

619-
if (npages &&
620-
copy_to_user((void __user *)req->certs_address, snp_dev->certs_data,
621-
req->certs_len)) {
633+
if (npages && copy_to_sockptr(certs_address, snp_dev->certs_data, req->certs_len)) {
622634
ret = -EFAULT;
623635
goto e_free;
624636
}
625637

626-
if (copy_to_user((void __user *)arg->resp_data, resp, sizeof(*resp)))
638+
if (copy_to_sockptr(io->resp_data, resp, sizeof(*resp)))
627639
ret = -EFAULT;
628640

629641
e_free:
@@ -636,6 +648,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
636648
struct snp_guest_dev *snp_dev = to_snp_dev(file);
637649
void __user *argp = (void __user *)arg;
638650
struct snp_guest_request_ioctl input;
651+
struct snp_req_resp io;
639652
int ret = -ENOTTY;
640653

641654
if (copy_from_user(&input, argp, sizeof(input)))
@@ -664,7 +677,14 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
664677
ret = get_derived_key(snp_dev, &input);
665678
break;
666679
case SNP_GET_EXT_REPORT:
667-
ret = get_ext_report(snp_dev, &input);
680+
/*
681+
* As get_ext_report() may be called from the ioctl() path and a
682+
* kernel internal path (configfs-tsm), decorate the passed
683+
* buffers as user pointers.
684+
*/
685+
io.req_data = USER_SOCKPTR((void __user *)input.req_data);
686+
io.resp_data = USER_SOCKPTR((void __user *)input.resp_data);
687+
ret = get_ext_report(snp_dev, &input, &io);
668688
break;
669689
default:
670690
break;

0 commit comments

Comments
 (0)