Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpuid_fault not working as expected #1330

Closed
wangbj opened this issue Oct 15, 2019 · 0 comments
Closed

cpuid_fault not working as expected #1330

wangbj opened this issue Oct 15, 2019 · 0 comments

Comments

@wangbj
Copy link

wangbj commented Oct 15, 2019

  • BIG assumption: firecracker is the HVM used for EC2 (t2.micro):

CPUID faulting allow user space programs simulate CPUID instruction, by trapping cpuid instruction to SEGSEGV: https://lore.kernel.org/patchwork/patch/726765/

This is done by query PLATFORM_INFO (0xce) MSR, bit-31. When bit-31 is set, the cpuid_fault can be done by write/clear MISC_FEATURES_ENABLES, bit-0.

On an AWS EC2 t2.micro instance, cpuid_fault is present:

$ sudo modprobe msr
$ sudo rdmsr -x 0xce
20080c33f3811800      # bit-31 is set.

And can be confirmed by cat /proc/cpuinfo as well:

$ cat /proc/cpuinfo | grep cpuid_fault
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm cpuid_fault invpcid_single pti fsgsbase bmi1 avx2 smep bmi2 erms invpcid xsaveopt

However, below program doesn't work as expected:

#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <asm/prctl.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <cpuid.h>
#include <signal.h>
#include <string.h>

int arch_prctl(int code, unsigned long addr);

static void sigsegv_action(int signo, siginfo_t* siginfo, void* ucontext) {
  const char msg[] = "got expected sigsegv\n";
  write(STDOUT_FILENO, msg, sizeof(msg));
  _exit(0);
}

int main(int argc, char* argv[])
{
  assert(arch_prctl(ARCH_SET_CPUID, 0) == 0);

  unsigned long eax, ebx, ecx, edx;

  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));

  sa.sa_flags = SA_ONESHOT | SA_RESTART | SA_SIGINFO | SA_RESETHAND;
  sa.sa_sigaction = sigsegv_action;
  assert(sigaction(SIGSEGV, &sa, NULL) == 0);

  // should segfault
  __cpuid(0x1, eax, ebx, ecx, edx);
  printf("eax=%lx\n", eax);

  return 0;
}

The expected result is it should segfault (print got expected sigsegv), but on t2.micro, the program prints eax=306f2 instead. It implies the kernel indeed received the arch_prctl request, and set the hardware register, but the VM (firecracker) somehow ignored the write to MISC_FEATURES_ENABLES, bit-0.

More details can be found in this application note.

At first I thought it might be an AWS kernel (optimization) issue, hence tried both on kernel: 4.15.0-1051-aws and 4.15.0-65-generic, but the results were the same.

More information about the system setup:

  • AWS ec2 t2.micro
  • stock ubuntu 18.04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant