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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'x86_urgent_for_v6.3_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:
"There's a little bit more 'movement' in there for my taste but it
needs to happen and should make the code better after it.

- Check cmdline_find_option()'s return value before further
processing

- Clear temporary storage in the resctrl code to prevent access to an
unexistent MSR

- Add a simple throttling mechanism to protect the hypervisor from
potentially malicious SEV guests issuing requests in rapid
succession.

In order to not jeopardize the sanity of everyone involved in
maintaining this code, the request issuing side has received a
cleanup, split in more or less trivial, small and digestible
pieces. Otherwise, the code was threatening to become an
unmaintainable mess.

Therefore, that cleanup is marked indirectly also for stable so
that there's no differences between the upstream code and the
stable variant when it comes down to backporting more there"

* tag 'x86_urgent_for_v6.3_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/mm: Fix use of uninitialized buffer in sme_enable()
x86/resctrl: Clear staged_config[] before and after it is used
virt/coco/sev-guest: Add throttling awareness
virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case
virt/coco/sev-guest: Do some code style cleanups
virt/coco/sev-guest: Carve out the request issuing logic into a helper
virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()
virt/coco/sev-guest: Simplify extended guest request handling
virt/coco/sev-guest: Check SEV_SNP attribute at probe time

+145 -92
+2 -1
arch/x86/include/asm/sev-common.h
··· 128 128 struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY]; 129 129 } __packed; 130 130 131 - /* Guest message request error code */ 131 + /* Guest message request error codes */ 132 132 #define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32) 133 + #define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33) 133 134 134 135 #define GHCB_MSR_TERM_REQ 0x100 135 136 #define GHCB_MSR_TERM_REASON_SET_POS 12
+2 -5
arch/x86/kernel/cpu/resctrl/ctrlmondata.c
··· 368 368 { 369 369 struct resctrl_schema *s; 370 370 struct rdtgroup *rdtgrp; 371 - struct rdt_domain *dom; 372 371 struct rdt_resource *r; 373 372 char *tok, *resname; 374 373 int ret = 0; ··· 396 397 goto out; 397 398 } 398 399 399 - list_for_each_entry(s, &resctrl_schema_all, list) { 400 - list_for_each_entry(dom, &s->res->domains, list) 401 - memset(dom->staged_config, 0, sizeof(dom->staged_config)); 402 - } 400 + rdt_staged_configs_clear(); 403 401 404 402 while ((tok = strsep(&buf, "\n")) != NULL) { 405 403 resname = strim(strsep(&tok, ":")); ··· 441 445 } 442 446 443 447 out: 448 + rdt_staged_configs_clear(); 444 449 rdtgroup_kn_unlock(of->kn); 445 450 cpus_read_unlock(); 446 451 return ret ?: nbytes;
+1
arch/x86/kernel/cpu/resctrl/internal.h
··· 555 555 void rdt_domain_reconfigure_cdp(struct rdt_resource *r); 556 556 void __init thread_throttle_mode_init(void); 557 557 void __init mbm_config_rftype_init(const char *config); 558 + void rdt_staged_configs_clear(void); 558 559 559 560 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
+21 -4
arch/x86/kernel/cpu/resctrl/rdtgroup.c
··· 78 78 va_end(ap); 79 79 } 80 80 81 + void rdt_staged_configs_clear(void) 82 + { 83 + struct rdt_resource *r; 84 + struct rdt_domain *dom; 85 + 86 + lockdep_assert_held(&rdtgroup_mutex); 87 + 88 + for_each_alloc_capable_rdt_resource(r) { 89 + list_for_each_entry(dom, &r->domains, list) 90 + memset(dom->staged_config, 0, sizeof(dom->staged_config)); 91 + } 92 + } 93 + 81 94 /* 82 95 * Trivial allocator for CLOSIDs. Since h/w only supports a small number, 83 96 * we can keep a bitmap of free CLOSIDs in a single integer. ··· 3120 3107 { 3121 3108 struct resctrl_schema *s; 3122 3109 struct rdt_resource *r; 3123 - int ret; 3110 + int ret = 0; 3111 + 3112 + rdt_staged_configs_clear(); 3124 3113 3125 3114 list_for_each_entry(s, &resctrl_schema_all, list) { 3126 3115 r = s->res; ··· 3134 3119 } else { 3135 3120 ret = rdtgroup_init_cat(s, rdtgrp->closid); 3136 3121 if (ret < 0) 3137 - return ret; 3122 + goto out; 3138 3123 } 3139 3124 3140 3125 ret = resctrl_arch_update_domains(r, rdtgrp->closid); 3141 3126 if (ret < 0) { 3142 3127 rdt_last_cmd_puts("Failed to initialize allocations\n"); 3143 - return ret; 3128 + goto out; 3144 3129 } 3145 3130 3146 3131 } 3147 3132 3148 3133 rdtgrp->mode = RDT_MODE_SHAREABLE; 3149 3134 3150 - return 0; 3135 + out: 3136 + rdt_staged_configs_clear(); 3137 + return ret; 3151 3138 } 3152 3139 3153 3140 static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
+17 -9
arch/x86/kernel/sev.c
··· 2183 2183 struct ghcb *ghcb; 2184 2184 int ret; 2185 2185 2186 - if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) 2187 - return -ENODEV; 2188 - 2189 2186 if (!fw_err) 2190 2187 return -EINVAL; 2191 2188 ··· 2209 2212 if (ret) 2210 2213 goto e_put; 2211 2214 2212 - if (ghcb->save.sw_exit_info_2) { 2215 + *fw_err = ghcb->save.sw_exit_info_2; 2216 + switch (*fw_err) { 2217 + case 0: 2218 + break; 2219 + 2220 + case SNP_GUEST_REQ_ERR_BUSY: 2221 + ret = -EAGAIN; 2222 + break; 2223 + 2224 + case SNP_GUEST_REQ_INVALID_LEN: 2213 2225 /* Number of expected pages are returned in RBX */ 2214 - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && 2215 - ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) 2226 + if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { 2216 2227 input->data_npages = ghcb_get_rbx(ghcb); 2217 - 2218 - *fw_err = ghcb->save.sw_exit_info_2; 2219 - 2228 + ret = -ENOSPC; 2229 + break; 2230 + } 2231 + fallthrough; 2232 + default: 2220 2233 ret = -EIO; 2234 + break; 2221 2235 } 2222 2236 2223 2237 e_put:
+2 -1
arch/x86/mm/mem_encrypt_identity.c
··· 600 600 cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr | 601 601 ((u64)bp->ext_cmd_line_ptr << 32)); 602 602 603 - cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)); 603 + if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0) 604 + return; 604 605 605 606 if (!strncmp(buffer, cmdline_on, sizeof(buffer))) 606 607 sme_me_mask = me_mask;
+100 -72
drivers/virt/coco/sev-guest/sev-guest.c
··· 31 31 #define AAD_LEN 48 32 32 #define MSG_HDR_VER 1 33 33 34 + #define SNP_REQ_MAX_RETRY_DURATION (60*HZ) 35 + #define SNP_REQ_RETRY_DELAY (2*HZ) 36 + 34 37 struct snp_guest_crypto { 35 38 struct crypto_aead *tfm; 36 39 u8 *iv, *authtag; ··· 321 318 return __enc_payload(snp_dev, req, payload, sz); 322 319 } 323 320 321 + static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) 322 + { 323 + unsigned long err = 0xff, override_err = 0; 324 + unsigned long req_start = jiffies; 325 + unsigned int override_npages = 0; 326 + int rc; 327 + 328 + retry_request: 329 + /* 330 + * Call firmware to process the request. In this function the encrypted 331 + * message enters shared memory with the host. So after this call the 332 + * sequence number must be incremented or the VMPCK must be deleted to 333 + * prevent reuse of the IV. 334 + */ 335 + rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); 336 + switch (rc) { 337 + case -ENOSPC: 338 + /* 339 + * If the extended guest request fails due to having too 340 + * small of a certificate data buffer, retry the same 341 + * guest request without the extended data request in 342 + * order to increment the sequence number and thus avoid 343 + * IV reuse. 344 + */ 345 + override_npages = snp_dev->input.data_npages; 346 + exit_code = SVM_VMGEXIT_GUEST_REQUEST; 347 + 348 + /* 349 + * Override the error to inform callers the given extended 350 + * request buffer size was too small and give the caller the 351 + * required buffer size. 352 + */ 353 + override_err = SNP_GUEST_REQ_INVALID_LEN; 354 + 355 + /* 356 + * If this call to the firmware succeeds, the sequence number can 357 + * be incremented allowing for continued use of the VMPCK. If 358 + * there is an error reflected in the return value, this value 359 + * is checked further down and the result will be the deletion 360 + * of the VMPCK and the error code being propagated back to the 361 + * user as an ioctl() return code. 362 + */ 363 + goto retry_request; 364 + 365 + /* 366 + * The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been 367 + * throttled. Retry in the driver to avoid returning and reusing the 368 + * message sequence number on a different message. 369 + */ 370 + case -EAGAIN: 371 + if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) { 372 + rc = -ETIMEDOUT; 373 + break; 374 + } 375 + schedule_timeout_killable(SNP_REQ_RETRY_DELAY); 376 + goto retry_request; 377 + } 378 + 379 + /* 380 + * Increment the message sequence number. There is no harm in doing 381 + * this now because decryption uses the value stored in the response 382 + * structure and any failure will wipe the VMPCK, preventing further 383 + * use anyway. 384 + */ 385 + snp_inc_msg_seqno(snp_dev); 386 + 387 + if (fw_err) 388 + *fw_err = override_err ?: err; 389 + 390 + if (override_npages) 391 + snp_dev->input.data_npages = override_npages; 392 + 393 + /* 394 + * If an extended guest request was issued and the supplied certificate 395 + * buffer was not large enough, a standard guest request was issued to 396 + * prevent IV reuse. If the standard request was successful, return -EIO 397 + * back to the caller as would have originally been returned. 398 + */ 399 + if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) 400 + return -EIO; 401 + 402 + return rc; 403 + } 404 + 324 405 static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, 325 406 u8 type, void *req_buf, size_t req_sz, void *resp_buf, 326 407 u32 resp_sz, __u64 *fw_err) 327 408 { 328 - unsigned long err; 329 409 u64 seqno; 330 410 int rc; 331 411 ··· 424 338 if (rc) 425 339 return rc; 426 340 427 - /* 428 - * Call firmware to process the request. In this function the encrypted 429 - * message enters shared memory with the host. So after this call the 430 - * sequence number must be incremented or the VMPCK must be deleted to 431 - * prevent reuse of the IV. 432 - */ 433 - rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); 434 - 435 - /* 436 - * If the extended guest request fails due to having too small of a 437 - * certificate data buffer, retry the same guest request without the 438 - * extended data request in order to increment the sequence number 439 - * and thus avoid IV reuse. 440 - */ 441 - if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && 442 - err == SNP_GUEST_REQ_INVALID_LEN) { 443 - const unsigned int certs_npages = snp_dev->input.data_npages; 444 - 445 - exit_code = SVM_VMGEXIT_GUEST_REQUEST; 446 - 447 - /* 448 - * If this call to the firmware succeeds, the sequence number can 449 - * be incremented allowing for continued use of the VMPCK. If 450 - * there is an error reflected in the return value, this value 451 - * is checked further down and the result will be the deletion 452 - * of the VMPCK and the error code being propagated back to the 453 - * user as an ioctl() return code. 454 - */ 455 - rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); 456 - 457 - /* 458 - * Override the error to inform callers the given extended 459 - * request buffer size was too small and give the caller the 460 - * required buffer size. 461 - */ 462 - err = SNP_GUEST_REQ_INVALID_LEN; 463 - snp_dev->input.data_npages = certs_npages; 464 - } 465 - 466 - /* 467 - * Increment the message sequence number. There is no harm in doing 468 - * this now because decryption uses the value stored in the response 469 - * structure and any failure will wipe the VMPCK, preventing further 470 - * use anyway. 471 - */ 472 - snp_inc_msg_seqno(snp_dev); 473 - 474 - if (fw_err) 475 - *fw_err = err; 476 - 477 - /* 478 - * If an extended guest request was issued and the supplied certificate 479 - * buffer was not large enough, a standard guest request was issued to 480 - * prevent IV reuse. If the standard request was successful, return -EIO 481 - * back to the caller as would have originally been returned. 482 - */ 483 - if (!rc && err == SNP_GUEST_REQ_INVALID_LEN) 484 - return -EIO; 485 - 341 + rc = __handle_guest_request(snp_dev, exit_code, fw_err); 486 342 if (rc) { 487 - dev_alert(snp_dev->dev, 488 - "Detected error from ASP request. rc: %d, fw_err: %llu\n", 489 - rc, *fw_err); 490 - goto disable_vmpck; 343 + if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) 344 + return rc; 345 + 346 + dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); 347 + snp_disable_vmpck(snp_dev); 348 + return rc; 491 349 } 492 350 493 351 rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz); 494 352 if (rc) { 495 - dev_alert(snp_dev->dev, 496 - "Detected unexpected decode failure from ASP. rc: %d\n", 497 - rc); 498 - goto disable_vmpck; 353 + dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); 354 + snp_disable_vmpck(snp_dev); 355 + return rc; 499 356 } 500 357 501 358 return 0; 502 - 503 - disable_vmpck: 504 - snp_disable_vmpck(snp_dev); 505 - return rc; 506 359 } 507 360 508 361 static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) ··· 727 702 struct miscdevice *misc; 728 703 void __iomem *mapping; 729 704 int ret; 705 + 706 + if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) 707 + return -ENODEV; 730 708 731 709 if (!dev->platform_data) 732 710 return -ENODEV;