| 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Copyright IBM Corp. 2022, 2024 |
| 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 | #include <linux/cpufeature.h> |
| 31 | |
| 32 | #include <asm/uvdevice.h> |
| 33 | #include <asm/uv.h> |
| 34 | |
| 35 | #define BIT_UVIO_INTERNAL U32_MAX |
| 36 | /* Mapping from IOCTL-nr to UVC-bit */ |
| 37 | static const u32 ioctl_nr_to_uvc_bit[] __initconst = { |
| 38 | [UVIO_IOCTL_UVDEV_INFO_NR] = BIT_UVIO_INTERNAL, |
| 39 | [UVIO_IOCTL_ATT_NR] = BIT_UVC_CMD_RETR_ATTEST, |
| 40 | [UVIO_IOCTL_ADD_SECRET_NR] = BIT_UVC_CMD_ADD_SECRET, |
| 41 | [UVIO_IOCTL_LIST_SECRETS_NR] = BIT_UVC_CMD_LIST_SECRETS, |
| 42 | [UVIO_IOCTL_LOCK_SECRETS_NR] = BIT_UVC_CMD_LOCK_SECRETS, |
| 43 | [UVIO_IOCTL_RETR_SECRET_NR] = BIT_UVC_CMD_RETR_ATTEST, |
| 44 | }; |
| 45 | |
| 46 | static_assert(ARRAY_SIZE(ioctl_nr_to_uvc_bit) == UVIO_IOCTL_NUM_IOCTLS); |
| 47 | |
| 48 | static struct uvio_uvdev_info uvdev_info = { |
| 49 | .supp_uvio_cmds = GENMASK_ULL(UVIO_IOCTL_NUM_IOCTLS - 1, 0), |
| 50 | }; |
| 51 | |
| 52 | static void __init set_supp_uv_cmds(unsigned long *supp_uv_cmds) |
| 53 | { |
| 54 | int i; |
| 55 | |
| 56 | for (i = 0; i < UVIO_IOCTL_NUM_IOCTLS; i++) { |
| 57 | if (ioctl_nr_to_uvc_bit[i] == BIT_UVIO_INTERNAL) |
| 58 | continue; |
| 59 | if (!test_bit_inv(ioctl_nr_to_uvc_bit[i], uv_info.inst_calls_list)) |
| 60 | continue; |
| 61 | __set_bit(i, supp_uv_cmds); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | /** |
| 66 | * uvio_uvdev_info() - Get information about the uvdevice |
| 67 | * |
| 68 | * @uv_ioctl: ioctl control block |
| 69 | * |
| 70 | * Lists all IOCTLs that are supported by this uvdevice |
| 71 | * |
| 72 | * Return: 0 on success or a negative error code on error |
| 73 | */ |
| 74 | static int uvio_uvdev_info(struct uvio_ioctl_cb *uv_ioctl) |
| 75 | { |
| 76 | void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; |
| 77 | |
| 78 | if (uv_ioctl->argument_len < sizeof(uvdev_info)) |
| 79 | return -EINVAL; |
| 80 | if (copy_to_user(to: user_buf_arg, from: &uvdev_info, n: sizeof(uvdev_info))) |
| 81 | return -EFAULT; |
| 82 | |
| 83 | uv_ioctl->uv_rc = UVC_RC_EXECUTED; |
| 84 | return 0; |
| 85 | } |
| 86 | |
| 87 | static int uvio_build_uvcb_attest(struct uv_cb_attest *uvcb_attest, u8 *arcb, |
| 88 | u8 *meas, u8 *add_data, struct uvio_attest *uvio_attest) |
| 89 | { |
| 90 | void __user *user_buf_arcb = (void __user *)uvio_attest->arcb_addr; |
| 91 | |
| 92 | if (copy_from_user(to: arcb, from: user_buf_arcb, n: uvio_attest->arcb_len)) |
| 93 | return -EFAULT; |
| 94 | |
| 95 | uvcb_attest->header.len = sizeof(*uvcb_attest); |
| 96 | uvcb_attest->header.cmd = UVC_CMD_RETR_ATTEST; |
| 97 | uvcb_attest->arcb_addr = (u64)arcb; |
| 98 | uvcb_attest->cont_token = 0; |
| 99 | uvcb_attest->user_data_len = uvio_attest->user_data_len; |
| 100 | memcpy(uvcb_attest->user_data, uvio_attest->user_data, sizeof(uvcb_attest->user_data)); |
| 101 | uvcb_attest->meas_len = uvio_attest->meas_len; |
| 102 | uvcb_attest->meas_addr = (u64)meas; |
| 103 | uvcb_attest->add_data_len = uvio_attest->add_data_len; |
| 104 | uvcb_attest->add_data_addr = (u64)add_data; |
| 105 | |
| 106 | return 0; |
| 107 | } |
| 108 | |
| 109 | static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest, |
| 110 | struct uvio_ioctl_cb *uv_ioctl, |
| 111 | u8 *measurement, u8 *add_data, |
| 112 | struct uvio_attest *uvio_attest) |
| 113 | { |
| 114 | struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr; |
| 115 | u32 __user *user_buf_add_len = (u32 __user *)&user_uvio_attest->add_data_len; |
| 116 | void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr; |
| 117 | void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr; |
| 118 | void __user *user_buf_uid = &user_uvio_attest->config_uid; |
| 119 | |
| 120 | if (copy_to_user(to: user_buf_meas, from: measurement, n: uvio_attest->meas_len)) |
| 121 | return -EFAULT; |
| 122 | if (add_data && copy_to_user(to: user_buf_add, from: add_data, n: uvio_attest->add_data_len)) |
| 123 | return -EFAULT; |
| 124 | if (put_user(uvio_attest->add_data_len, user_buf_add_len)) |
| 125 | return -EFAULT; |
| 126 | if (copy_to_user(to: user_buf_uid, from: uvcb_attest->config_uid, n: sizeof(uvcb_attest->config_uid))) |
| 127 | return -EFAULT; |
| 128 | return 0; |
| 129 | } |
| 130 | |
| 131 | static int get_uvio_attest(struct uvio_ioctl_cb *uv_ioctl, struct uvio_attest *uvio_attest) |
| 132 | { |
| 133 | u8 __user *user_arg_buf = (u8 __user *)uv_ioctl->argument_addr; |
| 134 | |
| 135 | if (copy_from_user(uvio_attest, user_arg_buf, sizeof(*uvio_attest))) |
| 136 | return -EFAULT; |
| 137 | |
| 138 | if (uvio_attest->arcb_len > UVIO_ATT_ARCB_MAX_LEN) |
| 139 | return -EINVAL; |
| 140 | if (uvio_attest->arcb_len == 0) |
| 141 | return -EINVAL; |
| 142 | if (uvio_attest->meas_len > UVIO_ATT_MEASUREMENT_MAX_LEN) |
| 143 | return -EINVAL; |
| 144 | if (uvio_attest->meas_len == 0) |
| 145 | return -EINVAL; |
| 146 | if (uvio_attest->add_data_len > UVIO_ATT_ADDITIONAL_MAX_LEN) |
| 147 | return -EINVAL; |
| 148 | if (uvio_attest->reserved136) |
| 149 | return -EINVAL; |
| 150 | return 0; |
| 151 | } |
| 152 | |
| 153 | /** |
| 154 | * uvio_attestation() - Perform a Retrieve Attestation Measurement UVC. |
| 155 | * |
| 156 | * @uv_ioctl: ioctl control block |
| 157 | * |
| 158 | * uvio_attestation() does a Retrieve Attestation Measurement Ultravisor Call. |
| 159 | * It verifies that the given userspace addresses are valid and request sizes |
| 160 | * are sane. Every other check is made by the Ultravisor (UV) and won't result |
| 161 | * in a negative return value. It copies the input to kernelspace, builds the |
| 162 | * request, sends the UV-call, and copies the result to userspace. |
| 163 | * |
| 164 | * The Attestation Request has two input and two outputs. |
| 165 | * ARCB and User Data are inputs for the UV generated by userspace. |
| 166 | * Measurement and Additional Data are outputs for userspace generated by UV. |
| 167 | * |
| 168 | * The Attestation Request Control Block (ARCB) is a cryptographically verified |
| 169 | * and secured request to UV and User Data is some plaintext data which is |
| 170 | * going to be included in the Attestation Measurement calculation. |
| 171 | * |
| 172 | * Measurement is a cryptographic measurement of the callers properties, |
| 173 | * optional data configured by the ARCB and the user data. If specified by the |
| 174 | * ARCB, UV will add some Additional Data to the measurement calculation. |
| 175 | * This Additional Data is then returned as well. |
| 176 | * |
| 177 | * If the Retrieve Attestation Measurement UV facility is not present, |
| 178 | * UV will return invalid command rc. This won't be fenced in the driver |
| 179 | * and does not result in a negative return value. |
| 180 | * |
| 181 | * Context: might sleep |
| 182 | * |
| 183 | * Return: 0 on success or a negative error code on error |
| 184 | */ |
| 185 | static int uvio_attestation(struct uvio_ioctl_cb *uv_ioctl) |
| 186 | { |
| 187 | struct uv_cb_attest *uvcb_attest = NULL; |
| 188 | struct uvio_attest *uvio_attest = NULL; |
| 189 | u8 *measurement = NULL; |
| 190 | u8 *add_data = NULL; |
| 191 | u8 *arcb = NULL; |
| 192 | int ret; |
| 193 | |
| 194 | ret = -EINVAL; |
| 195 | if (uv_ioctl->argument_len != sizeof(*uvio_attest)) |
| 196 | goto out; |
| 197 | |
| 198 | ret = -ENOMEM; |
| 199 | uvio_attest = kzalloc(sizeof(*uvio_attest), GFP_KERNEL); |
| 200 | if (!uvio_attest) |
| 201 | goto out; |
| 202 | |
| 203 | ret = get_uvio_attest(uv_ioctl, uvio_attest); |
| 204 | if (ret) |
| 205 | goto out; |
| 206 | |
| 207 | ret = -ENOMEM; |
| 208 | arcb = kvzalloc(uvio_attest->arcb_len, GFP_KERNEL); |
| 209 | measurement = kvzalloc(uvio_attest->meas_len, GFP_KERNEL); |
| 210 | if (!arcb || !measurement) |
| 211 | goto out; |
| 212 | |
| 213 | if (uvio_attest->add_data_len) { |
| 214 | add_data = kvzalloc(uvio_attest->add_data_len, GFP_KERNEL); |
| 215 | if (!add_data) |
| 216 | goto out; |
| 217 | } |
| 218 | |
| 219 | uvcb_attest = kzalloc(sizeof(*uvcb_attest), GFP_KERNEL); |
| 220 | if (!uvcb_attest) |
| 221 | goto out; |
| 222 | |
| 223 | ret = uvio_build_uvcb_attest(uvcb_attest, arcb, meas: measurement, add_data, uvio_attest); |
| 224 | if (ret) |
| 225 | goto out; |
| 226 | |
| 227 | uv_call_sched(0, (u64)uvcb_attest); |
| 228 | |
| 229 | uv_ioctl->uv_rc = uvcb_attest->header.rc; |
| 230 | uv_ioctl->uv_rrc = uvcb_attest->header.rrc; |
| 231 | |
| 232 | ret = uvio_copy_attest_result_to_user(uvcb_attest, uv_ioctl, measurement, add_data, |
| 233 | uvio_attest); |
| 234 | out: |
| 235 | kvfree(addr: arcb); |
| 236 | kvfree(addr: measurement); |
| 237 | kvfree(addr: add_data); |
| 238 | kfree(objp: uvio_attest); |
| 239 | kfree(objp: uvcb_attest); |
| 240 | return ret; |
| 241 | } |
| 242 | |
| 243 | /** |
| 244 | * uvio_add_secret() - Perform an Add Secret UVC |
| 245 | * |
| 246 | * @uv_ioctl: ioctl control block |
| 247 | * |
| 248 | * uvio_add_secret() performs the Add Secret Ultravisor Call. |
| 249 | * |
| 250 | * The given userspace argument address and size are verified to be |
| 251 | * valid but every other check is made by the Ultravisor |
| 252 | * (UV). Therefore UV errors won't result in a negative return |
| 253 | * value. The request is then copied to kernelspace, the UV-call is |
| 254 | * performed and the results are copied back to userspace. |
| 255 | * |
| 256 | * The argument has to point to an Add Secret Request Control Block |
| 257 | * which is an encrypted and cryptographically verified request that |
| 258 | * inserts a protected guest's secrets into the Ultravisor for later |
| 259 | * use. |
| 260 | * |
| 261 | * If the Add Secret UV facility is not present, UV will return |
| 262 | * invalid command rc. This won't be fenced in the driver and does not |
| 263 | * result in a negative return value. |
| 264 | * |
| 265 | * Context: might sleep |
| 266 | * |
| 267 | * Return: 0 on success or a negative error code on error |
| 268 | */ |
| 269 | static int uvio_add_secret(struct uvio_ioctl_cb *uv_ioctl) |
| 270 | { |
| 271 | void __user *user_buf_arg = (void __user *)uv_ioctl->argument_addr; |
| 272 | struct uv_cb_guest_addr uvcb = { |
| 273 | .header.len = sizeof(uvcb), |
| 274 | .header.cmd = UVC_CMD_ADD_SECRET, |
| 275 | }; |
| 276 | void *asrcb = NULL; |
| 277 | int ret; |
| 278 | |
| 279 | if (uv_ioctl->argument_len > UVIO_ADD_SECRET_MAX_LEN) |
| 280 | return -EINVAL; |
| 281 | if (uv_ioctl->argument_len == 0) |
| 282 | return -EINVAL; |
| 283 | |
| 284 | asrcb = kvzalloc(uv_ioctl->argument_len, GFP_KERNEL); |
| 285 | if (!asrcb) |
| 286 | return -ENOMEM; |
| 287 | |
| 288 | ret = -EFAULT; |
| 289 | if (copy_from_user(to: asrcb, from: user_buf_arg, n: uv_ioctl->argument_len)) |
| 290 | goto out; |
| 291 | |
| 292 | ret = 0; |
| 293 | uvcb.addr = (u64)asrcb; |
| 294 | uv_call_sched(0, (u64)&uvcb); |
| 295 | uv_ioctl->uv_rc = uvcb.header.rc; |
| 296 | uv_ioctl->uv_rrc = uvcb.header.rrc; |
| 297 | |
| 298 | out: |
| 299 | kvfree(addr: asrcb); |
| 300 | return ret; |
| 301 | } |
| 302 | |
| 303 | /* |
| 304 | * Do the actual secret list creation. Calls the list secrets UVC until there |
| 305 | * is no more space in the user buffer, or the list ends. |
| 306 | */ |
| 307 | static int uvio_get_list(void *zpage, struct uvio_ioctl_cb *uv_ioctl) |
| 308 | { |
| 309 | const size_t data_off = offsetof(struct uv_secret_list, secrets); |
| 310 | u8 __user *user_buf = (u8 __user *)uv_ioctl->argument_addr; |
| 311 | struct uv_secret_list *list = zpage; |
| 312 | u16 num_secrets_stored = 0; |
| 313 | size_t user_off = data_off; |
| 314 | size_t copy_len; |
| 315 | |
| 316 | do { |
| 317 | uv_list_secrets(list, list->next_secret_idx, &uv_ioctl->uv_rc, |
| 318 | &uv_ioctl->uv_rrc); |
| 319 | if (uv_ioctl->uv_rc != UVC_RC_EXECUTED && |
| 320 | uv_ioctl->uv_rc != UVC_RC_MORE_DATA) |
| 321 | break; |
| 322 | |
| 323 | copy_len = sizeof(list->secrets[0]) * list->num_secr_stored; |
| 324 | if (copy_to_user(to: user_buf + user_off, from: list->secrets, n: copy_len)) |
| 325 | return -EFAULT; |
| 326 | |
| 327 | user_off += copy_len; |
| 328 | num_secrets_stored += list->num_secr_stored; |
| 329 | } while (uv_ioctl->uv_rc == UVC_RC_MORE_DATA && |
| 330 | user_off + sizeof(*list) <= uv_ioctl->argument_len); |
| 331 | |
| 332 | list->num_secr_stored = num_secrets_stored; |
| 333 | if (copy_to_user(to: user_buf, from: list, n: data_off)) |
| 334 | return -EFAULT; |
| 335 | return 0; |
| 336 | } |
| 337 | |
| 338 | /** |
| 339 | * uvio_list_secrets() - Perform a List Secret UVC |
| 340 | * |
| 341 | * @uv_ioctl: ioctl control block |
| 342 | * |
| 343 | * uvio_list_secrets() performs the List Secret Ultravisor Call. It verifies |
| 344 | * that the given userspace argument address is valid and its size is sane. |
| 345 | * Every other check is made by the Ultravisor (UV) and won't result in a |
| 346 | * negative return value. It builds the request, performs the UV-call, and |
| 347 | * copies the result to userspace. |
| 348 | * |
| 349 | * The argument specifies the location for the result of the UV-Call. |
| 350 | * |
| 351 | * Argument length must be a multiple of a page. |
| 352 | * The list secrets IOCTL will call the list UVC multiple times and fill |
| 353 | * the provided user-buffer with list elements until either the list ends or |
| 354 | * the buffer is full. The list header is merged over all list header from the |
| 355 | * individual UVCs. |
| 356 | * |
| 357 | * If the List Secrets UV facility is not present, UV will return invalid |
| 358 | * command rc. This won't be fenced in the driver and does not result in a |
| 359 | * negative return value. |
| 360 | * |
| 361 | * Context: might sleep |
| 362 | * |
| 363 | * Return: 0 on success or a negative error code on error |
| 364 | */ |
| 365 | static int uvio_list_secrets(struct uvio_ioctl_cb *uv_ioctl) |
| 366 | { |
| 367 | void *zpage; |
| 368 | int rc; |
| 369 | |
| 370 | if (uv_ioctl->argument_len == 0 || |
| 371 | uv_ioctl->argument_len % UVIO_LIST_SECRETS_LEN != 0) |
| 372 | return -EINVAL; |
| 373 | |
| 374 | zpage = (void *)get_zeroed_page(GFP_KERNEL); |
| 375 | if (!zpage) |
| 376 | return -ENOMEM; |
| 377 | |
| 378 | rc = uvio_get_list(zpage, uv_ioctl); |
| 379 | |
| 380 | free_page((unsigned long)zpage); |
| 381 | return rc; |
| 382 | } |
| 383 | |
| 384 | /** |
| 385 | * uvio_lock_secrets() - Perform a Lock Secret Store UVC |
| 386 | * |
| 387 | * @ioctl: ioctl control block |
| 388 | * |
| 389 | * uvio_lock_secrets() performs the Lock Secret Store Ultravisor Call. It |
| 390 | * performs the UV-call and copies the return codes to the ioctl control block. |
| 391 | * After this call was dispatched successfully every following Add Secret UVC |
| 392 | * and Lock Secrets UVC will fail with return code 0x102. |
| 393 | * |
| 394 | * The argument address and size must be 0. |
| 395 | * |
| 396 | * If the Lock Secrets UV facility is not present, UV will return invalid |
| 397 | * command rc. This won't be fenced in the driver and does not result in a |
| 398 | * negative return value. |
| 399 | * |
| 400 | * Context: might sleep |
| 401 | * |
| 402 | * Return: 0 on success or a negative error code on error |
| 403 | */ |
| 404 | static int uvio_lock_secrets(struct uvio_ioctl_cb *ioctl) |
| 405 | { |
| 406 | struct uv_cb_nodata uvcb = { |
| 407 | .header.len = sizeof(uvcb), |
| 408 | .header.cmd = UVC_CMD_LOCK_SECRETS, |
| 409 | }; |
| 410 | |
| 411 | if (ioctl->argument_addr || ioctl->argument_len) |
| 412 | return -EINVAL; |
| 413 | |
| 414 | uv_call(0, (u64)&uvcb); |
| 415 | ioctl->uv_rc = uvcb.header.rc; |
| 416 | ioctl->uv_rrc = uvcb.header.rrc; |
| 417 | |
| 418 | return 0; |
| 419 | } |
| 420 | |
| 421 | /** |
| 422 | * uvio_retr_secret() - Perform a retrieve secret UVC |
| 423 | * |
| 424 | * @uv_ioctl: ioctl control block. |
| 425 | * |
| 426 | * uvio_retr_secret() performs the Retrieve Secret Ultravisor Call. |
| 427 | * The first two bytes of the argument specify the index of the secret to be |
| 428 | * retrieved. The retrieved secret is copied into the argument buffer if there |
| 429 | * is enough space. |
| 430 | * The argument length must be at least two bytes and at max 8192 bytes. |
| 431 | * |
| 432 | * Context: might sleep |
| 433 | * |
| 434 | * Return: 0 on success or a negative error code on error |
| 435 | */ |
| 436 | static int uvio_retr_secret(struct uvio_ioctl_cb *uv_ioctl) |
| 437 | { |
| 438 | u16 __user *user_index = (u16 __user *)uv_ioctl->argument_addr; |
| 439 | struct uv_cb_retr_secr uvcb = { |
| 440 | .header.len = sizeof(uvcb), |
| 441 | .header.cmd = UVC_CMD_RETR_SECRET, |
| 442 | }; |
| 443 | u32 buf_len = uv_ioctl->argument_len; |
| 444 | void *buf = NULL; |
| 445 | int ret; |
| 446 | |
| 447 | if (buf_len > UVIO_RETR_SECRET_MAX_LEN || buf_len < sizeof(*user_index)) |
| 448 | return -EINVAL; |
| 449 | |
| 450 | buf = kvzalloc(buf_len, GFP_KERNEL); |
| 451 | if (!buf) |
| 452 | return -ENOMEM; |
| 453 | |
| 454 | ret = -EFAULT; |
| 455 | if (get_user(uvcb.secret_idx, user_index)) |
| 456 | goto err; |
| 457 | |
| 458 | uvcb.buf_addr = (u64)buf; |
| 459 | uvcb.buf_size = buf_len; |
| 460 | uv_call_sched(0, (u64)&uvcb); |
| 461 | |
| 462 | if (copy_to_user(to: (__user void *)uv_ioctl->argument_addr, from: buf, n: buf_len)) |
| 463 | goto err; |
| 464 | |
| 465 | ret = 0; |
| 466 | uv_ioctl->uv_rc = uvcb.header.rc; |
| 467 | uv_ioctl->uv_rrc = uvcb.header.rrc; |
| 468 | |
| 469 | err: |
| 470 | kvfree_sensitive(addr: buf, len: buf_len); |
| 471 | return ret; |
| 472 | } |
| 473 | |
| 474 | static int uvio_copy_and_check_ioctl(struct uvio_ioctl_cb *ioctl, void __user *argp, |
| 475 | unsigned long cmd) |
| 476 | { |
| 477 | u8 nr = _IOC_NR(cmd); |
| 478 | |
| 479 | if (_IOC_DIR(cmd) != (_IOC_READ | _IOC_WRITE)) |
| 480 | return -ENOIOCTLCMD; |
| 481 | if (_IOC_TYPE(cmd) != UVIO_TYPE_UVC) |
| 482 | return -ENOIOCTLCMD; |
| 483 | if (nr >= UVIO_IOCTL_NUM_IOCTLS) |
| 484 | return -ENOIOCTLCMD; |
| 485 | if (_IOC_SIZE(cmd) != sizeof(*ioctl)) |
| 486 | return -ENOIOCTLCMD; |
| 487 | if (copy_from_user(ioctl, argp, sizeof(*ioctl))) |
| 488 | return -EFAULT; |
| 489 | if (ioctl->flags != 0) |
| 490 | return -EINVAL; |
| 491 | if (memchr_inv(ioctl->reserved14, 0, sizeof(ioctl->reserved14))) |
| 492 | return -EINVAL; |
| 493 | |
| 494 | return nr; |
| 495 | } |
| 496 | |
| 497 | /* |
| 498 | * IOCTL entry point for the Ultravisor device. |
| 499 | */ |
| 500 | static long uvio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
| 501 | { |
| 502 | void __user *argp = (void __user *)arg; |
| 503 | struct uvio_ioctl_cb uv_ioctl = { }; |
| 504 | long ret; |
| 505 | int nr; |
| 506 | |
| 507 | nr = uvio_copy_and_check_ioctl(ioctl: &uv_ioctl, argp, cmd); |
| 508 | if (nr < 0) |
| 509 | return nr; |
| 510 | |
| 511 | switch (nr) { |
| 512 | case UVIO_IOCTL_UVDEV_INFO_NR: |
| 513 | ret = uvio_uvdev_info(uv_ioctl: &uv_ioctl); |
| 514 | break; |
| 515 | case UVIO_IOCTL_ATT_NR: |
| 516 | ret = uvio_attestation(uv_ioctl: &uv_ioctl); |
| 517 | break; |
| 518 | case UVIO_IOCTL_ADD_SECRET_NR: |
| 519 | ret = uvio_add_secret(uv_ioctl: &uv_ioctl); |
| 520 | break; |
| 521 | case UVIO_IOCTL_LIST_SECRETS_NR: |
| 522 | ret = uvio_list_secrets(uv_ioctl: &uv_ioctl); |
| 523 | break; |
| 524 | case UVIO_IOCTL_LOCK_SECRETS_NR: |
| 525 | ret = uvio_lock_secrets(ioctl: &uv_ioctl); |
| 526 | break; |
| 527 | case UVIO_IOCTL_RETR_SECRET_NR: |
| 528 | ret = uvio_retr_secret(uv_ioctl: &uv_ioctl); |
| 529 | break; |
| 530 | default: |
| 531 | ret = -ENOIOCTLCMD; |
| 532 | break; |
| 533 | } |
| 534 | if (ret) |
| 535 | return ret; |
| 536 | |
| 537 | if (copy_to_user(to: argp, from: &uv_ioctl, n: sizeof(uv_ioctl))) |
| 538 | ret = -EFAULT; |
| 539 | |
| 540 | return ret; |
| 541 | } |
| 542 | |
| 543 | static const struct file_operations uvio_dev_fops = { |
| 544 | .owner = THIS_MODULE, |
| 545 | .unlocked_ioctl = uvio_ioctl, |
| 546 | }; |
| 547 | |
| 548 | static struct miscdevice uvio_dev_miscdev = { |
| 549 | .minor = MISC_DYNAMIC_MINOR, |
| 550 | .name = UVIO_DEVICE_NAME, |
| 551 | .fops = &uvio_dev_fops, |
| 552 | }; |
| 553 | |
| 554 | static void __exit uvio_dev_exit(void) |
| 555 | { |
| 556 | misc_deregister(misc: &uvio_dev_miscdev); |
| 557 | } |
| 558 | |
| 559 | static int __init uvio_dev_init(void) |
| 560 | { |
| 561 | set_supp_uv_cmds((unsigned long *)&uvdev_info.supp_uv_cmds); |
| 562 | return misc_register(misc: &uvio_dev_miscdev); |
| 563 | } |
| 564 | |
| 565 | module_cpu_feature_match(S390_CPU_FEATURE_UV, uvio_dev_init); |
| 566 | module_exit(uvio_dev_exit); |
| 567 | |
| 568 | MODULE_AUTHOR("IBM Corporation" ); |
| 569 | MODULE_LICENSE("GPL" ); |
| 570 | MODULE_DESCRIPTION("Ultravisor UAPI driver" ); |
| 571 | |