14689752cSSteffen Eiden // SPDX-License-Identifier: GPL-2.0
24689752cSSteffen Eiden /*
34689752cSSteffen Eiden * Copyright IBM Corp. 2022
44689752cSSteffen Eiden * Author(s): Steffen Eiden <seiden@linux.ibm.com>
54689752cSSteffen Eiden *
64689752cSSteffen Eiden * This file provides a Linux misc device to give userspace access to some
74689752cSSteffen Eiden * Ultravisor (UV) functions. The device only accepts IOCTLs and will only
84689752cSSteffen Eiden * be present if the Ultravisor facility (158) is present.
94689752cSSteffen Eiden *
104689752cSSteffen Eiden * When userspace sends a valid IOCTL uvdevice will copy the input data to
114689752cSSteffen Eiden * kernel space, do some basic validity checks to avoid kernel/system
124689752cSSteffen Eiden * corruption. Any other check that the Ultravisor does will not be done by
134689752cSSteffen Eiden * the uvdevice to keep changes minimal when adding new functionalities
144689752cSSteffen Eiden * to existing UV-calls.
154689752cSSteffen Eiden * After the checks uvdevice builds a corresponding
164689752cSSteffen Eiden * Ultravisor Call Control Block, and sends the request to the Ultravisor.
174689752cSSteffen Eiden * Then, it copies the response, including the return codes, back to userspace.
184689752cSSteffen Eiden * It is the responsibility of the userspace to check for any error issued
194689752cSSteffen Eiden * by UV and to interpret the UV response. The uvdevice acts as a communication
204689752cSSteffen Eiden * channel for userspace to the Ultravisor.
214689752cSSteffen Eiden */
224689752cSSteffen Eiden
234689752cSSteffen Eiden #include <linux/module.h>
244689752cSSteffen Eiden #include <linux/kernel.h>
254689752cSSteffen Eiden #include <linux/miscdevice.h>
264689752cSSteffen Eiden #include <linux/types.h>
274689752cSSteffen Eiden #include <linux/stddef.h>
284689752cSSteffen Eiden #include <linux/vmalloc.h>
294689752cSSteffen Eiden #include <linux/slab.h>
305fcd0d8aSSteffen Eiden #include <linux/cpufeature.h>
314689752cSSteffen Eiden
324689752cSSteffen Eiden #include <asm/uvdevice.h>
334689752cSSteffen Eiden #include <asm/uv.h>
344689752cSSteffen Eiden
35ea9d9716SSteffen Eiden #define BIT_UVIO_INTERNAL U32_MAX
36ea9d9716SSteffen Eiden /* Mapping from IOCTL-nr to UVC-bit */
37ea9d9716SSteffen Eiden static const u32 ioctl_nr_to_uvc_bit[] __initconst = {
38ea9d9716SSteffen Eiden [UVIO_IOCTL_UVDEV_INFO_NR] = BIT_UVIO_INTERNAL,
39ea9d9716SSteffen Eiden [UVIO_IOCTL_ATT_NR] = BIT_UVC_CMD_RETR_ATTEST,
4044567ca2SSteffen Eiden [UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET,
41b96b3ce2SSteffen Eiden [UVIO_IOCTL_LIST_SECRETS_NR] = BIT_UVC_CMD_LIST_SECRETS,
422d8a26acSSteffen Eiden [UVIO_IOCTL_LOCK_SECRETS_NR] = BIT_UVC_CMD_LOCK_SECRETS,
43ea9d9716SSteffen Eiden };
44ea9d9716SSteffen Eiden
45ea9d9716SSteffen Eiden static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS);
46ea9d9716SSteffen Eiden
47ea9d9716SSteffen Eiden static struct uvio_uvdev_info uvdev_info = {
48ea9d9716SSteffen Eiden .supp_uvio_cmds = GENMASK_ULL(UVIO_IOCTL_NUM_IOCTLS - 1, 0),
49ea9d9716SSteffen Eiden };
50ea9d9716SSteffen Eiden
set_supp_uv_cmds(unsigned long * supp_uv_cmds)51ea9d9716SSteffen Eiden static void __init set_supp_uv_cmds(unsigned long *supp_uv_cmds)
52ea9d9716SSteffen Eiden {
53ea9d9716SSteffen Eiden int i;
54ea9d9716SSteffen Eiden
55ea9d9716SSteffen Eiden for (i = 0; i < UVIO_IOCTL_NUM_IOCTLS; i++) {
56ea9d9716SSteffen Eiden if (ioctl_nr_to_uvc_bit[i] == BIT_UVIO_INTERNAL)
57ea9d9716SSteffen Eiden continue;
58ea9d9716SSteffen Eiden if (!test_bit_inv(ioctl_nr_to_uvc_bit[i], uv_info.inst_calls_list))
59ea9d9716SSteffen Eiden continue;
60ea9d9716SSteffen Eiden __set_bit(i, supp_uv_cmds);
61ea9d9716SSteffen Eiden }
62ea9d9716SSteffen Eiden }
63ea9d9716SSteffen Eiden
64ea9d9716SSteffen Eiden /**
65ea9d9716SSteffen Eiden * uvio_uvdev_info() - get information about the uvdevice
66ea9d9716SSteffen Eiden *
67ea9d9716SSteffen Eiden * @uv_ioctl: ioctl control block
68ea9d9716SSteffen Eiden *
69ea9d9716SSteffen Eiden * Lists all IOCTLs that are supported by this uvdevice
70ea9d9716SSteffen Eiden */
uvio_uvdev_info(struct uvio_ioctl_cb * uv_ioctl)71ea9d9716SSteffen Eiden static int uvio_uvdev_info(struct uvio_ioctl_cb *uv_ioctl)
72ea9d9716SSteffen Eiden {
73ea9d9716SSteffen Eiden void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
74ea9d9716SSteffen Eiden
75ea9d9716SSteffen Eiden if (uv_ioctl->argument_len < sizeof(uvdev_info))
76ea9d9716SSteffen Eiden return -EINVAL;
77ea9d9716SSteffen Eiden if (copy_to_user(user_buf_arg, &uvdev_info, sizeof(uvdev_info)))
78ea9d9716SSteffen Eiden return -EFAULT;
79ea9d9716SSteffen Eiden
80ea9d9716SSteffen Eiden uv_ioctl->uv_rc = UVC_RC_EXECUTED;
81ea9d9716SSteffen Eiden return 0;
82ea9d9716SSteffen Eiden }
83ea9d9716SSteffen Eiden
uvio_build_uvcb_attest(struct uv_cb_attest * uvcb_attest,u8 * arcb,u8 * meas,u8 * add_data,struct uvio_attest * uvio_attest)844689752cSSteffen Eiden static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb,
854689752cSSteffen Eiden u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest)
864689752cSSteffen Eiden {
874689752cSSteffen Eiden void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr;
884689752cSSteffen Eiden
894689752cSSteffen Eiden if (copy_from_user(arcb, user_buf_arcb, uvio_attest->arcb_len))
904689752cSSteffen Eiden return -EFAULT;
914689752cSSteffen Eiden
924689752cSSteffen Eiden uvcb_attest->header.len = sizeof(*uvcb_attest);
934689752cSSteffen Eiden uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST;
944689752cSSteffen Eiden uvcb_attest->arcb_addr = (u64)arcb;
954689752cSSteffen Eiden uvcb_attest->cont_token = 0;
964689752cSSteffen Eiden uvcb_attest->user_data_len = uvio_attest->user_data_len;
974689752cSSteffen Eiden memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data));
984689752cSSteffen Eiden uvcb_attest->meas_len = uvio_attest->meas_len;
994689752cSSteffen Eiden uvcb_attest->meas_addr = (u64)meas;
1004689752cSSteffen Eiden uvcb_attest->add_data_len = uvio_attest->add_data_len;
1014689752cSSteffen Eiden uvcb_attest->add_data_addr = (u64)add_data;
1024689752cSSteffen Eiden
1034689752cSSteffen Eiden return 0;
1044689752cSSteffen Eiden }
1054689752cSSteffen Eiden
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)1064689752cSSteffen Eiden static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,
1074689752cSSteffen Eiden struct uvio_ioctl_cb *uv_ioctl,
1084689752cSSteffen Eiden u8 *measurement, u8 *add_data,
1094689752cSSteffen Eiden struct uvio_attest *uvio_attest)
1104689752cSSteffen Eiden {
1114689752cSSteffen Eiden struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr;
112*26fb87ffSSteffen Eiden u32 __user *user_buf_add_len = (u32 __user *)&user_uvio_attest->add_data_len;
1134689752cSSteffen Eiden void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr;
1144689752cSSteffen Eiden void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr;
1154689752cSSteffen Eiden void __user *user_buf_uid = &user_uvio_attest->config_uid;
1164689752cSSteffen Eiden
1174689752cSSteffen Eiden if (copy_to_user(user_buf_meas, measurement, uvio_attest->meas_len))
1184689752cSSteffen Eiden return -EFAULT;
1194689752cSSteffen Eiden if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len))
1204689752cSSteffen Eiden return -EFAULT;
121*26fb87ffSSteffen Eiden if (put_user(uvio_attest->add_data_len, user_buf_add_len))
122*26fb87ffSSteffen Eiden return -EFAULT;
1234689752cSSteffen Eiden if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid)))
1244689752cSSteffen Eiden return -EFAULT;
1254689752cSSteffen Eiden return 0;
1264689752cSSteffen Eiden }
1274689752cSSteffen Eiden
get_uvio_attest(struct uvio_ioctl_cb * uv_ioctl,struct uvio_attest * uvio_attest)1284689752cSSteffen Eiden static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest)
1294689752cSSteffen Eiden {
1304689752cSSteffen Eiden u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr;
1314689752cSSteffen Eiden
1324689752cSSteffen Eiden if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest)))
1334689752cSSteffen Eiden return -EFAULT;
1344689752cSSteffen Eiden
1354689752cSSteffen Eiden if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN)
1364689752cSSteffen Eiden return -EINVAL;
1374689752cSSteffen Eiden if (uvio_attest->arcb_len == 0)
1384689752cSSteffen Eiden return -EINVAL;
1394689752cSSteffen Eiden if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN)
1404689752cSSteffen Eiden return -EINVAL;
1414689752cSSteffen Eiden if (uvio_attest->meas_len == 0)
1424689752cSSteffen Eiden return -EINVAL;
1434689752cSSteffen Eiden if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN)
1444689752cSSteffen Eiden return -EINVAL;
1454689752cSSteffen Eiden if (uvio_attest->reserved136)
1464689752cSSteffen Eiden return -EINVAL;
1474689752cSSteffen Eiden return 0;
1484689752cSSteffen Eiden }
1494689752cSSteffen Eiden
1504689752cSSteffen Eiden /**
1514689752cSSteffen Eiden * uvio_attestation() - Perform a Retrieve Attestation Measurement UVC.
1524689752cSSteffen Eiden *
1534689752cSSteffen Eiden * @uv_ioctl: ioctl control block
1544689752cSSteffen Eiden *
1554689752cSSteffen Eiden * uvio_attestation() does a Retrieve Attestation Measurement Ultravisor Call.
1564689752cSSteffen Eiden * It verifies that the given userspace addresses are valid and request sizes
1574689752cSSteffen Eiden * are sane. Every other check is made by the Ultravisor (UV) and won't result
1584689752cSSteffen Eiden * in a negative return value. It copies the input to kernelspace, builds the
1594689752cSSteffen Eiden * request, sends the UV-call, and copies the result to userspace.
1604689752cSSteffen Eiden *
1614689752cSSteffen Eiden * The Attestation Request has two input and two outputs.
1624689752cSSteffen Eiden * ARCB and User Data are inputs for the UV generated by userspace.
1634689752cSSteffen Eiden * Measurement and Additional Data are outputs for userspace generated by UV.
1644689752cSSteffen Eiden *
1654689752cSSteffen Eiden * The Attestation Request Control Block (ARCB) is a cryptographically verified
1664689752cSSteffen Eiden * and secured request to UV and User Data is some plaintext data which is
1674689752cSSteffen Eiden * going to be included in the Attestation Measurement calculation.
1684689752cSSteffen Eiden *
1694689752cSSteffen Eiden * Measurement is a cryptographic measurement of the callers properties,
1704689752cSSteffen Eiden * optional data configured by the ARCB and the user data. If specified by the
1714689752cSSteffen Eiden * ARCB, UV will add some Additional Data to the measurement calculation.
1724689752cSSteffen Eiden * This Additional Data is then returned as well.
1734689752cSSteffen Eiden *
1744689752cSSteffen Eiden * If the Retrieve Attestation Measurement UV facility is not present,
1754689752cSSteffen Eiden * UV will return invalid command rc. This won't be fenced in the driver
1764689752cSSteffen Eiden * and does not result in a negative return value.
1774689752cSSteffen Eiden *
1784689752cSSteffen Eiden * Context: might sleep
1794689752cSSteffen Eiden *
1804689752cSSteffen Eiden * Return: 0 on success or a negative error code on error.
1814689752cSSteffen Eiden */
uvio_attestation(struct uvio_ioctl_cb * uv_ioctl)1824689752cSSteffen Eiden static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl)
1834689752cSSteffen Eiden {
1844689752cSSteffen Eiden struct uv_cb_attest *uvcb_attest = NULL;
1854689752cSSteffen Eiden struct uvio_attest *uvio_attest = NULL;
1864689752cSSteffen Eiden u8 *measurement = NULL;
1874689752cSSteffen Eiden u8 *add_data = NULL;
1884689752cSSteffen Eiden u8 *arcb = NULL;
1894689752cSSteffen Eiden int ret;
1904689752cSSteffen Eiden
1914689752cSSteffen Eiden ret = -EINVAL;
1924689752cSSteffen Eiden if (uv_ioctl->argument_len != sizeof(*uvio_attest))
1934689752cSSteffen Eiden goto out;
1944689752cSSteffen Eiden
1954689752cSSteffen Eiden ret = -ENOMEM;
1964689752cSSteffen Eiden uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL);
1974689752cSSteffen Eiden if (!uvio_attest)
1984689752cSSteffen Eiden goto out;
1994689752cSSteffen Eiden
2004689752cSSteffen Eiden ret = get_uvio_attest(uv_ioctl, uvio_attest);
2014689752cSSteffen Eiden if (ret)
2024689752cSSteffen Eiden goto out;
2034689752cSSteffen Eiden
2044689752cSSteffen Eiden ret = -ENOMEM;
2054689752cSSteffen Eiden arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL);
2064689752cSSteffen Eiden measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL);
2074689752cSSteffen Eiden if (!arcb || !measurement)
2084689752cSSteffen Eiden goto out;
2094689752cSSteffen Eiden
2104689752cSSteffen Eiden if (uvio_attest->add_data_len) {
2114689752cSSteffen Eiden add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL);
2124689752cSSteffen Eiden if (!add_data)
2134689752cSSteffen Eiden goto out;
2144689752cSSteffen Eiden }
2154689752cSSteffen Eiden
2164689752cSSteffen Eiden uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL);
2174689752cSSteffen Eiden if (!uvcb_attest)
2184689752cSSteffen Eiden goto out;
2194689752cSSteffen Eiden
2204689752cSSteffen Eiden ret = uvio_build_uvcb_attest(uvcb_attest, arcb, measurement, add_data, uvio_attest);
2214689752cSSteffen Eiden if (ret)
2224689752cSSteffen Eiden goto out;
2234689752cSSteffen Eiden
2244689752cSSteffen Eiden uv_call_sched(0, (u64)uvcb_attest);
2254689752cSSteffen Eiden
2264689752cSSteffen Eiden uv_ioctl->uv_rc = uvcb_attest->header.rc;
2274689752cSSteffen Eiden uv_ioctl->uv_rrc = uvcb_attest->header.rrc;
2284689752cSSteffen Eiden
2294689752cSSteffen Eiden ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data,
2304689752cSSteffen Eiden uvio_attest);
2314689752cSSteffen Eiden out:
2324689752cSSteffen Eiden kvfree(arcb);
2334689752cSSteffen Eiden kvfree(measurement);
2344689752cSSteffen Eiden kvfree(add_data);
2354689752cSSteffen Eiden kfree(uvio_attest);
2364689752cSSteffen Eiden kfree(uvcb_attest);
2374689752cSSteffen Eiden return ret;
2384689752cSSteffen Eiden }
2394689752cSSteffen Eiden
24044567ca2SSteffen Eiden /** uvio_add_secret() - perform an Add Secret UVC
24144567ca2SSteffen Eiden *
24244567ca2SSteffen Eiden * @uv_ioctl: ioctl control block
24344567ca2SSteffen Eiden *
24444567ca2SSteffen Eiden * uvio_add_secret() performs the Add Secret Ultravisor Call.
24544567ca2SSteffen Eiden *
24644567ca2SSteffen Eiden * The given userspace argument address and size are verified to be
24744567ca2SSteffen Eiden * valid but every other check is made by the Ultravisor
24844567ca2SSteffen Eiden * (UV). Therefore UV errors won't result in a negative return
24944567ca2SSteffen Eiden * value. The request is then copied to kernelspace, the UV-call is
25044567ca2SSteffen Eiden * performed and the results are copied back to userspace.
25144567ca2SSteffen Eiden *
25244567ca2SSteffen Eiden * The argument has to point to an Add Secret Request Control Block
25344567ca2SSteffen Eiden * which is an encrypted and cryptographically verified request that
25444567ca2SSteffen Eiden * inserts a protected guest's secrets into the Ultravisor for later
25544567ca2SSteffen Eiden * use.
25644567ca2SSteffen Eiden *
25744567ca2SSteffen Eiden * If the Add Secret UV facility is not present, UV will return
25844567ca2SSteffen Eiden * invalid command rc. This won't be fenced in the driver and does not
25944567ca2SSteffen Eiden * result in a negative return value.
26044567ca2SSteffen Eiden *
26144567ca2SSteffen Eiden * Context: might sleep
26244567ca2SSteffen Eiden *
26344567ca2SSteffen Eiden * Return: 0 on success or a negative error code on error.
26444567ca2SSteffen Eiden */
uvio_add_secret(struct uvio_ioctl_cb * uv_ioctl)26544567ca2SSteffen Eiden static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl)
26644567ca2SSteffen Eiden {
26744567ca2SSteffen Eiden void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
26844567ca2SSteffen Eiden struct uv_cb_guest_addr uvcb = {
26944567ca2SSteffen Eiden .header.len = sizeof(uvcb),
27044567ca2SSteffen Eiden .header.cmd = UVC_CMD_ADD_SECRET,
27144567ca2SSteffen Eiden };
27244567ca2SSteffen Eiden void *asrcb = NULL;
27344567ca2SSteffen Eiden int ret;
27444567ca2SSteffen Eiden
27544567ca2SSteffen Eiden if (uv_ioctl->argument_len > UVIO_ADD_SECRET_MAX_LEN)
27644567ca2SSteffen Eiden return -EINVAL;
27744567ca2SSteffen Eiden if (uv_ioctl->argument_len == 0)
27844567ca2SSteffen Eiden return -EINVAL;
27944567ca2SSteffen Eiden
28044567ca2SSteffen Eiden asrcb = kvzalloc(uv_ioctl->argument_len, GFP_KERNEL);
28144567ca2SSteffen Eiden if (!asrcb)
28244567ca2SSteffen Eiden return -ENOMEM;
28344567ca2SSteffen Eiden
28444567ca2SSteffen Eiden ret = -EFAULT;
28544567ca2SSteffen Eiden if (copy_from_user(asrcb, user_buf_arg, uv_ioctl->argument_len))
28644567ca2SSteffen Eiden goto out;
28744567ca2SSteffen Eiden
28844567ca2SSteffen Eiden ret = 0;
28944567ca2SSteffen Eiden uvcb.addr = (u64)asrcb;
29044567ca2SSteffen Eiden uv_call_sched(0, (u64)&uvcb);
29144567ca2SSteffen Eiden uv_ioctl->uv_rc = uvcb.header.rc;
29244567ca2SSteffen Eiden uv_ioctl->uv_rrc = uvcb.header.rrc;
29344567ca2SSteffen Eiden
29444567ca2SSteffen Eiden out:
29544567ca2SSteffen Eiden kvfree(asrcb);
29644567ca2SSteffen Eiden return ret;
29744567ca2SSteffen Eiden }
29844567ca2SSteffen Eiden
299b96b3ce2SSteffen Eiden /** uvio_list_secrets() - perform a List Secret UVC
300b96b3ce2SSteffen Eiden * @uv_ioctl: ioctl control block
301b96b3ce2SSteffen Eiden *
302b96b3ce2SSteffen Eiden * uvio_list_secrets() performs the List Secret Ultravisor Call. It verifies
303b96b3ce2SSteffen Eiden * that the given userspace argument address is valid and its size is sane.
304b96b3ce2SSteffen Eiden * Every other check is made by the Ultravisor (UV) and won't result in a
305b96b3ce2SSteffen Eiden * negative return value. It builds the request, performs the UV-call, and
306b96b3ce2SSteffen Eiden * copies the result to userspace.
307b96b3ce2SSteffen Eiden *
308b96b3ce2SSteffen Eiden * The argument specifies the location for the result of the UV-Call.
309b96b3ce2SSteffen Eiden *
310b96b3ce2SSteffen Eiden * If the List Secrets UV facility is not present, UV will return invalid
311b96b3ce2SSteffen Eiden * command rc. This won't be fenced in the driver and does not result in a
312b96b3ce2SSteffen Eiden * negative return value.
313b96b3ce2SSteffen Eiden *
314b96b3ce2SSteffen Eiden * Context: might sleep
315b96b3ce2SSteffen Eiden *
316b96b3ce2SSteffen Eiden * Return: 0 on success or a negative error code on error.
317b96b3ce2SSteffen Eiden */
uvio_list_secrets(struct uvio_ioctl_cb * uv_ioctl)318b96b3ce2SSteffen Eiden static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl)
319b96b3ce2SSteffen Eiden {
320b96b3ce2SSteffen Eiden void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr;
321b96b3ce2SSteffen Eiden struct uv_cb_guest_addr uvcb = {
322b96b3ce2SSteffen Eiden .header.len = sizeof(uvcb),
323b96b3ce2SSteffen Eiden .header.cmd = UVC_CMD_LIST_SECRETS,
324b96b3ce2SSteffen Eiden };
325b96b3ce2SSteffen Eiden void *secrets = NULL;
326b96b3ce2SSteffen Eiden int ret = 0;
327b96b3ce2SSteffen Eiden
328b96b3ce2SSteffen Eiden if (uv_ioctl->argument_len != UVIO_LIST_SECRETS_LEN)
329b96b3ce2SSteffen Eiden return -EINVAL;
330b96b3ce2SSteffen Eiden
331b96b3ce2SSteffen Eiden secrets = kvzalloc(UVIO_LIST_SECRETS_LEN, GFP_KERNEL);
332b96b3ce2SSteffen Eiden if (!secrets)
333b96b3ce2SSteffen Eiden return -ENOMEM;
334b96b3ce2SSteffen Eiden
335b96b3ce2SSteffen Eiden uvcb.addr = (u64)secrets;
336b96b3ce2SSteffen Eiden uv_call_sched(0, (u64)&uvcb);
337b96b3ce2SSteffen Eiden uv_ioctl->uv_rc = uvcb.header.rc;
338b96b3ce2SSteffen Eiden uv_ioctl->uv_rrc = uvcb.header.rrc;
339b96b3ce2SSteffen Eiden
340b96b3ce2SSteffen Eiden if (copy_to_user(user_buf_arg, secrets, UVIO_LIST_SECRETS_LEN))
341b96b3ce2SSteffen Eiden ret = -EFAULT;
342b96b3ce2SSteffen Eiden
343b96b3ce2SSteffen Eiden kvfree(secrets);
344b96b3ce2SSteffen Eiden return ret;
345b96b3ce2SSteffen Eiden }
346b96b3ce2SSteffen Eiden
3472d8a26acSSteffen Eiden /** uvio_lock_secrets() - perform a Lock Secret Store UVC
3482d8a26acSSteffen Eiden * @uv_ioctl: ioctl control block
3492d8a26acSSteffen Eiden *
3502d8a26acSSteffen Eiden * uvio_lock_secrets() performs the Lock Secret Store Ultravisor Call. It
3512d8a26acSSteffen Eiden * performs the UV-call and copies the return codes to the ioctl control block.
3522d8a26acSSteffen Eiden * After this call was dispatched successfully every following Add Secret UVC
3532d8a26acSSteffen Eiden * and Lock Secrets UVC will fail with return code 0x102.
3542d8a26acSSteffen Eiden *
3552d8a26acSSteffen Eiden * The argument address and size must be 0.
3562d8a26acSSteffen Eiden *
3572d8a26acSSteffen Eiden * If the Lock Secrets UV facility is not present, UV will return invalid
3582d8a26acSSteffen Eiden * command rc. This won't be fenced in the driver and does not result in a
3592d8a26acSSteffen Eiden * negative return value.
3602d8a26acSSteffen Eiden *
3612d8a26acSSteffen Eiden * Context: might sleep
3622d8a26acSSteffen Eiden *
3632d8a26acSSteffen Eiden * Return: 0 on success or a negative error code on error.
3642d8a26acSSteffen Eiden */
uvio_lock_secrets(struct uvio_ioctl_cb * ioctl)3652d8a26acSSteffen Eiden static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl)
3662d8a26acSSteffen Eiden {
3672d8a26acSSteffen Eiden struct uv_cb_nodata uvcb = {
3682d8a26acSSteffen Eiden .header.len = sizeof(uvcb),
3692d8a26acSSteffen Eiden .header.cmd = UVC_CMD_LOCK_SECRETS,
3702d8a26acSSteffen Eiden };
3712d8a26acSSteffen Eiden
3722d8a26acSSteffen Eiden if (ioctl->argument_addr || ioctl->argument_len)
3732d8a26acSSteffen Eiden return -EINVAL;
3742d8a26acSSteffen Eiden
3752d8a26acSSteffen Eiden uv_call(0, (u64)&uvcb);
3762d8a26acSSteffen Eiden ioctl->uv_rc = uvcb.header.rc;
3772d8a26acSSteffen Eiden ioctl->uv_rrc = uvcb.header.rrc;
3782d8a26acSSteffen Eiden
3792d8a26acSSteffen Eiden return 0;
3802d8a26acSSteffen Eiden }
3812d8a26acSSteffen Eiden
uvio_copy_and_check_ioctl(struct uvio_ioctl_cb * ioctl,void __user * argp,unsigned long cmd)382ea9d9716SSteffen Eiden static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp,
383ea9d9716SSteffen Eiden unsigned long cmd)
3844689752cSSteffen Eiden {
385ea9d9716SSteffen Eiden u8 nr = _IOC_NR(cmd);
386ea9d9716SSteffen Eiden
387ea9d9716SSteffen Eiden if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE))
388ea9d9716SSteffen Eiden return -ENOIOCTLCMD;
389ea9d9716SSteffen Eiden if (_IOC_TYPE(cmd) != UVIO_TYPE_UVC)
390ea9d9716SSteffen Eiden return -ENOIOCTLCMD;
391ea9d9716SSteffen Eiden if (nr >= UVIO_IOCTL_NUM_IOCTLS)
392ea9d9716SSteffen Eiden return -ENOIOCTLCMD;
393ea9d9716SSteffen Eiden if (_IOC_SIZE(cmd) != sizeof(*ioctl))
394ea9d9716SSteffen Eiden return -ENOIOCTLCMD;
3954689752cSSteffen Eiden if (copy_from_user(ioctl, argp, sizeof(*ioctl)))
3964689752cSSteffen Eiden return -EFAULT;
3974689752cSSteffen Eiden if (ioctl->flags != 0)
3984689752cSSteffen Eiden return -EINVAL;
3994689752cSSteffen Eiden if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14)))
4004689752cSSteffen Eiden return -EINVAL;
4014689752cSSteffen Eiden
402ea9d9716SSteffen Eiden return nr;
4034689752cSSteffen Eiden }
4044689752cSSteffen Eiden
4054689752cSSteffen Eiden /*
4064689752cSSteffen Eiden * IOCTL entry point for the Ultravisor device.
4074689752cSSteffen Eiden */
uvio_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)4084689752cSSteffen Eiden static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
4094689752cSSteffen Eiden {
4104689752cSSteffen Eiden void __user *argp = (void __user *)arg;
4114689752cSSteffen Eiden struct uvio_ioctl_cb uv_ioctl = { };
4124689752cSSteffen Eiden long ret;
413ea9d9716SSteffen Eiden int nr;
4144689752cSSteffen Eiden
415ea9d9716SSteffen Eiden nr = uvio_copy_and_check_ioctl(&uv_ioctl, argp, cmd);
416ea9d9716SSteffen Eiden if (nr < 0)
417ea9d9716SSteffen Eiden return nr;
418ea9d9716SSteffen Eiden
419ea9d9716SSteffen Eiden switch (nr) {
420ea9d9716SSteffen Eiden case UVIO_IOCTL_UVDEV_INFO_NR:
421ea9d9716SSteffen Eiden ret = uvio_uvdev_info(&uv_ioctl);
422ea9d9716SSteffen Eiden break;
423ea9d9716SSteffen Eiden case UVIO_IOCTL_ATT_NR:
4244689752cSSteffen Eiden ret = uvio_attestation(&uv_ioctl);
4254689752cSSteffen Eiden break;
42644567ca2SSteffen Eiden case UVIO_IOCTL_ADD_SECRET_NR:
42744567ca2SSteffen Eiden ret = uvio_add_secret(&uv_ioctl);
42844567ca2SSteffen Eiden break;
429b96b3ce2SSteffen Eiden case UVIO_IOCTL_LIST_SECRETS_NR:
430b96b3ce2SSteffen Eiden ret = uvio_list_secrets(&uv_ioctl);
431b96b3ce2SSteffen Eiden break;
4322d8a26acSSteffen Eiden case UVIO_IOCTL_LOCK_SECRETS_NR:
4332d8a26acSSteffen Eiden ret = uvio_lock_secrets(&uv_ioctl);
4342d8a26acSSteffen Eiden break;
4354689752cSSteffen Eiden default:
4364689752cSSteffen Eiden ret = -ENOIOCTLCMD;
4374689752cSSteffen Eiden break;
4384689752cSSteffen Eiden }
4394689752cSSteffen Eiden if (ret)
4404689752cSSteffen Eiden return ret;
4414689752cSSteffen Eiden
4424689752cSSteffen Eiden if (copy_to_user(argp, &uv_ioctl, sizeof(uv_ioctl)))
4434689752cSSteffen Eiden ret = -EFAULT;
4444689752cSSteffen Eiden
4454689752cSSteffen Eiden return ret;
4464689752cSSteffen Eiden }
4474689752cSSteffen Eiden
4484689752cSSteffen Eiden static const struct file_operations uvio_dev_fops = {
4494689752cSSteffen Eiden .owner = THIS_MODULE,
4504689752cSSteffen Eiden .unlocked_ioctl = uvio_ioctl,
4514689752cSSteffen Eiden .llseek = no_llseek,
4524689752cSSteffen Eiden };
4534689752cSSteffen Eiden
4544689752cSSteffen Eiden static struct miscdevice uvio_dev_miscdev = {
4554689752cSSteffen Eiden .minor = MISC_DYNAMIC_MINOR,
4564689752cSSteffen Eiden .name = UVIO_DEVICE_NAME,
4574689752cSSteffen Eiden .fops = &uvio_dev_fops,
4584689752cSSteffen Eiden };
4594689752cSSteffen Eiden
uvio_dev_exit(void)4604689752cSSteffen Eiden static void __exit uvio_dev_exit(void)
4614689752cSSteffen Eiden {
4624689752cSSteffen Eiden misc_deregister(&uvio_dev_miscdev);
4634689752cSSteffen Eiden }
4644689752cSSteffen Eiden
uvio_dev_init(void)4654689752cSSteffen Eiden static int __init uvio_dev_init(void)
4664689752cSSteffen Eiden {
467ea9d9716SSteffen Eiden set_supp_uv_cmds((unsigned long *)&uvdev_info.supp_uv_cmds);
4684689752cSSteffen Eiden return misc_register(&uvio_dev_miscdev);
4694689752cSSteffen Eiden }
4704689752cSSteffen Eiden
4715fcd0d8aSSteffen Eiden module_cpu_feature_match(S390_CPU_FEATURE_UV, uvio_dev_init);
4724689752cSSteffen Eiden module_exit(uvio_dev_exit);
4734689752cSSteffen Eiden
4744689752cSSteffen Eiden MODULE_AUTHOR("IBM Corporation");
4754689752cSSteffen Eiden MODULE_LICENSE("GPL");
4764689752cSSteffen Eiden MODULE_DESCRIPTION("Ultravisor UAPI driver");
477