From: Tavis Ormandy <taviso@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
Subject: x86: AMD Zen2 ymm registers rolling back
Date: Tue, 21 Feb 2023 22:40:07 -0800 [thread overview]
Message-ID: <Y/W4x7/KFqmDmmR7@thinkstation.cmpxchg8b.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 2234 bytes --]
Hello, I'm experiencing a serious bug on AMD Zen2 that is causing
registers to "roll back" to previous values after a context switch.
I know that sounds unbelievable - but I have a reliable reproducer!
$ grep -m1 'model name' /proc/cpuinfo
model name : AMD Ryzen Threadripper PRO 3945WX 12-Cores
The bug occurs when there is a context switch after a ucomiss
instruction. The YMM registers are "rolled back" to some previous state.
It's not clear to me how or why this is happening, or if it can happen
across a process boundary.
To reproduce:
$ nasm -felf64 -O0 zenymmasm.asm
$ ld -o zenymmasm zenymmasm.o
If you run it it should just print some nuls:
$ ./zenymmasm
$
That is the expected, correct result.
However, if you run the attached program hammer.c (it just runs
sched_yield() in a loop), and then pin this testcase to the same core as
that:
$ taskset -c 1 ./zenymmasm
SECRETSECRET
The previous register values are restored.
I think this should be impossible.
The code does this:
vmovdqu ymm0, [rel secret] <--- put SECRET into ymm0
mov rax, SYS_sched_yield
syscall
vpxor ymm0, ymm0, ymm0 <--- Here the value of ymm0 should be lost
It's not related to to VPXOR, you can use VZEROALL or whatever else.
ucomiss xmm0, dword [rel space]
mov rax, SYS_sched_yield
syscall
It's the UCOMISS r128,m32 instruction that triggers the bug, the value
of the m32 must be < 0x80000. As far as I know, this should only ever
change condition flags, but if we dump the value of ymm0:
mov rax, SYS_write
mov rdi, 1
lea rsi, [rel regstate]
mov rdx, 32
syscall
It will have reverted back to the pre-vpxor SECRET value !?!?
In the original C program, we were seeing register values randomly
restored from significantly earlier in the program execution (like, from
ld.so), sometimes values we don't recognize and can't explain.
We've reproduced on multiple Zen2 machines.
Obviously, not great if your registers are randomly time travelling :)
Thanks, Tavis.
--
_o) $ lynx lock.cmpxchg8b.com
/\\ _o) _o) $ finger taviso@sdf.org
_\_V _( ) _( ) @taviso
[-- Attachment #2: hammer.c --]
[-- Type: text/plain, Size: 578 bytes --]
#define _GNU_SOURCE
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <sched.h>
#include <syscall.h>
#include <x86intrin.h>
#include <sys/random.h>
#include <err.h>
int main(int argc, char **argv)
{
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(1, &set);
if (sched_setaffinity(0, sizeof(set), &set) != 0) {
err(EXIT_FAILURE, "failed to set cpu affinity");
}
while (true) {
asm volatile ("syscall" :: "a"(SYS_sched_yield) : "rcx", "r11");
}
return 0;
}
[-- Attachment #3: zenymmasm.asm --]
[-- Type: text/plain, Size: 802 bytes --]
BITS 64
global _start
%define SYS_sched_yield 0x18
%define SYS_write 0x01
%define SYS_exit 0x3c
section .data
align 32
secret: times 4 dq 'SECRET'
align 32
regstate: dq 0,0,0,0
align 32
space: dd 1
section .text
_start:
vmovdqu ymm0, [rel secret]
mov rax, SYS_sched_yield
syscall
vpxor ymm0, ymm0, ymm0
mov rax, SYS_sched_yield
syscall
ucomiss xmm0, dword [rel space]
mov rax, SYS_sched_yield
syscall
vmovdqu [rel regstate], ymm0
mov rax, SYS_write
mov rdi, 1
lea rsi, [rel regstate]
mov rdx, 32
syscall
mov rax, SYS_exit
mov rdi, 0
syscall
int3
next reply other threads:[~2023-02-22 6:40 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-22 6:40 Tavis Ormandy [this message]
2023-02-22 8:33 ` Borislav Petkov
2023-02-22 9:14 ` Borislav Petkov
2023-02-22 9:38 ` Andrew Cooper
2023-02-22 10:09 ` Borislav Petkov
2023-02-22 21:26 ` Tavis Ormandy
2023-02-22 22:17 ` Andrew Cooper
2023-02-22 22:26 ` Borislav Petkov
2023-02-22 22:25 ` Borislav Petkov
2023-02-28 18:47 ` Alexander Monakov
2023-02-28 19:20 ` Borislav Petkov
2023-02-28 19:24 ` Alexander Monakov
2023-02-28 19:25 ` Borislav Petkov
2023-02-28 19:29 ` Alexander Monakov
2023-02-28 19:38 ` Andrew Cooper
2023-02-28 21:45 ` Alexander Monakov
2023-02-28 20:56 ` Borislav Petkov
2023-02-28 21:16 ` Alexander Monakov
2023-03-01 0:23 ` Andrew Cooper
2023-03-01 8:54 ` Borislav Petkov
2023-03-07 16:45 ` Tavis Ormandy
2023-03-07 17:46 ` [PATCH] x86/amd: Work around Erratum 1386 - XSAVES malfunction on context switch Andrew Cooper
2023-03-07 17:50 ` Borislav Petkov
2023-03-07 18:22 ` Andrew Cooper
2023-03-07 18:56 ` Borislav Petkov
2023-03-07 20:01 ` Andrew Cooper
2023-03-07 20:09 ` Borislav Petkov
2023-03-14 16:01 ` Dave Hansen
2023-03-08 16:23 ` [tip: x86/urgent] x86/CPU/AMD: Disable XSAVES on AMD family 0x17 tip-bot2 for Andrew Cooper
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y/W4x7/KFqmDmmR7@thinkstation.cmpxchg8b.net \
--to=taviso@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®