Skip to content

Commit 8d561ba

Browse files
committed
Merge tag 'x86_urgent_for_v6.17_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Borislav Petkov: - Remove a transitional asm/cpuid.h header which was added only as a fallback during cpuid helpers reorg - Initialize reserved fields in the SVSM page validation calls structure to zero in order to allow for future structure extensions - Have the sev-guest driver's buffers used in encryption operations be in linear mapping space as the encryption operation can be offloaded to an accelerator - Have a read-only MSR write when in an AMD SNP guest trap to the hypervisor as it is usually done. This makes the guest user experience better by simply raising a #GP instead of terminating said guest - Do not output AVX512 elapsed time for kernel threads because the data is wrong and fix a NULL pointer dereferencing in the process - Adjust the SRSO mitigation selection to the new attack vectors * tag 'x86_urgent_for_v6.17_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpuid: Remove transitional <asm/cpuid.h> header x86/sev: Ensure SVSM reserved fields in a page validation entry are initialized to zero virt: sev-guest: Satisfy linear mapping requirement in get_derived_key() x86/sev: Improve handling of writes to intercepted TSC MSRs x86/fpu: Fix NULL dereference in avx512_status() x86/bugs: Select best SRSO mitigation
2 parents 0a9ee9c + ed6c4b6 commit 8d561ba

File tree

8 files changed

+53
-50
lines changed

8 files changed

+53
-50
lines changed

Documentation/admin-guide/hw-vuln/attack_vector_controls.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ Spectre_v1 X
214214
Spectre_v2 X X
215215
Spectre_v2_user X X * (Note 1)
216216
SRBDS X X X X
217-
SRSO X X
217+
SRSO X X X X
218218
SSB (Note 4)
219219
TAA X X X X * (Note 2)
220220
TSA X X X X

arch/x86/boot/startup/sev-shared.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ static void __head svsm_pval_4k_page(unsigned long paddr, bool validate)
785785
pc->entry[0].page_size = RMP_PG_SIZE_4K;
786786
pc->entry[0].action = validate;
787787
pc->entry[0].ignore_cf = 0;
788+
pc->entry[0].rsvd = 0;
788789
pc->entry[0].pfn = paddr >> PAGE_SHIFT;
789790

790791
/* Protocol 0, Call ID 1 */

arch/x86/coco/sev/core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ static u64 svsm_build_ca_from_pfn_range(u64 pfn, u64 pfn_end, bool action,
227227
pe->page_size = RMP_PG_SIZE_4K;
228228
pe->action = action;
229229
pe->ignore_cf = 0;
230+
pe->rsvd = 0;
230231
pe->pfn = pfn;
231232

232233
pe++;
@@ -257,6 +258,7 @@ static int svsm_build_ca_from_psc_desc(struct snp_psc_desc *desc, unsigned int d
257258
pe->page_size = e->pagesize ? RMP_PG_SIZE_2M : RMP_PG_SIZE_4K;
258259
pe->action = e->operation == SNP_PAGE_STATE_PRIVATE;
259260
pe->ignore_cf = 0;
261+
pe->rsvd = 0;
260262
pe->pfn = e->gfn;
261263

262264
pe++;

arch/x86/coco/sev/vc-handle.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -371,29 +371,30 @@ static enum es_result __vc_handle_msr_caa(struct pt_regs *regs, bool write)
371371
* executing with Secure TSC enabled, so special handling is required for
372372
* accesses of MSR_IA32_TSC and MSR_AMD64_GUEST_TSC_FREQ.
373373
*/
374-
static enum es_result __vc_handle_secure_tsc_msrs(struct pt_regs *regs, bool write)
374+
static enum es_result __vc_handle_secure_tsc_msrs(struct es_em_ctxt *ctxt, bool write)
375375
{
376+
struct pt_regs *regs = ctxt->regs;
376377
u64 tsc;
377378

378379
/*
379-
* GUEST_TSC_FREQ should not be intercepted when Secure TSC is enabled.
380-
* Terminate the SNP guest when the interception is enabled.
380+
* Writing to MSR_IA32_TSC can cause subsequent reads of the TSC to
381+
* return undefined values, and GUEST_TSC_FREQ is read-only. Generate
382+
* a #GP on all writes.
381383
*/
382-
if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ)
383-
return ES_VMM_ERROR;
384+
if (write) {
385+
ctxt->fi.vector = X86_TRAP_GP;
386+
ctxt->fi.error_code = 0;
387+
return ES_EXCEPTION;
388+
}
384389

385390
/*
386-
* Writes: Writing to MSR_IA32_TSC can cause subsequent reads of the TSC
387-
* to return undefined values, so ignore all writes.
388-
*
389-
* Reads: Reads of MSR_IA32_TSC should return the current TSC value, use
390-
* the value returned by rdtsc_ordered().
391+
* GUEST_TSC_FREQ read should not be intercepted when Secure TSC is
392+
* enabled. Terminate the guest if a read is attempted.
391393
*/
392-
if (write) {
393-
WARN_ONCE(1, "TSC MSR writes are verboten!\n");
394-
return ES_OK;
395-
}
394+
if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ)
395+
return ES_VMM_ERROR;
396396

397+
/* Reads of MSR_IA32_TSC should return the current TSC value. */
397398
tsc = rdtsc_ordered();
398399
regs->ax = lower_32_bits(tsc);
399400
regs->dx = upper_32_bits(tsc);
@@ -416,7 +417,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
416417
case MSR_IA32_TSC:
417418
case MSR_AMD64_GUEST_TSC_FREQ:
418419
if (sev_status & MSR_AMD64_SNP_SECURE_TSC)
419-
return __vc_handle_secure_tsc_msrs(regs, write);
420+
return __vc_handle_secure_tsc_msrs(ctxt, write);
420421
break;
421422
default:
422423
break;

arch/x86/include/asm/cpuid.h

Lines changed: 0 additions & 8 deletions
This file was deleted.

arch/x86/kernel/cpu/bugs.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ static bool __init should_mitigate_vuln(unsigned int bug)
386386

387387
case X86_BUG_SPECTRE_V2:
388388
case X86_BUG_RETBLEED:
389-
case X86_BUG_SRSO:
390389
case X86_BUG_L1TF:
391390
case X86_BUG_ITS:
392391
return cpu_attack_vector_mitigated(CPU_MITIGATE_USER_KERNEL) ||
@@ -3184,8 +3183,18 @@ static void __init srso_select_mitigation(void)
31843183
}
31853184

31863185
if (srso_mitigation == SRSO_MITIGATION_AUTO) {
3187-
if (should_mitigate_vuln(X86_BUG_SRSO)) {
3186+
/*
3187+
* Use safe-RET if user->kernel or guest->host protection is
3188+
* required. Otherwise the 'microcode' mitigation is sufficient
3189+
* to protect the user->user and guest->guest vectors.
3190+
*/
3191+
if (cpu_attack_vector_mitigated(CPU_MITIGATE_GUEST_HOST) ||
3192+
(cpu_attack_vector_mitigated(CPU_MITIGATE_USER_KERNEL) &&
3193+
!boot_cpu_has(X86_FEATURE_SRSO_USER_KERNEL_NO))) {
31883194
srso_mitigation = SRSO_MITIGATION_SAFE_RET;
3195+
} else if (cpu_attack_vector_mitigated(CPU_MITIGATE_USER_USER) ||
3196+
cpu_attack_vector_mitigated(CPU_MITIGATE_GUEST_GUEST)) {
3197+
srso_mitigation = SRSO_MITIGATION_MICROCODE;
31893198
} else {
31903199
srso_mitigation = SRSO_MITIGATION_NONE;
31913200
return;

arch/x86/kernel/fpu/xstate.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,19 +1881,20 @@ long fpu_xstate_prctl(int option, unsigned long arg2)
18811881
#ifdef CONFIG_PROC_PID_ARCH_STATUS
18821882
/*
18831883
* Report the amount of time elapsed in millisecond since last AVX512
1884-
* use in the task.
1884+
* use in the task. Report -1 if no AVX-512 usage.
18851885
*/
18861886
static void avx512_status(struct seq_file *m, struct task_struct *task)
18871887
{
1888-
unsigned long timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp);
1889-
long delta;
1888+
unsigned long timestamp;
1889+
long delta = -1;
18901890

1891-
if (!timestamp) {
1892-
/*
1893-
* Report -1 if no AVX512 usage
1894-
*/
1895-
delta = -1;
1896-
} else {
1891+
/* AVX-512 usage is not tracked for kernel threads. Don't report anything. */
1892+
if (task->flags & (PF_KTHREAD | PF_USER_WORKER))
1893+
return;
1894+
1895+
timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp);
1896+
1897+
if (timestamp) {
18971898
delta = (long)(jiffies - timestamp);
18981899
/*
18991900
* Cap to LONG_MAX if time difference > LONG_MAX

drivers/virt/coco/sev-guest/sev-guest.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,11 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
116116

117117
static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
118118
{
119+
struct snp_derived_key_resp *derived_key_resp __free(kfree) = NULL;
119120
struct snp_derived_key_req *derived_key_req __free(kfree) = NULL;
120-
struct snp_derived_key_resp derived_key_resp = {0};
121121
struct snp_msg_desc *mdesc = snp_dev->msg_desc;
122122
struct snp_guest_req req = {};
123123
int rc, resp_len;
124-
/* Response data is 64 bytes and max authsize for GCM is 16 bytes. */
125-
u8 buf[64 + 16];
126124

127125
if (!arg->req_data || !arg->resp_data)
128126
return -EINVAL;
@@ -132,8 +130,9 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
132130
* response payload. Make sure that it has enough space to cover the
133131
* authtag.
134132
*/
135-
resp_len = sizeof(derived_key_resp.data) + mdesc->ctx->authsize;
136-
if (sizeof(buf) < resp_len)
133+
resp_len = sizeof(derived_key_resp->data) + mdesc->ctx->authsize;
134+
derived_key_resp = kzalloc(resp_len, GFP_KERNEL_ACCOUNT);
135+
if (!derived_key_resp)
137136
return -ENOMEM;
138137

139138
derived_key_req = kzalloc(sizeof(*derived_key_req), GFP_KERNEL_ACCOUNT);
@@ -149,23 +148,21 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
149148
req.vmpck_id = mdesc->vmpck_id;
150149
req.req_buf = derived_key_req;
151150
req.req_sz = sizeof(*derived_key_req);
152-
req.resp_buf = buf;
151+
req.resp_buf = derived_key_resp;
153152
req.resp_sz = resp_len;
154153
req.exit_code = SVM_VMGEXIT_GUEST_REQUEST;
155154

156155
rc = snp_send_guest_request(mdesc, &req);
157156
arg->exitinfo2 = req.exitinfo2;
158-
if (rc)
159-
return rc;
160-
161-
memcpy(derived_key_resp.data, buf, sizeof(derived_key_resp.data));
162-
if (copy_to_user((void __user *)arg->resp_data, &derived_key_resp,
163-
sizeof(derived_key_resp)))
164-
rc = -EFAULT;
157+
if (!rc) {
158+
if (copy_to_user((void __user *)arg->resp_data, derived_key_resp,
159+
sizeof(derived_key_resp->data)))
160+
rc = -EFAULT;
161+
}
165162

166163
/* The response buffer contains the sensitive data, explicitly clear it. */
167-
memzero_explicit(buf, sizeof(buf));
168-
memzero_explicit(&derived_key_resp, sizeof(derived_key_resp));
164+
memzero_explicit(derived_key_resp, sizeof(*derived_key_resp));
165+
169166
return rc;
170167
}
171168

0 commit comments

Comments
 (0)