From patchwork Fri Mar 4 14:11:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Eiden X-Patchwork-Id: 12769170 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E47F2C433FE for ; Fri, 4 Mar 2022 14:12:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239715AbiCDOND (ORCPT ); Fri, 4 Mar 2022 09:13:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239806AbiCDOMq (ORCPT ); Fri, 4 Mar 2022 09:12:46 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0E2BB1BAF0E; Fri, 4 Mar 2022 06:11:56 -0800 (PST) Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 224ClNGR009570; Fri, 4 Mar 2022 14:11:53 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=NT/rFNOirwFYgYHEeM9iPKz1Ofj9JEuTEwwcrCXSYe0=; b=WnmAvyd9YFrrpY78tUSqmjEgMRt8oFtHWUsjMO70gNSeT1ke2mnbyAUXEAQVl6GGuxRs ScYWzleobnCqd5EUcaCTQ48m2CD5bVU29sHmT6Z0i6wBWyy75WntoyuYkX3uZoUfHsFl bV68Ph5UjeZS87gbhewuQo21hBby+zFTjAIF3JM0J+gYyZwU2b+Q0mvbEVAacFijbEt8 gUC4oxFm5rEin0raJaET/BwG+7fqBT+46ZqQ6Bq6Rpn+Z/CTBQ5cU9NFPJpU5MCgBv/n DQhuB8b4dy4n4LipsWYtXcijejcWKQyahV0bDgvT6LWQ2b1ZEOe9OR+vgupGXkIdbYWf UQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com with ESMTP id 3ekg3rn3p0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:53 +0000 Received: from m0098416.ppops.net (m0098416.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 224DeEwo029487; Fri, 4 Mar 2022 14:11:52 GMT Received: from ppma04fra.de.ibm.com (6a.4a.5195.ip4.static.sl-reverse.com [149.81.74.106]) by mx0b-001b2d01.pphosted.com with ESMTP id 3ekg3rn3mx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:52 +0000 Received: from pps.filterd (ppma04fra.de.ibm.com [127.0.0.1]) by ppma04fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 224E7C8s016037; Fri, 4 Mar 2022 14:11:50 GMT Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by ppma04fra.de.ibm.com with ESMTP id 3ek4k5hn76-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:50 +0000 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 224EBlFP35258688 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 4 Mar 2022 14:11:47 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 56EAB42041; Fri, 4 Mar 2022 14:11:47 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AFFC94203F; Fri, 4 Mar 2022 14:11:44 +0000 (GMT) Received: from localhost.localdomain (unknown [9.114.12.92]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 4 Mar 2022 14:11:44 +0000 (GMT) From: Steffen Eiden To: linux-s390@vger.kernel.org Cc: Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Janosch Frank , David Hildenbrand , Claudio Imbrenda , Shuah Khan , Nico Boehr , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 1/4] drivers/s390/char: Add Ultravisor io device Date: Fri, 4 Mar 2022 09:11:38 -0500 Message-Id: <20220304141141.32767-2-seiden@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220304141141.32767-1-seiden@linux.ibm.com> References: <20220304141141.32767-1-seiden@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: wbCBK1qtZ6al7hNa-FbMOuapVPfyJfzj X-Proofpoint-GUID: cI0i2lbt_wSWj47LxxSZjIDCiI4ykPMx X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-03-04_06,2022-03-04_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 clxscore=1015 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 spamscore=0 phishscore=0 impostorscore=0 mlxlogscore=999 bulkscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2203040077 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org This patch adds a new miscdevice to expose some Ultravisor functions to userspace. Userspace can send IOCTLs to the uvdevice that will then emit a corresponding Ultravisor Call and hands the result over to userspace. The uvdevice is available if the Ultravisor Call facility is present. Userspace can call call the Retrieve Attestation Measurement Ultravisor Call using IOCTLs on the uvdevice. The uvdevice will do some sanity checks first. Then, copy the request data to kernel space, build the UVCB, perform the UV call, and copy the result back to userspace. Signed-off-by: Steffen Eiden Reviewed-by: Janosch Frank Signed-off-by: Steffen Eiden Reviewed-by: Janosch Frank --- MAINTAINERS | 2 + arch/s390/include/asm/uv.h | 23 ++- arch/s390/include/uapi/asm/uvdevice.h | 51 +++++ drivers/s390/char/Kconfig | 10 + drivers/s390/char/Makefile | 1 + drivers/s390/char/uvdevice.c | 264 ++++++++++++++++++++++++++ 6 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 arch/s390/include/uapi/asm/uvdevice.h create mode 100644 drivers/s390/char/uvdevice.c diff --git a/MAINTAINERS b/MAINTAINERS index 777cd6fa2b3d..f32e876f45c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10577,9 +10577,11 @@ F: Documentation/virt/kvm/s390* F: arch/s390/include/asm/gmap.h F: arch/s390/include/asm/kvm* F: arch/s390/include/uapi/asm/kvm* +F: arch/s390/include/uapi/asm/uvdevice.h F: arch/s390/kernel/uv.c F: arch/s390/kvm/ F: arch/s390/mm/gmap.c +F: drivers/s390/char/uvdevice.c F: tools/testing/selftests/kvm/*/s390x/ F: tools/testing/selftests/kvm/s390x/ diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h index 86218382d29c..760dda4024b9 100644 --- a/arch/s390/include/asm/uv.h +++ b/arch/s390/include/asm/uv.h @@ -2,7 +2,7 @@ /* * Ultravisor Interfaces * - * Copyright IBM Corp. 2019 + * Copyright IBM Corp. 2019, 2022 * * Author(s): * Vasily Gorbik @@ -52,6 +52,7 @@ #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 +#define UVC_CMD_RETR_ATTEST 0x1020 /* Bits in installed uv calls */ enum uv_cmds_inst { @@ -76,6 +77,7 @@ enum uv_cmds_inst { BIT_UVC_CMD_UNSHARE_ALL = 20, BIT_UVC_CMD_PIN_PAGE_SHARED = 21, BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, + BIT_UVC_CMD_RETR_ATTEST = 28, }; enum uv_feat_ind { @@ -218,6 +220,25 @@ struct uv_cb_share { u64 reserved28; } __packed __aligned(8); +/* Retrieve Attestation Measurement */ +struct uv_cb_attest { + struct uv_cb_header header; /* 0x0000 */ + u64 reserved08[2]; /* 0x0008 */ + u64 arcb_addr; /* 0x0018 */ + u64 cont_token; /* 0x0020 */ + u8 reserved28[6]; /* 0x0028 */ + u16 user_data_len; /* 0x002e */ + u8 user_data[256]; /* 0x0030 */ + u32 reserved130[3]; /* 0x0130 */ + u32 meas_len; /* 0x013c */ + u64 meas_addr; /* 0x0140 */ + u8 config_uid[16]; /* 0x0148 */ + u32 reserved158; /* 0x0158 */ + u32 add_data_len; /* 0x015c */ + u64 add_data_addr; /* 0x0160 */ + u64 reserved168[4]; /* 0x0168 */ +} __packed __aligned(8); + static inline int __uv_call(unsigned long r1, unsigned long r2) { int cc; diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h new file mode 100644 index 000000000000..d40f69345c75 --- /dev/null +++ b/arch/s390/include/uapi/asm/uvdevice.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright IBM Corp. 2022 + * Author(s): Steffen Eiden + */ +#ifndef __S390X_ASM_UVDEVICE_H +#define __S390X_ASM_UVDEVICE_H + +#include + +struct uvio_ioctl_cb { + __u32 flags; + __u16 uv_rc; /* UV header rc value */ + __u16 uv_rrc; /* UV header rrc value */ + __u64 argument_addr; /* Userspace address of uvio argument */ + __u32 argument_len; + __u8 reserved14[0x40 - 0x14]; /* must be zero */ +}; + +#define UVIO_ATT_USER_DATA_LEN 0x100 +#define UVIO_ATT_UID_LEN 0x10 +struct uvio_attest { + __u64 arcb_addr; /* 0x0000 */ + __u64 meas_addr; /* 0x0008 */ + __u64 add_data_addr; /* 0x0010 */ + __u8 user_data[UVIO_ATT_USER_DATA_LEN]; /* 0x0018 */ + __u8 config_uid[UVIO_ATT_UID_LEN]; /* 0x0118 */ + __u32 arcb_len; /* 0x0128 */ + __u32 meas_len; /* 0x012c */ + __u32 add_data_len; /* 0x0130 */ + __u16 user_data_len; /* 0x0134 */ + __u16 reserved136; /* 0x0136 */ +}; + +/* + * The following max values define an upper length for the IOCTL in/out buffers. + * However, they do not represent the maximum the Ultravisor allows which is + * often way smaller. By allowing larger buffer sizes we hopefully do not need + * to update the code with every machine update. It is therefore possible for + * userspace to request more memory than actually used by kernel/UV. + */ +#define UVIO_ATT_ARCB_MAX_LEN 0x100000 +#define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000 +#define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 + +#define UVIO_DEVICE_NAME "uv" +#define UVIO_TYPE_UVC 'u' + +#define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb) + +#endif /* __S390X_ASM_UVDEVICE_H */ diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 6cc4b19acf85..c8fa466815ac 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -184,3 +184,13 @@ config S390_VMUR depends on S390 help Character device driver for z/VM reader, puncher and printer. + +config S390_UV_UAPI + def_tristate y + prompt "Ultravisor userspace API" + help + Selecting exposes parts of the UV interface to userspace + by providing a misc character device at /dev/uv. + Using IOCTLs one can interact with the UV. + The device is only available if the Ultravisor + Facility (158) is present. diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index c6fdb81a068a..ce32270082f5 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_MONREADER) += monreader.o obj-$(CONFIG_MONWRITER) += monwriter.o obj-$(CONFIG_S390_VMUR) += vmur.o obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o +obj-$(CONFIG_S390_UV_UAPI) += uvdevice.o hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o obj-$(CONFIG_HMC_DRV) += hmcdrv.o diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c new file mode 100644 index 000000000000..b720dc8d0bd9 --- /dev/null +++ b/drivers/s390/char/uvdevice.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright IBM Corp. 2022 + * Author(s): Steffen Eiden + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +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; + + ret = -ENOMEM; + uv_ioctl = vzalloc(sizeof(*uv_ioctl)); + if (!uv_ioctl) + goto out; + + switch (cmd) { + case UVIO_IOCTL_ATT: + ret = uvio_copy_and_check_ioctl(uv_ioctl, argp); + if (ret) + goto out; + ret = uvio_attestation(uv_ioctl); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + if (ret) + goto out; + + if (copy_to_user(argp, uv_ioctl, sizeof(*uv_ioctl))) + ret = -EFAULT; + + out: + vfree(uv_ioctl); + 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"); From patchwork Fri Mar 4 14:11:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Eiden X-Patchwork-Id: 12769171 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD67EC4332F for ; Fri, 4 Mar 2022 14:12:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237921AbiCDOND (ORCPT ); Fri, 4 Mar 2022 09:13:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239813AbiCDOMs (ORCPT ); Fri, 4 Mar 2022 09:12:48 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4C8941BAF25; Fri, 4 Mar 2022 06:11:58 -0800 (PST) Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 224Btadn024411; Fri, 4 Mar 2022 14:11:56 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=nUscuEfE/jpVEFUSLNhY5DExzQWSb0qfl9VDkN2TDIU=; b=PavoTpj+aTYvfACRaGXdiKIU2zJ9NMuqf52ZsbQ3MFPoU9g34RT8ZRPhnSSlP3+/b68d grB7DajeOXCpSNxKnYK8dak7cQJEEHwHbKwVt66spYVaeSOTM9jVEXBIyPnjXLwSDiWm chFp5RlFb28PVhlHLcxNUIMBzDRXCwyPCEzVHqbjxeF8hy3xzJh4rxHhXpQSSOwSX7yc K+oA/hBSX+/j6/3A/mm81xIAFHjQ5pqtABxrnFxdpFcgLoc5uHnb72C0PWMp+UxDKO1g BBwCQn6whsuZHcolUECwJRDWKz96Ucgv2mcw07paKycwlTCfkWob4YrrI37wMdZtsa6Z nQ== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekjavakec-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:56 +0000 Received: from m0098394.ppops.net (m0098394.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 224E3ws2007283; Fri, 4 Mar 2022 14:11:56 GMT Received: from ppma03fra.de.ibm.com (6b.4a.5195.ip4.static.sl-reverse.com [149.81.74.107]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekjavakdg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:56 +0000 Received: from pps.filterd (ppma03fra.de.ibm.com [127.0.0.1]) by ppma03fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 224E92Jn026804; Fri, 4 Mar 2022 14:11:53 GMT Received: from b06cxnps4075.portsmouth.uk.ibm.com (d06relay12.portsmouth.uk.ibm.com [9.149.109.197]) by ppma03fra.de.ibm.com with ESMTP id 3ek4k41nf7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:53 +0000 Received: from d06av24.portsmouth.uk.ibm.com (d06av24.portsmouth.uk.ibm.com [9.149.105.60]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 224EBosP38666628 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 4 Mar 2022 14:11:50 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3F5B042042; Fri, 4 Mar 2022 14:11:50 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A2A2242049; Fri, 4 Mar 2022 14:11:47 +0000 (GMT) Received: from localhost.localdomain (unknown [9.114.12.92]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 4 Mar 2022 14:11:47 +0000 (GMT) From: Steffen Eiden To: linux-s390@vger.kernel.org Cc: Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Janosch Frank , David Hildenbrand , Claudio Imbrenda , Shuah Khan , Nico Boehr , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 2/4] drivers/s390/char: Add Query Ultravisor Information to uvdevice Date: Fri, 4 Mar 2022 09:11:39 -0500 Message-Id: <20220304141141.32767-3-seiden@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220304141141.32767-1-seiden@linux.ibm.com> References: <20220304141141.32767-1-seiden@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: izywVKffqj_lAOiH0rSytcboxF3rI9Sc X-Proofpoint-ORIG-GUID: Jt4KBbCixOzmWE4FrpSwt2fvh_OVU-rM X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-03-04_06,2022-03-04_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 bulkscore=0 impostorscore=0 adultscore=0 phishscore=0 mlxscore=0 lowpriorityscore=0 mlxlogscore=743 suspectscore=0 spamscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2203040077 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org This patch enables userspace to call the Query Ultravisor Information Ultravisor Call using IOCTLs on the uvdevice. The uvdevice will do some sanity checks first, build the UVCB, perform the UV call, and copy the result to userspace. Signed-off-by: Steffen Eiden Reviewed-by: Janosch Frank --- arch/s390/include/uapi/asm/uvdevice.h | 2 + drivers/s390/char/uvdevice.c | 56 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/arch/s390/include/uapi/asm/uvdevice.h b/arch/s390/include/uapi/asm/uvdevice.h index d40f69345c75..7520bdde3102 100644 --- a/arch/s390/include/uapi/asm/uvdevice.h +++ b/arch/s390/include/uapi/asm/uvdevice.h @@ -42,10 +42,12 @@ struct uvio_attest { #define UVIO_ATT_ARCB_MAX_LEN 0x100000 #define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000 #define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 +#define UVIO_QUI_MAX_LEN 0x8000 #define UVIO_DEVICE_NAME "uv" #define UVIO_TYPE_UVC 'u' #define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb) +#define UVIO_IOCTL_QUI _IOWR(UVIO_TYPE_UVC, 0x02, struct uvio_ioctl_cb) #endif /* __S390X_ASM_UVDEVICE_H */ diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c index b720dc8d0bd9..cfce8c5999e6 100644 --- a/drivers/s390/char/uvdevice.c +++ b/drivers/s390/char/uvdevice.c @@ -31,6 +31,55 @@ #include #include +/** + * uvio_qui() - Perform a Query Ultravisor Information UVC. + * + * uv_ioctl: ioctl control block + * + * uvio_qui() does a Query Ultravisor Information (QUI) Ultravisor Call. + * It creates the uvc qui request and sends it to the Ultravisor. After that + * it copies the response to userspace and fills the rc and rrc of uv_ioctl + * uv_call with the response values of the Ultravisor. + * + * Create the UVC structure, send the UVC to UV and write the response in the ioctl struct. + * + * Return: 0 on success or a negative error code on error. + */ +static int uvio_qui(struct uvio_ioctl_cb *uv_ioctl) +{ + u8 __user *user_buf_addr = (__user u8 *)uv_ioctl->argument_addr; + size_t user_buf_len = uv_ioctl->argument_len; + struct uv_cb_header *uvcb_qui = NULL; + int ret; + + /* + * Do not check for a too small buffer. If userspace provides a buffer + * that is too small the Ultravisor will complain. + */ + ret = -EINVAL; + if (!user_buf_len || user_buf_len > UVIO_QUI_MAX_LEN) + goto out; + ret = -ENOMEM; + uvcb_qui = kvzalloc(user_buf_len, GFP_KERNEL); + if (!uvcb_qui) + goto out; + uvcb_qui->len = user_buf_len; + uvcb_qui->cmd = UVC_CMD_QUI; + + uv_call(0, (u64)uvcb_qui); + + ret = -EFAULT; + if (copy_to_user(user_buf_addr, uvcb_qui, uvcb_qui->len)) + goto out; + uv_ioctl->uv_rc = uvcb_qui->rc; + uv_ioctl->uv_rrc = uvcb_qui->rrc; + + ret = 0; +out: + kvfree(uvcb_qui); + return ret; +} + static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb, u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest) { @@ -217,6 +266,13 @@ static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto out; ret = uvio_attestation(uv_ioctl); break; + case UVIO_IOCTL_QUI: + ret = uvio_copy_and_check_ioctl(uv_ioctl, argp); + if (ret) + goto out; + ret = uvio_qui(uv_ioctl); + break; + default: ret = -ENOIOCTLCMD; break; From patchwork Fri Mar 4 14:11:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Eiden X-Patchwork-Id: 12769172 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3530BC43219 for ; Fri, 4 Mar 2022 14:12:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239803AbiCDOND (ORCPT ); Fri, 4 Mar 2022 09:13:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37496 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239851AbiCDOMv (ORCPT ); Fri, 4 Mar 2022 09:12:51 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E96801BB709; Fri, 4 Mar 2022 06:12:01 -0800 (PST) Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 224BtfYq025081; Fri, 4 Mar 2022 14:11:59 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=/Oz15d53pTs9hoMiFZC+TF4bEzDc54nbKzqXWKsjF5k=; b=D+RDKngq4Yw2FOuyzMUfUgOU/zjWfZO5pHoPTkwIDsDrwGvCTGF8v7dM6a1zuZK4UunO dptXyI8lbrT17mVRALeJ+G0PXuQlxjSFVwNJUkolnVC8n4ncoSTmim9qc76fdAHL/svR lt1PN2ZHtuJn+dAQgXFX4xZXqKQPJYhJu+AN3Z99k2C5cpmuX2dOEQ5l2/i9/3iRArbr ZQrvCI4vgJ4AzDXByUQiI6roa7Lgd63K5cEJZW9FBwEVMnmNu2FnyTKr7XpilOJmHJKQ rl5madzINyOhyI0iKYfOXFGzZyeaWA3qExuyRCOJzaONga1uLDLKcaQv59UFsHFQ3LxQ Bg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekjavakgp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:59 +0000 Received: from m0098394.ppops.net (m0098394.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 224DrufL006823; Fri, 4 Mar 2022 14:11:59 GMT Received: from ppma02fra.de.ibm.com (47.49.7a9f.ip4.static.sl-reverse.com [159.122.73.71]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekjavaker-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:58 +0000 Received: from pps.filterd (ppma02fra.de.ibm.com [127.0.0.1]) by ppma02fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 224E75Y4029287; Fri, 4 Mar 2022 14:11:56 GMT Received: from b06avi18626390.portsmouth.uk.ibm.com (b06avi18626390.portsmouth.uk.ibm.com [9.149.26.192]) by ppma02fra.de.ibm.com with ESMTP id 3ek4k4hnf9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:56 +0000 Received: from d06av24.portsmouth.uk.ibm.com (d06av24.portsmouth.uk.ibm.com [9.149.105.60]) by b06avi18626390.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 224E0rBp50069860 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 4 Mar 2022 14:00:53 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2C68B42041; Fri, 4 Mar 2022 14:11:53 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8E70B42045; Fri, 4 Mar 2022 14:11:50 +0000 (GMT) Received: from localhost.localdomain (unknown [9.114.12.92]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 4 Mar 2022 14:11:50 +0000 (GMT) From: Steffen Eiden To: linux-s390@vger.kernel.org Cc: Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Janosch Frank , David Hildenbrand , Claudio Imbrenda , Shuah Khan , Nico Boehr , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 3/4] selftests: drivers/s390x: Add uvdevice tests Date: Fri, 4 Mar 2022 09:11:40 -0500 Message-Id: <20220304141141.32767-4-seiden@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220304141141.32767-1-seiden@linux.ibm.com> References: <20220304141141.32767-1-seiden@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: -YGKsGvfv60rhoxN7PpTv7PGsZn2AfzZ X-Proofpoint-ORIG-GUID: -_3IokWpvLqXJRymzyA5CMVr__ezxzxf X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-03-04_06,2022-03-04_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 bulkscore=0 impostorscore=0 adultscore=0 phishscore=0 mlxscore=0 lowpriorityscore=0 mlxlogscore=999 suspectscore=0 spamscore=0 priorityscore=1501 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2203040077 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Adds some selftests to test ioctl error paths of the uv-uapi. The Kconfig S390_UV_UAPI must be selected and the Ultravisor facility must be available. The test can be executed by non-root, however, the uvdevice special file /dev/uv must be accessible for reading and writing which may imply root privileges. ./test-uv-device TAP version 13 1..6 # Starting 6 tests from 3 test cases. # RUN uvio_fixture.att.fault_ioctl_arg ... # OK uvio_fixture.att.fault_ioctl_arg ok 1 uvio_fixture.att.fault_ioctl_arg # RUN uvio_fixture.att.fault_uvio_arg ... # OK uvio_fixture.att.fault_uvio_arg ok 2 uvio_fixture.att.fault_uvio_arg # RUN uvio_fixture.att.inval_ioctl_cb ... # OK uvio_fixture.att.inval_ioctl_cb ok 3 uvio_fixture.att.inval_ioctl_cb # RUN uvio_fixture.att.inval_ioctl_cmd ... # OK uvio_fixture.att.inval_ioctl_cmd ok 4 uvio_fixture.att.inval_ioctl_cmd # RUN attest_fixture.att_inval_request ... # OK attest_fixture.att_inval_request ok 5 attest_fixture.att_inval_request # RUN attest_fixture.att_inval_addr ... # OK attest_fixture.att_inval_addr ok 6 attest_fixture.att_inval_addr # PASSED: 6 / 6 tests passed. # Totals: pass:6 fail:0 xfail:0 xpass:0 skip:0 error:0 Signed-off-by: Steffen Eiden Acked-by: Janosch Frank --- MAINTAINERS | 1 + tools/testing/selftests/Makefile | 1 + tools/testing/selftests/drivers/.gitignore | 1 + .../selftests/drivers/s390x/uvdevice/Makefile | 22 ++ .../selftests/drivers/s390x/uvdevice/config | 1 + .../drivers/s390x/uvdevice/test_uvdevice.c | 276 ++++++++++++++++++ 6 files changed, 302 insertions(+) create mode 100644 tools/testing/selftests/drivers/s390x/uvdevice/Makefile create mode 100644 tools/testing/selftests/drivers/s390x/uvdevice/config create mode 100644 tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c diff --git a/MAINTAINERS b/MAINTAINERS index f32e876f45c2..7fdf0fa006db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10582,6 +10582,7 @@ F: arch/s390/kernel/uv.c F: arch/s390/kvm/ F: arch/s390/mm/gmap.c F: drivers/s390/char/uvdevice.c +F: tools/testing/selftests/drivers/s390x/uvdevice/ F: tools/testing/selftests/kvm/*/s390x/ F: tools/testing/selftests/kvm/s390x/ diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index d08fe4cfe811..d454faf936c3 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -10,6 +10,7 @@ TARGETS += core TARGETS += cpufreq TARGETS += cpu-hotplug TARGETS += drivers/dma-buf +TARGETS += drivers/s390x/uvdevice TARGETS += efivarfs TARGETS += exec TARGETS += filesystems diff --git a/tools/testing/selftests/drivers/.gitignore b/tools/testing/selftests/drivers/.gitignore index ca74f2e1c719..09e23b5afa96 100644 --- a/tools/testing/selftests/drivers/.gitignore +++ b/tools/testing/selftests/drivers/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only /dma-buf/udmabuf +/s390x/uvdevice/test_uvdevice diff --git a/tools/testing/selftests/drivers/s390x/uvdevice/Makefile b/tools/testing/selftests/drivers/s390x/uvdevice/Makefile new file mode 100644 index 000000000000..5e701d2708d4 --- /dev/null +++ b/tools/testing/selftests/drivers/s390x/uvdevice/Makefile @@ -0,0 +1,22 @@ +include ../../../../../build/Build.include + +UNAME_M := $(shell uname -m) + +ifneq ($(UNAME_M),s390x) +nothing: +.PHONY: all clean run_tests install +.SILENT: +else + +TEST_GEN_PROGS := test_uvdevice + +top_srcdir ?= ../../../../../.. +KSFT_KHDR_INSTALL := 1 +khdr_dir = $(top_srcdir)/usr/include +LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include + +CFLAGS += -Wall -Werror -static -I$(khdr_dir) -I$(LINUX_TOOL_ARCH_INCLUDE) + +include ../../../lib.mk + +endif diff --git a/tools/testing/selftests/drivers/s390x/uvdevice/config b/tools/testing/selftests/drivers/s390x/uvdevice/config new file mode 100644 index 000000000000..f28a04b99eff --- /dev/null +++ b/tools/testing/selftests/drivers/s390x/uvdevice/config @@ -0,0 +1 @@ +CONFIG_S390_UV_UAPI=y diff --git a/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c b/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c new file mode 100644 index 000000000000..ea0cdc37b44f --- /dev/null +++ b/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * selftest for the Ultravisor UAPI device + * + * Copyright IBM Corp. 2022 + * Author(s): Steffen Eiden + */ + +#include +#include +#include +#include +#include + +#include + +#include "../../../kselftest_harness.h" + +#define UV_PATH "/dev/uv" +#define BUFFER_SIZE 0x200 +FIXTURE(uvio_fixture) { + int uv_fd; + struct uvio_ioctl_cb uvio_ioctl; + uint8_t buffer[BUFFER_SIZE]; + __u64 fault_page; +}; + +FIXTURE_VARIANT(uvio_fixture) { + unsigned long ioctl_cmd; + uint32_t arg_size; +}; + +FIXTURE_VARIANT_ADD(uvio_fixture, att) { + .ioctl_cmd = UVIO_IOCTL_ATT, + .arg_size = sizeof(struct uvio_attest), +}; + +FIXTURE_SETUP(uvio_fixture) +{ + self->uv_fd = open(UV_PATH, O_ACCMODE); + + self->uvio_ioctl.argument_addr = (__u64)self->buffer; + self->uvio_ioctl.argument_len = variant->arg_size; + self->fault_page = + (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0); +} + +FIXTURE_TEARDOWN(uvio_fixture) +{ + if (self->uv_fd) + close(self->uv_fd); + munmap((void *)self->fault_page, (size_t)getpagesize()); +} + +TEST_F(uvio_fixture, fault_ioctl_arg) +{ + int rc, errno_cache; + + rc = ioctl(self->uv_fd, variant->ioctl_cmd, NULL); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); + + rc = ioctl(self->uv_fd, variant->ioctl_cmd, self->fault_page); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); +} + +TEST_F(uvio_fixture, fault_uvio_arg) +{ + int rc, errno_cache; + + self->uvio_ioctl.argument_addr = 0; + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); + + self->uvio_ioctl.argument_addr = self->fault_page; + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); +} + +/* + * Test to verify that IOCTLs with invalid values in the ioctl_control block + * are rejected. + */ +TEST_F(uvio_fixture, inval_ioctl_cb) +{ + int rc, errno_cache; + + self->uvio_ioctl.argument_len = 0; + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + + self->uvio_ioctl.argument_len = (uint32_t)-1; + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + self->uvio_ioctl.argument_len = variant->arg_size; + + self->uvio_ioctl.flags = (uint32_t)-1; + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + self->uvio_ioctl.flags = 0; + + memset(self->uvio_ioctl.reserved14, 0xff, sizeof(self->uvio_ioctl.reserved14)); + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + + memset(&self->uvio_ioctl, 0x11, sizeof(self->uvio_ioctl)); + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); + ASSERT_EQ(rc, -1); +} + +TEST_F(uvio_fixture, inval_ioctl_cmd) +{ + int rc, errno_cache; + uint8_t nr = _IOC_NR(variant->ioctl_cmd); + unsigned long cmds[] = { + _IOWR('a', nr, struct uvio_ioctl_cb), + _IOWR(UVIO_TYPE_UVC, nr, int), + _IO(UVIO_TYPE_UVC, nr), + _IOR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb), + _IOW(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb), + }; + + for (size_t i = 0; i < ARRAY_SIZE(cmds); i++) { + rc = ioctl(self->uv_fd, cmds[i], &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, ENOTTY); + } +} + +struct test_attest_buffer { + uint8_t arcb[0x180]; + uint8_t meas[64]; + uint8_t add[32]; +}; + +FIXTURE(attest_fixture) { + int uv_fd; + struct uvio_ioctl_cb uvio_ioctl; + struct uvio_attest uvio_attest; + struct test_attest_buffer attest_buffer; + __u64 fault_page; +}; + +FIXTURE_SETUP(attest_fixture) +{ + self->uv_fd = open(UV_PATH, O_ACCMODE); + + self->uvio_ioctl.argument_addr = (__u64)&self->uvio_attest; + self->uvio_ioctl.argument_len = sizeof(self->uvio_attest); + + self->uvio_attest.arcb_addr = (__u64)&self->attest_buffer.arcb; + self->uvio_attest.arcb_len = sizeof(self->attest_buffer.arcb); + + self->uvio_attest.meas_addr = (__u64)&self->attest_buffer.meas; + self->uvio_attest.meas_len = sizeof(self->attest_buffer.meas); + + self->uvio_attest.add_data_addr = (__u64)&self->attest_buffer.add; + self->uvio_attest.add_data_len = sizeof(self->attest_buffer.add); + self->fault_page = + (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0); +} + +FIXTURE_TEARDOWN(attest_fixture) +{ + if (self->uv_fd) + close(self->uv_fd); + munmap((void *)self->fault_page, (size_t)getpagesize()); +} + +static void att_inval_sizes_test(uint32_t *size, uint32_t max_size, bool test_zero, + struct __test_metadata *_metadata, + FIXTURE_DATA(attest_fixture) *self) +{ + int rc, errno_cache; + uint32_t tmp = *size; + + if (test_zero) { + *size = 0; + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + } + *size = max_size + 1; + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + *size = tmp; +} + +/* + * Test to verify that attestation IOCTLs with invalid values in the UVIO + * attestation control block are rejected. + */ +TEST_F(attest_fixture, att_inval_request) +{ + int rc, errno_cache; + + att_inval_sizes_test(&self->uvio_attest.add_data_len, UVIO_ATT_ADDITIONAL_MAX_LEN, + false, _metadata, self); + att_inval_sizes_test(&self->uvio_attest.meas_len, UVIO_ATT_MEASUREMENT_MAX_LEN, + true, _metadata, self); + att_inval_sizes_test(&self->uvio_attest.arcb_len, UVIO_ATT_ARCB_MAX_LEN, + true, _metadata, self); + + self->uvio_attest.reserved136 = (uint16_t)-1; + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EINVAL); + + memset(&self->uvio_attest, 0x11, sizeof(self->uvio_attest)); + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + ASSERT_EQ(rc, -1); +} + +static void att_inval_addr_test(__u64 *addr, struct __test_metadata *_metadata, + FIXTURE_DATA(attest_fixture) *self) +{ + int rc, errno_cache; + __u64 tmp = *addr; + + *addr = 0; + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); + *addr = self->fault_page; + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); + errno_cache = errno; + ASSERT_EQ(rc, -1); + ASSERT_EQ(errno_cache, EFAULT); + *addr = tmp; +} + +TEST_F(attest_fixture, att_inval_addr) +{ + att_inval_addr_test(&self->uvio_attest.arcb_addr, _metadata, self); + att_inval_addr_test(&self->uvio_attest.add_data_addr, _metadata, self); + att_inval_addr_test(&self->uvio_attest.meas_addr, _metadata, self); +} + +static void __attribute__((constructor)) __constructor_order_last(void) +{ + if (!__constructor_order) + __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; +} + +int main(int argc, char **argv) +{ + int fd = open(UV_PATH, O_ACCMODE); + + if (fd < 0) + ksft_exit_skip("No uv-device or cannot access " UV_PATH "\n" + "Enable CONFIG_S390_UV_UAPI and check the access rights on " + UV_PATH ".\n"); + close(fd); + return test_harness_run(argc, argv); +} From patchwork Fri Mar 4 14:11:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffen Eiden X-Patchwork-Id: 12769173 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80797C4321E for ; Fri, 4 Mar 2022 14:12:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233974AbiCDONE (ORCPT ); Fri, 4 Mar 2022 09:13:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239861AbiCDOMv (ORCPT ); Fri, 4 Mar 2022 09:12:51 -0500 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1CD211BAF0E; Fri, 4 Mar 2022 06:12:03 -0800 (PST) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 224DQ4vw030810; Fri, 4 Mar 2022 14:12:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=pGmYGwb79apXudBWe4k2mRuaKzUVH0A8Evs3CZ+9Nhs=; b=Tj10yMLrKB85pP3n/RGMgzoJaBUhWQMfpVGEnOrgJjrK4iesVHS6Iea2tdMrb7Kqxj9P ku07n1fA9kIHfV7srCurdGdbgoTuWMSUn88mlNkf+cUfgBffDFx1yG01W8Mjawd7ARpu 8x1qYENSa51pNRCD/6G1q3FNptl6OZzueE2YNc2djF+yKXiLO42wU8iDQ/ri+TzrCTjF YnXmz8fTcT6Bo3WG+kV5PvJWZIznmvgEowEThmJ1weM2mXeXjlMbE4tHez8wI9V1nc7q f57Z3k/PY9ZMtc1MMpcPoidXgosMoUCHdrL8aN705gj1gIAD/nDIzzqx6OZKdxuzIp9P 4A== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekgwgv73s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:12:02 +0000 Received: from m0098410.ppops.net (m0098410.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 224E5YbX012333; Fri, 4 Mar 2022 14:12:02 GMT Received: from ppma01fra.de.ibm.com (46.49.7a9f.ip4.static.sl-reverse.com [159.122.73.70]) by mx0a-001b2d01.pphosted.com with ESMTP id 3ekgwgv72k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:12:01 +0000 Received: from pps.filterd (ppma01fra.de.ibm.com [127.0.0.1]) by ppma01fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 224E7QO0004051; Fri, 4 Mar 2022 14:11:59 GMT Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by ppma01fra.de.ibm.com with ESMTP id 3ek4k81nej-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 04 Mar 2022 14:11:59 +0000 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 224EBuGs52625702 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 4 Mar 2022 14:11:56 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5D01E42042; Fri, 4 Mar 2022 14:11:56 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7F0BE42041; Fri, 4 Mar 2022 14:11:53 +0000 (GMT) Received: from localhost.localdomain (unknown [9.114.12.92]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 4 Mar 2022 14:11:53 +0000 (GMT) From: Steffen Eiden To: linux-s390@vger.kernel.org Cc: Heiko Carstens , Vasily Gorbik , Christian Borntraeger , Alexander Gordeev , Janosch Frank , David Hildenbrand , Claudio Imbrenda , Shuah Khan , Nico Boehr , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH v3 4/4] selftests: drivers/s390x: Add uvdevice QUI tests Date: Fri, 4 Mar 2022 09:11:41 -0500 Message-Id: <20220304141141.32767-5-seiden@linux.ibm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220304141141.32767-1-seiden@linux.ibm.com> References: <20220304141141.32767-1-seiden@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: s_IpDuoY74pg2aeZrn5jeNC6EYW4Zrdr X-Proofpoint-ORIG-GUID: pgKV1ARvP8UgVWrTGqVt2G-3-wRewzHR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.64.514 definitions=2022-03-04_06,2022-03-04_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 phishscore=0 mlxscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 adultscore=0 mlxlogscore=999 bulkscore=0 spamscore=0 priorityscore=1501 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2202240000 definitions=main-2203040077 Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Add test variant to also verify that QUI-error paths are working as intended. ./test-uv-device TAP version 13 1..10 # Starting 10 tests from 4 test cases. # RUN uvio_fixture.qui.fault_ioctl_arg ... # OK uvio_fixture.qui.fault_ioctl_arg ok 1 uvio_fixture.qui.fault_ioctl_arg # RUN uvio_fixture.qui.fault_uvio_arg ... # OK uvio_fixture.qui.fault_uvio_arg ok 2 uvio_fixture.qui.fault_uvio_arg # RUN uvio_fixture.qui.inval_ioctl_cb ... # OK uvio_fixture.qui.inval_ioctl_cb ok 3 uvio_fixture.qui.inval_ioctl_cb # RUN uvio_fixture.qui.inval_ioctl_cmd ... # OK uvio_fixture.qui.inval_ioctl_cmd ok 4 uvio_fixture.qui.inval_ioctl_cmd # RUN uvio_fixture.att.fault_ioctl_arg ... # OK uvio_fixture.att.fault_ioctl_arg ok 5 uvio_fixture.att.fault_ioctl_arg # RUN uvio_fixture.att.fault_uvio_arg ... # OK uvio_fixture.att.fault_uvio_arg ok 6 uvio_fixture.att.fault_uvio_arg # RUN uvio_fixture.att.inval_ioctl_cb ... # OK uvio_fixture.att.inval_ioctl_cb ok 7 uvio_fixture.att.inval_ioctl_cb # RUN uvio_fixture.att.inval_ioctl_cmd ... # OK uvio_fixture.att.inval_ioctl_cmd ok 8 uvio_fixture.att.inval_ioctl_cmd # RUN attest_fixture.att_inval_request ... # OK attest_fixture.att_inval_request ok 9 attest_fixture.att_inval_request # RUN attest_fixture.att_inval_addr ... # OK attest_fixture.att_inval_addr ok 10 attest_fixture.att_inval_addr # PASSED: 10 / 10 tests passed. # Totals: pass:10 fail:0 xfail:0 xpass:0 skip:0 error:0 Signed-off-by: Steffen Eiden Acked-by: Janosch Frank --- .../testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c b/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c index ea0cdc37b44f..44a6fbefc156 100644 --- a/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c +++ b/tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c @@ -30,6 +30,11 @@ FIXTURE_VARIANT(uvio_fixture) { uint32_t arg_size; }; +FIXTURE_VARIANT_ADD(uvio_fixture, qui) { + .ioctl_cmd = UVIO_IOCTL_QUI, + .arg_size = BUFFER_SIZE, +}; + FIXTURE_VARIANT_ADD(uvio_fixture, att) { .ioctl_cmd = UVIO_IOCTL_ATT, .arg_size = sizeof(struct uvio_attest),