Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kvm-s390-next-5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux into HEAD

KVM: s390: Fix and feature for 5.19

- ultravisor communication device driver
- fix TEID on terminating storage key ops

+714 -6
+6
Documentation/virt/kvm/api.rst
··· 3814 3814 error number indicating the type of exception. This exception is also 3815 3815 raised directly at the corresponding VCPU if the flag 3816 3816 KVM_S390_MEMOP_F_INJECT_EXCEPTION is set. 3817 + On protection exceptions, unless specified otherwise, the injected 3818 + translation-exception identifier (TEID) indicates suppression. 3817 3819 3818 3820 If the KVM_S390_MEMOP_F_SKEY_PROTECTION flag is set, storage key 3819 3821 protection is also in effect and may cause exceptions if accesses are 3820 3822 prohibited given the access key designated by "key"; the valid range is 0..15. 3821 3823 KVM_S390_MEMOP_F_SKEY_PROTECTION is available if KVM_CAP_S390_MEM_OP_EXTENSION 3822 3824 is > 0. 3825 + Since the accessed memory may span multiple pages and those pages might have 3826 + different storage keys, it is possible that a protection exception occurs 3827 + after memory has been modified. In this case, if the exception is injected, 3828 + the TEID does not indicate suppression. 3823 3829 3824 3830 Absolute read/write: 3825 3831 ^^^^^^^^^^^^^^^^^^^^
+3
MAINTAINERS
··· 10785 10785 F: arch/s390/include/asm/gmap.h 10786 10786 F: arch/s390/include/asm/kvm* 10787 10787 F: arch/s390/include/uapi/asm/kvm* 10788 + F: arch/s390/include/uapi/asm/uvdevice.h 10788 10789 F: arch/s390/kernel/uv.c 10789 10790 F: arch/s390/kvm/ 10790 10791 F: arch/s390/mm/gmap.c 10792 + F: drivers/s390/char/uvdevice.c 10793 + F: tools/testing/selftests/drivers/s390x/uvdevice/ 10791 10794 F: tools/testing/selftests/kvm/*/s390x/ 10792 10795 F: tools/testing/selftests/kvm/s390x/ 10793 10796
+22 -1
arch/s390/include/asm/uv.h
··· 2 2 /* 3 3 * Ultravisor Interfaces 4 4 * 5 - * Copyright IBM Corp. 2019 5 + * Copyright IBM Corp. 2019, 2022 6 6 * 7 7 * Author(s): 8 8 * Vasily Gorbik <gor@linux.ibm.com> ··· 52 52 #define UVC_CMD_UNPIN_PAGE_SHARED 0x0342 53 53 #define UVC_CMD_SET_SHARED_ACCESS 0x1000 54 54 #define UVC_CMD_REMOVE_SHARED_ACCESS 0x1001 55 + #define UVC_CMD_RETR_ATTEST 0x1020 55 56 56 57 /* Bits in installed uv calls */ 57 58 enum uv_cmds_inst { ··· 77 76 BIT_UVC_CMD_UNSHARE_ALL = 20, 78 77 BIT_UVC_CMD_PIN_PAGE_SHARED = 21, 79 78 BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, 79 + BIT_UVC_CMD_RETR_ATTEST = 28, 80 80 }; 81 81 82 82 enum uv_feat_ind { ··· 219 217 u64 reserved08[3]; 220 218 u64 paddr; 221 219 u64 reserved28; 220 + } __packed __aligned(8); 221 + 222 + /* Retrieve Attestation Measurement */ 223 + struct uv_cb_attest { 224 + struct uv_cb_header header; /* 0x0000 */ 225 + u64 reserved08[2]; /* 0x0008 */ 226 + u64 arcb_addr; /* 0x0018 */ 227 + u64 cont_token; /* 0x0020 */ 228 + u8 reserved28[6]; /* 0x0028 */ 229 + u16 user_data_len; /* 0x002e */ 230 + u8 user_data[256]; /* 0x0030 */ 231 + u32 reserved130[3]; /* 0x0130 */ 232 + u32 meas_len; /* 0x013c */ 233 + u64 meas_addr; /* 0x0140 */ 234 + u8 config_uid[16]; /* 0x0148 */ 235 + u32 reserved158; /* 0x0158 */ 236 + u32 add_data_len; /* 0x015c */ 237 + u64 add_data_addr; /* 0x0160 */ 238 + u64 reserved168[4]; /* 0x0168 */ 222 239 } __packed __aligned(8); 223 240 224 241 static inline int __uv_call(unsigned long r1, unsigned long r2)
+51
arch/s390/include/uapi/asm/uvdevice.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* 3 + * Copyright IBM Corp. 2022 4 + * Author(s): Steffen Eiden <seiden@linux.ibm.com> 5 + */ 6 + #ifndef __S390_ASM_UVDEVICE_H 7 + #define __S390_ASM_UVDEVICE_H 8 + 9 + #include <linux/types.h> 10 + 11 + struct uvio_ioctl_cb { 12 + __u32 flags; 13 + __u16 uv_rc; /* UV header rc value */ 14 + __u16 uv_rrc; /* UV header rrc value */ 15 + __u64 argument_addr; /* Userspace address of uvio argument */ 16 + __u32 argument_len; 17 + __u8 reserved14[0x40 - 0x14]; /* must be zero */ 18 + }; 19 + 20 + #define UVIO_ATT_USER_DATA_LEN 0x100 21 + #define UVIO_ATT_UID_LEN 0x10 22 + struct uvio_attest { 23 + __u64 arcb_addr; /* 0x0000 */ 24 + __u64 meas_addr; /* 0x0008 */ 25 + __u64 add_data_addr; /* 0x0010 */ 26 + __u8 user_data[UVIO_ATT_USER_DATA_LEN]; /* 0x0018 */ 27 + __u8 config_uid[UVIO_ATT_UID_LEN]; /* 0x0118 */ 28 + __u32 arcb_len; /* 0x0128 */ 29 + __u32 meas_len; /* 0x012c */ 30 + __u32 add_data_len; /* 0x0130 */ 31 + __u16 user_data_len; /* 0x0134 */ 32 + __u16 reserved136; /* 0x0136 */ 33 + }; 34 + 35 + /* 36 + * The following max values define an upper length for the IOCTL in/out buffers. 37 + * However, they do not represent the maximum the Ultravisor allows which is 38 + * often way smaller. By allowing larger buffer sizes we hopefully do not need 39 + * to update the code with every machine update. It is therefore possible for 40 + * userspace to request more memory than actually used by kernel/UV. 41 + */ 42 + #define UVIO_ATT_ARCB_MAX_LEN 0x100000 43 + #define UVIO_ATT_MEASUREMENT_MAX_LEN 0x8000 44 + #define UVIO_ATT_ADDITIONAL_MAX_LEN 0x8000 45 + 46 + #define UVIO_DEVICE_NAME "uv" 47 + #define UVIO_TYPE_UVC 'u' 48 + 49 + #define UVIO_IOCTL_ATT _IOWR(UVIO_TYPE_UVC, 0x01, struct uvio_ioctl_cb) 50 + 51 + #endif /* __S390_ASM_UVDEVICE_H */
+18 -4
arch/s390/kvm/gaccess.c
··· 491 491 PROT_TYPE_IEP = 4, 492 492 }; 493 493 494 - static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva, 495 - u8 ar, enum gacc_mode mode, enum prot_type prot) 494 + static int trans_exc_ending(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar, 495 + enum gacc_mode mode, enum prot_type prot, bool terminate) 496 496 { 497 497 struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm; 498 498 struct trans_exc_code_bits *tec; ··· 519 519 case PROT_TYPE_DAT: 520 520 tec->b61 = 1; 521 521 break; 522 + } 523 + if (terminate) { 524 + tec->b56 = 0; 525 + tec->b60 = 0; 526 + tec->b61 = 0; 522 527 } 523 528 fallthrough; 524 529 case PGM_ASCE_TYPE: ··· 555 550 break; 556 551 } 557 552 return code; 553 + } 554 + 555 + static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva, u8 ar, 556 + enum gacc_mode mode, enum prot_type prot) 557 + { 558 + return trans_exc_ending(vcpu, code, gva, ar, mode, prot, false); 558 559 } 559 560 560 561 static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce, ··· 1120 1109 data += fragment_len; 1121 1110 ga = kvm_s390_logical_to_effective(vcpu, ga + fragment_len); 1122 1111 } 1123 - if (rc > 0) 1124 - rc = trans_exc(vcpu, rc, ga, ar, mode, prot); 1112 + if (rc > 0) { 1113 + bool terminate = (mode == GACC_STORE) && (idx > 0); 1114 + 1115 + rc = trans_exc_ending(vcpu, rc, ga, ar, mode, prot, terminate); 1116 + } 1125 1117 out_unlock: 1126 1118 if (need_ipte_lock) 1127 1119 ipte_unlock(vcpu);
+10
drivers/s390/char/Kconfig
··· 100 100 This option enables the Open-for-Business interface to the s390 101 101 Service Element. 102 102 103 + config S390_UV_UAPI 104 + def_tristate m 105 + prompt "Ultravisor userspace API" 106 + help 107 + Selecting exposes parts of the UV interface to userspace 108 + by providing a misc character device at /dev/uv. 109 + Using IOCTLs one can interact with the UV. 110 + The device is only available if the Ultravisor 111 + Facility (158) is present. 112 + 103 113 config S390_TAPE 104 114 def_tristate m 105 115 prompt "S/390 tape device support"
+1
drivers/s390/char/Makefile
··· 48 48 obj-$(CONFIG_MONWRITER) += monwriter.o 49 49 obj-$(CONFIG_S390_VMUR) += vmur.o 50 50 obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o 51 + obj-$(CONFIG_S390_UV_UAPI) += uvdevice.o 51 52 52 53 hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o 53 54 obj-$(CONFIG_HMC_DRV) += hmcdrv.o
+257
drivers/s390/char/uvdevice.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright IBM Corp. 2022 4 + * Author(s): Steffen Eiden <seiden@linux.ibm.com> 5 + * 6 + * This file provides a Linux misc device to give userspace access to some 7 + * Ultravisor (UV) functions. The device only accepts IOCTLs and will only 8 + * be present if the Ultravisor facility (158) is present. 9 + * 10 + * When userspace sends a valid IOCTL uvdevice will copy the input data to 11 + * kernel space, do some basic validity checks to avoid kernel/system 12 + * corruption. Any other check that the Ultravisor does will not be done by 13 + * the uvdevice to keep changes minimal when adding new functionalities 14 + * to existing UV-calls. 15 + * After the checks uvdevice builds a corresponding 16 + * Ultravisor Call Control Block, and sends the request to the Ultravisor. 17 + * Then, it copies the response, including the return codes, back to userspace. 18 + * It is the responsibility of the userspace to check for any error issued 19 + * by UV and to interpret the UV response. The uvdevice acts as a communication 20 + * channel for userspace to the Ultravisor. 21 + */ 22 + 23 + #include <linux/module.h> 24 + #include <linux/kernel.h> 25 + #include <linux/miscdevice.h> 26 + #include <linux/types.h> 27 + #include <linux/stddef.h> 28 + #include <linux/vmalloc.h> 29 + #include <linux/slab.h> 30 + 31 + #include <asm/uvdevice.h> 32 + #include <asm/uv.h> 33 + 34 + static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb, 35 + u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest) 36 + { 37 + void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr; 38 + 39 + if (copy_from_user(arcb, user_buf_arcb, uvio_attest->arcb_len)) 40 + return -EFAULT; 41 + 42 + uvcb_attest->header.len = sizeof(*uvcb_attest); 43 + uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST; 44 + uvcb_attest->arcb_addr = (u64)arcb; 45 + uvcb_attest->cont_token = 0; 46 + uvcb_attest->user_data_len = uvio_attest->user_data_len; 47 + memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data)); 48 + uvcb_attest->meas_len = uvio_attest->meas_len; 49 + uvcb_attest->meas_addr = (u64)meas; 50 + uvcb_attest->add_data_len = uvio_attest->add_data_len; 51 + uvcb_attest->add_data_addr = (u64)add_data; 52 + 53 + return 0; 54 + } 55 + 56 + static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest, 57 + struct uvio_ioctl_cb *uv_ioctl, 58 + u8 *measurement, u8 *add_data, 59 + struct uvio_attest *uvio_attest) 60 + { 61 + struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr; 62 + void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr; 63 + void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr; 64 + void __user *user_buf_uid = &user_uvio_attest->config_uid; 65 + 66 + if (copy_to_user(user_buf_meas, measurement, uvio_attest->meas_len)) 67 + return -EFAULT; 68 + if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len)) 69 + return -EFAULT; 70 + if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid))) 71 + return -EFAULT; 72 + return 0; 73 + } 74 + 75 + static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest) 76 + { 77 + u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr; 78 + 79 + if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest))) 80 + return -EFAULT; 81 + 82 + if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN) 83 + return -EINVAL; 84 + if (uvio_attest->arcb_len == 0) 85 + return -EINVAL; 86 + if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN) 87 + return -EINVAL; 88 + if (uvio_attest->meas_len == 0) 89 + return -EINVAL; 90 + if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN) 91 + return -EINVAL; 92 + if (uvio_attest->reserved136) 93 + return -EINVAL; 94 + return 0; 95 + } 96 + 97 + /** 98 + * uvio_attestation() - Perform a Retrieve Attestation Measurement UVC. 99 + * 100 + * @uv_ioctl: ioctl control block 101 + * 102 + * uvio_attestation() does a Retrieve Attestation Measurement Ultravisor Call. 103 + * It verifies that the given userspace addresses are valid and request sizes 104 + * are sane. Every other check is made by the Ultravisor (UV) and won't result 105 + * in a negative return value. It copies the input to kernelspace, builds the 106 + * request, sends the UV-call, and copies the result to userspace. 107 + * 108 + * The Attestation Request has two input and two outputs. 109 + * ARCB and User Data are inputs for the UV generated by userspace. 110 + * Measurement and Additional Data are outputs for userspace generated by UV. 111 + * 112 + * The Attestation Request Control Block (ARCB) is a cryptographically verified 113 + * and secured request to UV and User Data is some plaintext data which is 114 + * going to be included in the Attestation Measurement calculation. 115 + * 116 + * Measurement is a cryptographic measurement of the callers properties, 117 + * optional data configured by the ARCB and the user data. If specified by the 118 + * ARCB, UV will add some Additional Data to the measurement calculation. 119 + * This Additional Data is then returned as well. 120 + * 121 + * If the Retrieve Attestation Measurement UV facility is not present, 122 + * UV will return invalid command rc. This won't be fenced in the driver 123 + * and does not result in a negative return value. 124 + * 125 + * Context: might sleep 126 + * 127 + * Return: 0 on success or a negative error code on error. 128 + */ 129 + static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl) 130 + { 131 + struct uv_cb_attest *uvcb_attest = NULL; 132 + struct uvio_attest *uvio_attest = NULL; 133 + u8 *measurement = NULL; 134 + u8 *add_data = NULL; 135 + u8 *arcb = NULL; 136 + int ret; 137 + 138 + ret = -EINVAL; 139 + if (uv_ioctl->argument_len != sizeof(*uvio_attest)) 140 + goto out; 141 + 142 + ret = -ENOMEM; 143 + uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL); 144 + if (!uvio_attest) 145 + goto out; 146 + 147 + ret = get_uvio_attest(uv_ioctl, uvio_attest); 148 + if (ret) 149 + goto out; 150 + 151 + ret = -ENOMEM; 152 + arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL); 153 + measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL); 154 + if (!arcb || !measurement) 155 + goto out; 156 + 157 + if (uvio_attest->add_data_len) { 158 + add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL); 159 + if (!add_data) 160 + goto out; 161 + } 162 + 163 + uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL); 164 + if (!uvcb_attest) 165 + goto out; 166 + 167 + ret = uvio_build_uvcb_attest(uvcb_attest, arcb, measurement, add_data, uvio_attest); 168 + if (ret) 169 + goto out; 170 + 171 + uv_call_sched(0, (u64)uvcb_attest); 172 + 173 + uv_ioctl->uv_rc = uvcb_attest->header.rc; 174 + uv_ioctl->uv_rrc = uvcb_attest->header.rrc; 175 + 176 + ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data, 177 + uvio_attest); 178 + out: 179 + kvfree(arcb); 180 + kvfree(measurement); 181 + kvfree(add_data); 182 + kfree(uvio_attest); 183 + kfree(uvcb_attest); 184 + return ret; 185 + } 186 + 187 + static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp) 188 + { 189 + if (copy_from_user(ioctl, argp, sizeof(*ioctl))) 190 + return -EFAULT; 191 + if (ioctl->flags != 0) 192 + return -EINVAL; 193 + if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14))) 194 + return -EINVAL; 195 + 196 + return 0; 197 + } 198 + 199 + /* 200 + * IOCTL entry point for the Ultravisor device. 201 + */ 202 + static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 203 + { 204 + void __user *argp = (void __user *)arg; 205 + struct uvio_ioctl_cb uv_ioctl = { }; 206 + long ret; 207 + 208 + switch (cmd) { 209 + case UVIO_IOCTL_ATT: 210 + ret = uvio_copy_and_check_ioctl(&uv_ioctl, argp); 211 + if (ret) 212 + return ret; 213 + ret = uvio_attestation(&uv_ioctl); 214 + break; 215 + default: 216 + ret = -ENOIOCTLCMD; 217 + break; 218 + } 219 + if (ret) 220 + return ret; 221 + 222 + if (copy_to_user(argp, &uv_ioctl, sizeof(uv_ioctl))) 223 + ret = -EFAULT; 224 + 225 + return ret; 226 + } 227 + 228 + static const struct file_operations uvio_dev_fops = { 229 + .owner = THIS_MODULE, 230 + .unlocked_ioctl = uvio_ioctl, 231 + .llseek = no_llseek, 232 + }; 233 + 234 + static struct miscdevice uvio_dev_miscdev = { 235 + .minor = MISC_DYNAMIC_MINOR, 236 + .name = UVIO_DEVICE_NAME, 237 + .fops = &uvio_dev_fops, 238 + }; 239 + 240 + static void __exit uvio_dev_exit(void) 241 + { 242 + misc_deregister(&uvio_dev_miscdev); 243 + } 244 + 245 + static int __init uvio_dev_init(void) 246 + { 247 + if (!test_facility(158)) 248 + return -ENXIO; 249 + return misc_register(&uvio_dev_miscdev); 250 + } 251 + 252 + module_init(uvio_dev_init); 253 + module_exit(uvio_dev_exit); 254 + 255 + MODULE_AUTHOR("IBM Corporation"); 256 + MODULE_LICENSE("GPL"); 257 + MODULE_DESCRIPTION("Ultravisor UAPI driver");
+1
tools/testing/selftests/Makefile
··· 10 10 TARGETS += cpufreq 11 11 TARGETS += cpu-hotplug 12 12 TARGETS += drivers/dma-buf 13 + TARGETS += drivers/s390x/uvdevice 13 14 TARGETS += efivarfs 14 15 TARGETS += exec 15 16 TARGETS += filesystems
+1
tools/testing/selftests/drivers/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 /dma-buf/udmabuf 3 + /s390x/uvdevice/test_uvdevice
+22
tools/testing/selftests/drivers/s390x/uvdevice/Makefile
··· 1 + include ../../../../../build/Build.include 2 + 3 + UNAME_M := $(shell uname -m) 4 + 5 + ifneq ($(UNAME_M),s390x) 6 + nothing: 7 + .PHONY: all clean run_tests install 8 + .SILENT: 9 + else 10 + 11 + TEST_GEN_PROGS := test_uvdevice 12 + 13 + top_srcdir ?= ../../../../../.. 14 + KSFT_KHDR_INSTALL := 1 15 + khdr_dir = $(top_srcdir)/usr/include 16 + LINUX_TOOL_ARCH_INCLUDE = $(top_srcdir)/tools/arch/$(ARCH)/include 17 + 18 + CFLAGS += -Wall -Werror -static -I$(khdr_dir) -I$(LINUX_TOOL_ARCH_INCLUDE) 19 + 20 + include ../../../lib.mk 21 + 22 + endif
+1
tools/testing/selftests/drivers/s390x/uvdevice/config
··· 1 + CONFIG_S390_UV_UAPI=y
+276
tools/testing/selftests/drivers/s390x/uvdevice/test_uvdevice.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * selftest for the Ultravisor UAPI device 4 + * 5 + * Copyright IBM Corp. 2022 6 + * Author(s): Steffen Eiden <seiden@linux.ibm.com> 7 + */ 8 + 9 + #include <stdint.h> 10 + #include <fcntl.h> 11 + #include <errno.h> 12 + #include <sys/ioctl.h> 13 + #include <sys/mman.h> 14 + 15 + #include <asm/uvdevice.h> 16 + 17 + #include "../../../kselftest_harness.h" 18 + 19 + #define UV_PATH "/dev/uv" 20 + #define BUFFER_SIZE 0x200 21 + FIXTURE(uvio_fixture) { 22 + int uv_fd; 23 + struct uvio_ioctl_cb uvio_ioctl; 24 + uint8_t buffer[BUFFER_SIZE]; 25 + __u64 fault_page; 26 + }; 27 + 28 + FIXTURE_VARIANT(uvio_fixture) { 29 + unsigned long ioctl_cmd; 30 + uint32_t arg_size; 31 + }; 32 + 33 + FIXTURE_VARIANT_ADD(uvio_fixture, att) { 34 + .ioctl_cmd = UVIO_IOCTL_ATT, 35 + .arg_size = sizeof(struct uvio_attest), 36 + }; 37 + 38 + FIXTURE_SETUP(uvio_fixture) 39 + { 40 + self->uv_fd = open(UV_PATH, O_ACCMODE); 41 + 42 + self->uvio_ioctl.argument_addr = (__u64)self->buffer; 43 + self->uvio_ioctl.argument_len = variant->arg_size; 44 + self->fault_page = 45 + (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0); 46 + } 47 + 48 + FIXTURE_TEARDOWN(uvio_fixture) 49 + { 50 + if (self->uv_fd) 51 + close(self->uv_fd); 52 + munmap((void *)self->fault_page, (size_t)getpagesize()); 53 + } 54 + 55 + TEST_F(uvio_fixture, fault_ioctl_arg) 56 + { 57 + int rc, errno_cache; 58 + 59 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, NULL); 60 + errno_cache = errno; 61 + ASSERT_EQ(rc, -1); 62 + ASSERT_EQ(errno_cache, EFAULT); 63 + 64 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, self->fault_page); 65 + errno_cache = errno; 66 + ASSERT_EQ(rc, -1); 67 + ASSERT_EQ(errno_cache, EFAULT); 68 + } 69 + 70 + TEST_F(uvio_fixture, fault_uvio_arg) 71 + { 72 + int rc, errno_cache; 73 + 74 + self->uvio_ioctl.argument_addr = 0; 75 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 76 + errno_cache = errno; 77 + ASSERT_EQ(rc, -1); 78 + ASSERT_EQ(errno_cache, EFAULT); 79 + 80 + self->uvio_ioctl.argument_addr = self->fault_page; 81 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 82 + errno_cache = errno; 83 + ASSERT_EQ(rc, -1); 84 + ASSERT_EQ(errno_cache, EFAULT); 85 + } 86 + 87 + /* 88 + * Test to verify that IOCTLs with invalid values in the ioctl_control block 89 + * are rejected. 90 + */ 91 + TEST_F(uvio_fixture, inval_ioctl_cb) 92 + { 93 + int rc, errno_cache; 94 + 95 + self->uvio_ioctl.argument_len = 0; 96 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 97 + errno_cache = errno; 98 + ASSERT_EQ(rc, -1); 99 + ASSERT_EQ(errno_cache, EINVAL); 100 + 101 + self->uvio_ioctl.argument_len = (uint32_t)-1; 102 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 103 + errno_cache = errno; 104 + ASSERT_EQ(rc, -1); 105 + ASSERT_EQ(errno_cache, EINVAL); 106 + self->uvio_ioctl.argument_len = variant->arg_size; 107 + 108 + self->uvio_ioctl.flags = (uint32_t)-1; 109 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 110 + errno_cache = errno; 111 + ASSERT_EQ(rc, -1); 112 + ASSERT_EQ(errno_cache, EINVAL); 113 + self->uvio_ioctl.flags = 0; 114 + 115 + memset(self->uvio_ioctl.reserved14, 0xff, sizeof(self->uvio_ioctl.reserved14)); 116 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 117 + errno_cache = errno; 118 + ASSERT_EQ(rc, -1); 119 + ASSERT_EQ(errno_cache, EINVAL); 120 + 121 + memset(&self->uvio_ioctl, 0x11, sizeof(self->uvio_ioctl)); 122 + rc = ioctl(self->uv_fd, variant->ioctl_cmd, &self->uvio_ioctl); 123 + ASSERT_EQ(rc, -1); 124 + } 125 + 126 + TEST_F(uvio_fixture, inval_ioctl_cmd) 127 + { 128 + int rc, errno_cache; 129 + uint8_t nr = _IOC_NR(variant->ioctl_cmd); 130 + unsigned long cmds[] = { 131 + _IOWR('a', nr, struct uvio_ioctl_cb), 132 + _IOWR(UVIO_TYPE_UVC, nr, int), 133 + _IO(UVIO_TYPE_UVC, nr), 134 + _IOR(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb), 135 + _IOW(UVIO_TYPE_UVC, nr, struct uvio_ioctl_cb), 136 + }; 137 + 138 + for (size_t i = 0; i < ARRAY_SIZE(cmds); i++) { 139 + rc = ioctl(self->uv_fd, cmds[i], &self->uvio_ioctl); 140 + errno_cache = errno; 141 + ASSERT_EQ(rc, -1); 142 + ASSERT_EQ(errno_cache, ENOTTY); 143 + } 144 + } 145 + 146 + struct test_attest_buffer { 147 + uint8_t arcb[0x180]; 148 + uint8_t meas[64]; 149 + uint8_t add[32]; 150 + }; 151 + 152 + FIXTURE(attest_fixture) { 153 + int uv_fd; 154 + struct uvio_ioctl_cb uvio_ioctl; 155 + struct uvio_attest uvio_attest; 156 + struct test_attest_buffer attest_buffer; 157 + __u64 fault_page; 158 + }; 159 + 160 + FIXTURE_SETUP(attest_fixture) 161 + { 162 + self->uv_fd = open(UV_PATH, O_ACCMODE); 163 + 164 + self->uvio_ioctl.argument_addr = (__u64)&self->uvio_attest; 165 + self->uvio_ioctl.argument_len = sizeof(self->uvio_attest); 166 + 167 + self->uvio_attest.arcb_addr = (__u64)&self->attest_buffer.arcb; 168 + self->uvio_attest.arcb_len = sizeof(self->attest_buffer.arcb); 169 + 170 + self->uvio_attest.meas_addr = (__u64)&self->attest_buffer.meas; 171 + self->uvio_attest.meas_len = sizeof(self->attest_buffer.meas); 172 + 173 + self->uvio_attest.add_data_addr = (__u64)&self->attest_buffer.add; 174 + self->uvio_attest.add_data_len = sizeof(self->attest_buffer.add); 175 + self->fault_page = 176 + (__u64)mmap(NULL, (size_t)getpagesize(), PROT_NONE, MAP_ANONYMOUS, -1, 0); 177 + } 178 + 179 + FIXTURE_TEARDOWN(attest_fixture) 180 + { 181 + if (self->uv_fd) 182 + close(self->uv_fd); 183 + munmap((void *)self->fault_page, (size_t)getpagesize()); 184 + } 185 + 186 + static void att_inval_sizes_test(uint32_t *size, uint32_t max_size, bool test_zero, 187 + struct __test_metadata *_metadata, 188 + FIXTURE_DATA(attest_fixture) *self) 189 + { 190 + int rc, errno_cache; 191 + uint32_t tmp = *size; 192 + 193 + if (test_zero) { 194 + *size = 0; 195 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 196 + errno_cache = errno; 197 + ASSERT_EQ(rc, -1); 198 + ASSERT_EQ(errno_cache, EINVAL); 199 + } 200 + *size = max_size + 1; 201 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 202 + errno_cache = errno; 203 + ASSERT_EQ(rc, -1); 204 + ASSERT_EQ(errno_cache, EINVAL); 205 + *size = tmp; 206 + } 207 + 208 + /* 209 + * Test to verify that attestation IOCTLs with invalid values in the UVIO 210 + * attestation control block are rejected. 211 + */ 212 + TEST_F(attest_fixture, att_inval_request) 213 + { 214 + int rc, errno_cache; 215 + 216 + att_inval_sizes_test(&self->uvio_attest.add_data_len, UVIO_ATT_ADDITIONAL_MAX_LEN, 217 + false, _metadata, self); 218 + att_inval_sizes_test(&self->uvio_attest.meas_len, UVIO_ATT_MEASUREMENT_MAX_LEN, 219 + true, _metadata, self); 220 + att_inval_sizes_test(&self->uvio_attest.arcb_len, UVIO_ATT_ARCB_MAX_LEN, 221 + true, _metadata, self); 222 + 223 + self->uvio_attest.reserved136 = (uint16_t)-1; 224 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 225 + errno_cache = errno; 226 + ASSERT_EQ(rc, -1); 227 + ASSERT_EQ(errno_cache, EINVAL); 228 + 229 + memset(&self->uvio_attest, 0x11, sizeof(self->uvio_attest)); 230 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 231 + ASSERT_EQ(rc, -1); 232 + } 233 + 234 + static void att_inval_addr_test(__u64 *addr, struct __test_metadata *_metadata, 235 + FIXTURE_DATA(attest_fixture) *self) 236 + { 237 + int rc, errno_cache; 238 + __u64 tmp = *addr; 239 + 240 + *addr = 0; 241 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 242 + errno_cache = errno; 243 + ASSERT_EQ(rc, -1); 244 + ASSERT_EQ(errno_cache, EFAULT); 245 + *addr = self->fault_page; 246 + rc = ioctl(self->uv_fd, UVIO_IOCTL_ATT, &self->uvio_ioctl); 247 + errno_cache = errno; 248 + ASSERT_EQ(rc, -1); 249 + ASSERT_EQ(errno_cache, EFAULT); 250 + *addr = tmp; 251 + } 252 + 253 + TEST_F(attest_fixture, att_inval_addr) 254 + { 255 + att_inval_addr_test(&self->uvio_attest.arcb_addr, _metadata, self); 256 + att_inval_addr_test(&self->uvio_attest.add_data_addr, _metadata, self); 257 + att_inval_addr_test(&self->uvio_attest.meas_addr, _metadata, self); 258 + } 259 + 260 + static void __attribute__((constructor)) __constructor_order_last(void) 261 + { 262 + if (!__constructor_order) 263 + __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; 264 + } 265 + 266 + int main(int argc, char **argv) 267 + { 268 + int fd = open(UV_PATH, O_ACCMODE); 269 + 270 + if (fd < 0) 271 + ksft_exit_skip("No uv-device or cannot access " UV_PATH "\n" 272 + "Enable CONFIG_S390_UV_UAPI and check the access rights on " 273 + UV_PATH ".\n"); 274 + close(fd); 275 + return test_harness_run(argc, argv); 276 + }
+45 -1
tools/testing/selftests/kvm/s390x/memop.c
··· 10 10 #include <string.h> 11 11 #include <sys/ioctl.h> 12 12 13 + #include <linux/bits.h> 14 + 13 15 #include "test_util.h" 14 16 #include "kvm_util.h" 15 17 ··· 196 194 #define SIDA_OFFSET(o) ._sida_offset = 1, .sida_offset = (o) 197 195 #define AR(a) ._ar = 1, .ar = (a) 198 196 #define KEY(a) .f_key = 1, .key = (a) 197 + #define INJECT .f_inject = 1 199 198 200 199 #define CHECK_N_DO(f, ...) ({ f(__VA_ARGS__, CHECK_ONLY); f(__VA_ARGS__); }) 201 200 ··· 433 430 TEST_ASSERT(rv == 4, "Should result in protection exception"); \ 434 431 }) 435 432 433 + static void guest_error_key(void) 434 + { 435 + GUEST_SYNC(STAGE_INITED); 436 + set_storage_key_range(mem1, PAGE_SIZE, 0x18); 437 + set_storage_key_range(mem1 + PAGE_SIZE, sizeof(mem1) - PAGE_SIZE, 0x98); 438 + GUEST_SYNC(STAGE_SKEYS_SET); 439 + GUEST_SYNC(STAGE_IDLED); 440 + } 441 + 436 442 static void test_errors_key(void) 437 443 { 438 - struct test_default t = test_default_init(guest_copy_key_fetch_prot); 444 + struct test_default t = test_default_init(guest_error_key); 439 445 440 446 HOST_SYNC(t.vcpu, STAGE_INITED); 441 447 HOST_SYNC(t.vcpu, STAGE_SKEYS_SET); ··· 454 442 CHECK_N_DO(ERR_PROT_MOP, t.vcpu, LOGICAL, READ, mem2, t.size, GADDR_V(mem2), KEY(2)); 455 443 CHECK_N_DO(ERR_PROT_MOP, t.vm, ABSOLUTE, WRITE, mem1, t.size, GADDR_V(mem1), KEY(2)); 456 444 CHECK_N_DO(ERR_PROT_MOP, t.vm, ABSOLUTE, READ, mem2, t.size, GADDR_V(mem2), KEY(2)); 445 + 446 + kvm_vm_free(t.kvm_vm); 447 + } 448 + 449 + static void test_termination(void) 450 + { 451 + struct test_default t = test_default_init(guest_error_key); 452 + uint64_t prefix; 453 + uint64_t teid; 454 + uint64_t teid_mask = BIT(63 - 56) | BIT(63 - 60) | BIT(63 - 61); 455 + uint64_t psw[2]; 456 + 457 + HOST_SYNC(t.vcpu, STAGE_INITED); 458 + HOST_SYNC(t.vcpu, STAGE_SKEYS_SET); 459 + 460 + /* vcpu, mismatching keys after first page */ 461 + ERR_PROT_MOP(t.vcpu, LOGICAL, WRITE, mem1, t.size, GADDR_V(mem1), KEY(1), INJECT); 462 + /* 463 + * The memop injected a program exception and the test needs to check the 464 + * Translation-Exception Identification (TEID). It is necessary to run 465 + * the guest in order to be able to read the TEID from guest memory. 466 + * Set the guest program new PSW, so the guest state is not clobbered. 467 + */ 468 + prefix = t.run->s.regs.prefix; 469 + psw[0] = t.run->psw_mask; 470 + psw[1] = t.run->psw_addr; 471 + MOP(t.vm, ABSOLUTE, WRITE, psw, sizeof(psw), GADDR(prefix + 464)); 472 + HOST_SYNC(t.vcpu, STAGE_IDLED); 473 + MOP(t.vm, ABSOLUTE, READ, &teid, sizeof(teid), GADDR(prefix + 168)); 474 + /* Bits 56, 60, 61 form a code, 0 being the only one allowing for termination */ 475 + ASSERT_EQ(teid & teid_mask, 0); 457 476 458 477 kvm_vm_free(t.kvm_vm); 459 478 } ··· 711 668 test_copy_key_fetch_prot(); 712 669 test_copy_key_fetch_prot_override(); 713 670 test_errors_key(); 671 + test_termination(); 714 672 test_errors_key_storage_prot_override(); 715 673 test_errors_key_fetch_prot_override_not_enabled(); 716 674 test_errors_key_fetch_prot_override_enabled();