// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright IBM Corp. 2022
 *  Author(s): Steffen Eiden <seiden@linux.ibm.com>
 *
 *  This file provides a Linux misc device to give userspace access to some
 *  Ultravisor (UV) functions. The device only accepts IOCTLs and will only
 *  be present if the Ultravisor facility (158) is present.
 *
 *  When userspace sends a valid IOCTL uvdevice will copy the input data to
 *  kernel space, do some basic validity checks to avoid kernel/system
 *  corruption. Any other check that the Ultravisor does will not be done by
 *  the uvdevice to keep changes minimal when adding new functionalities
 *  to existing UV-calls.
 *  After the checks uvdevice builds a corresponding
 *  Ultravisor Call Control Block, and sends the request to the Ultravisor.
 *  Then, it copies the response, including the return codes, back to userspace.
 *  It is the responsibility of the userspace to check for any error issued
 *  by UV and to interpret the UV response. The uvdevice acts as a communication
 *  channel for userspace to the Ultravisor.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>

#include <asm/uvdevice.h>
#include <asm/uv.h>

static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb,
				  u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest)
{
	void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr;

	if (copy_from_user(arcb, user_buf_arcb, uvio_attest->arcb_len))
		return -EFAULT;

	uvcb_attest->header.len = sizeof(*uvcb_attest);
	uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST;
	uvcb_attest->arcb_addr = (u64)arcb;
	uvcb_attest->cont_token = 0;
	uvcb_attest->user_data_len = uvio_attest->user_data_len;
	memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data));
	uvcb_attest->meas_len = uvio_attest->meas_len;
	uvcb_attest->meas_addr = (u64)meas;
	uvcb_attest->add_data_len = uvio_attest->add_data_len;
	uvcb_attest->add_data_addr = (u64)add_data;

	return 0;
}

static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,
					   struct uvio_ioctl_cb *uv_ioctl,
					   u8 *measurement, u8 *add_data,
					   struct uvio_attest *uvio_attest)
{
	struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr;
	void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr;
	void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr;
	void __user *user_buf_uid = &user_uvio_attest->config_uid;

	if (copy_to_user(user_buf_meas, measurement, uvio_attest->meas_len))
		return -EFAULT;
	if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len))
		return -EFAULT;
	if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid)))
		return -EFAULT;
	return 0;
}

static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest)
{
	u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr;

	if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest)))
		return -EFAULT;

	if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN)
		return -EINVAL;
	if (uvio_attest->arcb_len == 0)
		return -EINVAL;
	if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN)
		return -EINVAL;
	if (uvio_attest->meas_len == 0)
		return -EINVAL;
	if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN)
		return -EINVAL;
	if (uvio_attest->reserved136)
		return -EINVAL;
	return 0;
}

/**
 * uvio_attestation() - Perform a Retrieve Attestation Measurement UVC.
 *
 * @uv_ioctl: ioctl control block
 *
 * uvio_attestation() does a Retrieve Attestation Measurement Ultravisor Call.
 * It verifies that the given userspace addresses are valid and request sizes
 * are sane. Every other check is made by the Ultravisor (UV) and won't result
 * in a negative return value. It copies the input to kernelspace, builds the
 * request, sends the UV-call, and copies the result to userspace.
 *
 * The Attestation Request has two input and two outputs.
 * ARCB and User Data are inputs for the UV generated by userspace.
 * Measurement and Additional Data are outputs for userspace generated by UV.
 *
 * The Attestation Request Control Block (ARCB) is a cryptographically verified
 * and secured request to UV and User Data is some plaintext data which is
 * going to be included in the Attestation Measurement calculation.
 *
 * Measurement is a cryptographic measurement of the callers properties,
 * optional data configured by the ARCB and the user data. If specified by the
 * ARCB, UV will add some Additional Data to the measurement calculation.
 * This Additional Data is then returned as well.
 *
 * If the Retrieve Attestation Measurement UV facility is not present,
 * UV will return invalid command rc. This won't be fenced in the driver
 * and does not result in a negative return value.
 *
 * Context: might sleep
 *
 * Return: 0 on success or a negative error code on error.
 */
static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl)
{
	struct uv_cb_attest *uvcb_attest = NULL;
	struct uvio_attest *uvio_attest = NULL;
	u8 *measurement = NULL;
	u8 *add_data = NULL;
	u8 *arcb = NULL;
	int ret;

	ret = -EINVAL;
	if (uv_ioctl->argument_len != sizeof(*uvio_attest))
		goto out;

	ret = -ENOMEM;
	uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL);
	if (!uvio_attest)
		goto out;

	ret = get_uvio_attest(uv_ioctl, uvio_attest);
	if (ret)
		goto out;

	ret = -ENOMEM;
	arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL);
	measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL);
	if (!arcb || !measurement)
		goto out;

	if (uvio_attest->add_data_len) {
		add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL);
		if (!add_data)
			goto out;
	}

	uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL);
	if (!uvcb_attest)
		goto out;

	ret = uvio_build_uvcb_attest(uvcb_attest, arcb,  measurement, add_data, uvio_attest);
	if (ret)
		goto out;

	uv_call_sched(0, (u64)uvcb_attest);

	uv_ioctl->uv_rc = uvcb_attest->header.rc;
	uv_ioctl->uv_rrc = uvcb_attest->header.rrc;

	ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data,
					      uvio_attest);
out:
	kvfree(arcb);
	kvfree(measurement);
	kvfree(add_data);
	kfree(uvio_attest);
	kfree(uvcb_attest);
	return ret;
}

static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp)
{
	if (copy_from_user(ioctl, argp, sizeof(*ioctl)))
		return -EFAULT;
	if (ioctl->flags != 0)
		return -EINVAL;
	if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14)))
		return -EINVAL;

	return 0;
}

/*
 * IOCTL entry point for the Ultravisor device.
 */
static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	struct uvio_ioctl_cb uv_ioctl = { };
	long ret;

	switch (cmd) {
	case UVIO_IOCTL_ATT:
		ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp);
		if (ret)
			return ret;
		ret = uvio_attestation(&uv_ioctl);
		break;
	default:
		ret = -ENOIOCTLCMD;
		break;
	}
	if (ret)
		return ret;

	if (copy_to_user(argp, &uv_ioctl, sizeof(uv_ioctl)))
		ret = -EFAULT;

	return ret;
}

static const struct file_operations uvio_dev_fops = {
	.owner = THIS_MODULE,
	.unlocked_ioctl = uvio_ioctl,
	.llseek = no_llseek,
};

static struct miscdevice uvio_dev_miscdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = UVIO_DEVICE_NAME,
	.fops = &uvio_dev_fops,
};

static void __exit uvio_dev_exit(void)
{
	misc_deregister(&uvio_dev_miscdev);
}

static int __init uvio_dev_init(void)
{
	if (!test_facility(158))
		return -ENXIO;
	return misc_register(&uvio_dev_miscdev);
}

module_init(uvio_dev_init);
module_exit(uvio_dev_exit);

MODULE_AUTHOR("IBM Corporation");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Ultravisor UAPI driver");
