od redakcji: Michał Zalewski (aka lcamtuf) zbiera informacje dotyczące błędu w biosach. W związku z tym, że sam nie posiada tysięcy maszyn, zwraca się do was, drodzy czytelnicy, z prośbą o pomoc. Po konkrety zapraszamy do publikowanego niżej tekstu.
To jest prosty test, ktory, przeprowadzony na Linuxie, pozwoli ustalic, czy BIOS danego komputera jest podatny na brzydkiego buga, ktory znalazlem na swoim laptopie, a ktory pozwala na zawieszenie komputera w sprzyjajacych okolicznosciach. Co moge zaoferowac w zamian za poswiecenie? Moja wdziecznosc, i oczywiscie ewentualnie patcha =)
Szybkie wyjasnienie o co chodzi: test sprawdza, czy przy miekkim reboocie wasz BIOS zeruje pewne specjalne rejestry procesora kontrolujace dzialanie opcodu SYSENTER w nowszych CPU (nieuzywany w Linuxie 2.2 i 2.4). Robimy to przez wpisanie bzdurnej wartosci (1234) to jednego z tych rejestrow, zweryfikowanie jego stanu, reboot, ponowne odczytanie stanu. Aha, zmiana tej wartosci nie ma zadnych szczegolnych skutkow dla pracy systemu, po „zimnym” reboocie (wylaczenie komputera albo guzik RESET), rejestr zostanie zawsze wyzerowany, wiec nie ma sie czego bac.
Wymagania: komputer, ktory jest testowany, to musi byc przynajmniej Pentium II (moze byc lepszy); musicie wykonywac wszystkie polecenia z roota (spokojnie, nie ma tam niespodzianek); wymagany jest stabilny kernel (2.2 lub 2.4); musicie miec jako modul lub wkompilowana w kernel obsluge MSR (zwykle domyslne).
Jesli nie macie katalogu /dev/cpu, musicie pierw wykonac nastepujace polecenie (jako root):
mkdir -m 700 -p /dev/cpu/0
mknod /dev/cpu/0/msr c 202 0
…dobra, do rzeczy. Ponizej znajduja sie dwa krociutkie programy, program1.c i program2.c. Nalezy zapisac je w stosownych plikach i wykonac 'make program1′ i 'make program2′. Warningi mozna spokojnie zignorowac.
Nastepnie nalezy uruchomic ./program1. Jesli upomni sie o modul 'msr’, wpiszcie '/sbin/insmod msr’ i uruchomcie go ponownie. UWAGA: jesli nie macie tego modulu, utworzyliscie /dev/cpu/0/msr, i mimo to wciaz dostajecie taki komunikat, kernel najprawdopodobniej nie obsluguje tej funkcjonalnosci, i dalsze testy nie maja sensu (chyba, ze mozecie sie zbootowac do nowszej wersji).
Jesli program1 powie „Ok, zrobione”, nalezy odpalic ./program2. Powinien on powiedziec „Wynik prawidlowy”. Jesli tak, mozemy kontynuowac, jesli nie, kontynuowanie testu nie ma sensu.
Teraz nalezy „miekko” zrebootowac maszyne – NIE NALEZY UZYWAC GUZIKA RESET ANI WYLACZAC ZASILANIA. Dopuszczalne jest tylko polecenie 'reboot’ albo Ctrl-Alt-Del. Twardy reboot zafalszuje wyniki testu.
Po zbootowaniu Linuxa, nalezy odpalic ponownie ./program2 – uwaga, TYLKO ./program2. Jesli uruchomicie przez pomylke ./program1, wyniki testu beda zafalszowane.
Jesli ./program2 powie „Wynik jest inny”, wasz BIOS zachowuje sie przyzwoicie i nie ma sie czym przejmowac. Jesli ./program2 powie „Wynik prawidlowy”, oznacza to, ze BIOS zachowal sie nieprzyzwoicie.
Jesli dostaniecie ten drugi komunikat – „wynik prawidlowy” – prosilbym o zgloszenie wersji BIOSu czy chocby informacji o producencie i roku wypuszczenia, zgodnie z tym, co pojawia sie przy boocie… Jesli macie zainstalowane polecenie 'dmidecode’ (standard w nowszych Linuxach), mozecie dokladnie okreslic wersje BIOSu bez koniecznosci resetowania – wpiszcie:
dmidecode | grep -A 6 'BIOS Information Block'
…i wyslijcie wynik pracy tego polecenia.
Wyniki prosze przysylac na LCAMTUF@coredump.cx. Z gory dziekuje za poswiecenie 🙂
-- program1.c -- #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> void main(void) { unsigned long long w = 1234; int i = open("/dev/cpu/0/msr",O_WRONLY); if (i<0) { printf("Wpisz 'insmod msr', co?n"); exit(0); } lseek(i,0x174,SEEK_SET); if (write(i,&w,8) < 0) { printf("Nie ma takiego MSRa, blad.n"); exit(0); } printf("Ok, zrobione.n"); } -- EOF -- -- program2.c -- #include <stdio.h> #include <unistd.h> #include <stdlib.h> #includevoid main(void) { unsigned long long w; int i = open("/dev/cpu/0/msr",O_RDONLY); if (i<0) { printf("Wpisz 'insmod msr', co?n"); exit(0); } lseek(i,0x174,SEEK_SET); if (read(i,&w,8) < 0) { printf("Nie ma takiego MSRa, blad.n"); exit(0); } if (w == 1234) printf("Wynik prawidlowy.n"); else printf("Wynik jest inny.n"); } -- EOF --
Archiwalny news dodany przez użytkownika: lcamtuf.
Kliknij tutaj by zobaczyć archiwalne komentarze.