Dlaczego nie można programowo zrealizować ochrony pamięci?

Odpowiedz Nowy wątek
2016-02-17 17:42
0

Jakiś czas temu dowiedziałem się, że ochrona pamięci musi być realizowa sprzętowo, bo programowa jej emulacja spowolniłaby wykonanie nawet ze 100 razy.

Nie za bardzo rozumiem, dlaczego?

Ot, pomysł. System operacyjny działa na procesorze nie posiadającym wsparcia dla ochrony pamięci. W związku z tym, za każdym razem, gdy uruchamiany jest jakiś program, OS wpierw skanuje binarkę w poszukiwaniu odwołań do pamięci operacyjnej (ale już nie np. rejestrów procesora) i każde takie odwołanie otacza ifami sprawdzającymi, czy adres jest w porządku.

Pewnie napisałem bzdury…?

kmph ostatnio zakładasz dziwne tematy. może zmień książkę albo dilera - karolinaa 2016-02-17 18:13
Ale ja tak mam zawsze, co najwyżej czasem się powstrzymuję :( - kmph 2016-02-17 18:15

Pozostało 580 znaków

2016-02-17 17:56
3
  1. A zdajesz sobie sprawę że programy cały czas się odwołują do pamięci? Wiesz ile byś miał takich ifów? o_O Poza tym czym jest "odwołanie do pamięci"? Skok pod jakis adres to też jakieś odwołanie do pamięci. Chcesz testować też każdy skok?
  2. A co z alokacjami/realokacjami? Przecież przestrzeń adresowa procesu cały czas może ulegać zmianie... więc i te twoje "poprawne zakresy" też by musiały być płynne i zmienne.

Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

2016-02-17 18:15
1

No, i gdyby kod byłby self-modifying to już w ogóle ify (i statyczna analiza też) leżą i kwiczą.
Ale przykładowo pomijając nowoczesne systemy, na 8086 (i podobnych) gdzie właściwie nie było ochrony pamięci poza segmentacją to w pewnym stopniu było by chyba możliwe, jako taki proof-of-concept. Wykluczając też że kod będzie się sam modyfikował. Deasemblujesz i parsujesz sobie binarkę i np. Emulujesz jakoś (w sensie na wyrywki) stan procesora przed każdą instrukcją która odnosi się do pamięci.
// edit
A najfajniejszy to byłby chyba framework do emulacji może niekoniecznie całego procka od zera, ale coś trochę jak Wine, który odpalałby program w emulowanym środowisku i jednocześnie dawał pełny wgląd do jego bebechów.
Jeśli piszę głupoty to sorry, ale tak też sie ostatnio nad podobnymi sprawami zastanawiałem :P

edytowany 2x, ostatnio: Proxima, 2016-02-17 18:22

Pozostało 580 znaków

2016-02-17 18:25
3

każde takie odwołanie otacza ifami sprawdzającymi, czy adres jest w porządku.

Samo takie otaczanie zmienia adresy w kodzie. A OS nie jest w stanie wykryć co jest kodem, a co danymi, bo mogą być one przemieszane z sobą. Dodatkowo x86 zezwala na dowolną arytmetykę wskaźników i możesz mieć zmienne typu połowaAdresuMagicznejZmiennej, którą to potem skalujesz przez 2 podczas użycia. W jaki sposób parser miałby się zorientować statycznie, że coś takiego będzie miało miejsce w czasie wykonania? W dość ekstremalnym przypadku to nawet program może sobie ściągnąć adresy z neta. I co wtedy? Ściąganie całego Internetu przed odpaleniem programu?


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit, 2016-02-17 18:28

Pozostało 580 znaków

2016-02-18 12:18
0
kmph napisał(a):

Jakiś czas temu dowiedziałem się, że ochrona pamięci musi być realizowa sprzętowo, bo programowa jej emulacja spowolniłaby wykonanie nawet ze 100 razy.

Nie to, że musi. Jest to wydajniejsze. Tak samo jak nowoczesny krzem zawiera specjalne instrukcje do obslugi np. aes albo kodekow wideo.

kmph napisał(a):

Ot, pomysł. System operacyjny działa na procesorze nie posiadającym wsparcia dla ochrony pamięci. W związku z tym, za każdym razem, gdy uruchamiany jest jakiś program, OS wpierw skanuje binarkę w poszukiwaniu odwołań do pamięci operacyjnej (ale już nie np. rejestrów procesora) i każde takie odwołanie otacza ifami sprawdzającymi, czy adres jest w porządku.

  1. System nie wie jeszcze jakie adresu są w porządku. Zakres adresów może być przydzielony podczas działania programy poprzez syscalle albo bibliotekę standardową (ktora i tak uzywa syscalli).
  2. Generalnie coś podobnego jest realizowane z pomocą sprzętu. Tzn:
    • system ładuje binarkę, zapisuje sobie mapowania pamieci, tworzy podstawowe mapowania stron dla kontrolera pamieci
    • gdy program odnosi się do jakiegos miejsca w pamieci kontroler sprawdza czy dany adres wirtualny jest zamapowany
    • jezeli adres nie jest zmapowany w kontrolerze to jest wysylany sygnal (przerwanie sprzetowe)
    • przerwanie powoduje wykonanie procedury obslugi pamieci, system sprawdza czy dany adres jest poprawny dla danego procesu, jezeli jest poprawny ale nie zamapowany w kontolerze to go domapowuje i przydziela strony fizyczne, jak jest niepoprawny to wysyla odpowiedni sygnal do procesu, co skutkuje zazwyczaj jego zabiciem
  3. Widzisz proces powyżej? To się dzieje non stop podczas czasu życia programu jak odnosi się do jakiegoś adresu wirtualnego. Dlatego wykorzystywane jest wsparcie sprzętowe.

    Wibowit napisał(a):

    każde takie odwołanie otacza ifami sprawdzającymi, czy adres jest w porządku.

    Samo takie otaczanie zmienia adresy w kodzie. A OS nie jest w stanie wykryć co jest kodem, a co danymi, bo mogą być one przemieszane z sobą.

A sekcje .text i .data w binarce (elf), uprawnienia sekcji oraz oddzielny adress space dla instrukcji i danych w architekurze Harvardzkiej coś Ci mówią? :)

PS.
http://sva.cs.illinois.edu/index.html (http://sva.cs.illinois.edu/sva.html)

edytowany 5x, ostatnio: nalik, 2016-02-18 12:25
tylko że x86 nie ma architektury harvardzkiej. - Azarien 2016-02-18 13:04

Pozostało 580 znaków

2016-02-18 12:57
0

A sekcje .text i .data w binarce (elf), uprawnienia sekcji oraz oddzielny adress space dla instrukcji i danych w architekurze Harvardzkiej coś Ci mówią? :)

Kodziłem przez wiele lat w czystym asemblerze pod 16-bit i 32-bit. Wiem o czym mówię. Da się spokojnie pomieszać dane z kodem w architekturze x86. Da się też tworzyć samo-modyfikowalny kod. Zakładam też, że autora interesuje architektura x86.

Ponadto, za https://en.wikipedia.org/wiki/Modified_Harvard_architecture :

The Modified Harvard architecture is a variation of the Harvard computer architecture that allows the contents of the instruction memory to be accessed as if it were data. Most modern computers that are documented as Harvard architecture are, in fact, Modified Harvard architecture.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Da się też tworzyć samo-modyfikowalny kod - tak działa .NET przecież. jeśli funkcja jest jeszcze niezJITowana, za pierwszym razem gdy jest wykonana następuje skok do JITa, JIT tworzy kod binarny na podstawie kodu pośredniego, po czym następuje skok do skompilowanej funkcji. za następnym razem funkcja jest już wywoływana od razu. wszystko się dzieje w ramach uruchamianego procesu, niejako „oddolnie”. - Azarien 2016-02-18 13:17
JVM (HotSpot) działa tak samo. Tyle, że nie za pierwszym razem, a dopiero po rozgrzaniu danego kawałka kodu. Rozgrzanie kawałka kodu to wykonanie go określoną ilość razy. Nazwa HotSpot nawiązuje do tego rozgrzewania. - Wibowit 2016-02-18 13:57

Pozostało 580 znaków

2016-02-18 13:03
0

Samo takie otaczanie zmienia adresy w kodzie. A OS nie jest w stanie wykryć co jest kodem, a co danymi, bo mogą być one przemieszane z sobą.

Jestem w stanie sobie wyobrazić maszynę wirtualną na wzór Javy czy .NETa, której kod pośredni byłby zgodny z x86 a VM implementowałaby programowo kontrolę pamięci.
Ale wtedy to przecież będzie po prostu emulator.

Tu nie chodzi o "programowo" kontra "sprzętowo". Kontrola pamięci musi być transcendentna względem uruchamianego programu - musi pochodzić z zewnątrz – czy to od sprzętu czy od udającego sprzęt emulatora – a nie da się jej zrobić sensownie w ramach wykonywanego kodu (i nie jest to kwestia uprawnień user vs kernel).

Pozostało 580 znaków

2016-02-18 13:12
0
Wibowit napisał(a):

A sekcje .text i .data w binarce (elf), uprawnienia sekcji oraz oddzielny adress space dla instrukcji i danych w architekurze Harvardzkiej coś Ci mówią? :)

Kodziłem przez wiele lat w czystym asemblerze pod 16-bit i 32-bit. Wiem o czym mówię. Da się spokojnie pomieszać dane z kodem w architekturze x86. Da się też tworzyć samo-modyfikowalny kod. Zakładam też, że autora interesuje architektura x86.

W czystym asm bez kernala owszem. Ale da się też temu zapobiec. To system operacyjny definiuje ABI. System definiuje format dla kontenera kodu. System narzuca mechanizmy ochronne. Kompilator dorzuca mechanizmy ochronne do twojego kodu i to on emituje binarke, ktora jest w stanie sie prozumiec z systemem. Teoretycznie wiec jest to realizowalne. Ale po co, skoro mamy do tego sprzęt. Rozwój sprzętu i softu są ze sobą ściśle powiązane.

Azarien napisał(a):

Jestem w stanie sobie wyobrazić maszynę wirtualną na wzór Javy czy .NETa, której kod pośredni byłby zgodny z x86 a VM implementowałaby programowo kontrolę pamięci.
Ale wtedy to przecież będzie po prostu emulator.

Wirtualizacja. Rolą systemu jest między innymi wirtualziacja pamięci, czasu procesora, zasobów, etc. Inna sprawa, że obecnie wirtualizacja jest realizwoana sprzętowo gdzie tylko się da.

edytowany 7x, ostatnio: nalik, 2016-02-18 13:56
w jaki sposób chcesz wirtualizować pamięć nie mając żadnego wsparcia ze strony sprzętu, czyli np. przerwania w momencie odwołania do określonego obszaru? - Azarien 2016-02-18 14:47
To zalezy o czym mówimy. Jeżeli formie pośredniej kodu, którą kompiluje/inepretuje system to jest to realizowalne. Jeżeli o asm, to trzeba by przepisywac w locie kod ... cos jak binary rewriter, ale to jest z kolei spory narzut i jak zostało już powiedziane nie ze wszytkim musi sobie poradzić. - nalik 2016-02-18 14:53
jeśli mówimy o formie pośredniej to wszystko jest realizowalne. jeśli jednak program jest uruchomiony jako normalny proces, a system się tylko temu przygląda, to jest niezależnie od narzutu nierealizowalne, bo system nie dostanie okazji by się „temu przyjrzeć”. co innego kiedy to sprzęt albo emulator sprawdza każde odwołanie, i automatycznie wywołuje page fault czy coś podobnego, a system może odpowiednio zareagować. - Azarien 2016-02-18 15:07
No nie do końca. Kod nawet natywy możesz potraktować jako formę posrednią i go przepisać. Oczywiście założenie jest takie, że tylko userspace. Kodu kernela i bootloadera, ewentualnie firmware i sterowników nie przepisujesz. Ale to takie gdybanie. - nalik 2016-02-18 15:28

Pozostało 580 znaków

2016-02-18 13:55
0

Jeśli będziesz narzucał coraz to kolejne ograniczenia to w końcu będziesz mógł dojść do takiego stanu, że programowa realizacja ochrony pamięci stanie się łatwa. Skoro kontrolujesz ładowanie programów to możesz wymusić by np każde odwołanie do pamięci było poprzez wywołanie funkcji typu odczytajBajt, zapiszBajt, etc Brak wydajnej programowej ochrony pamięci sugeruje jednak, że nikt poważny nie planuje tak ścisłych ograniczeń.

Z architekturą x86 jest też kolejny problem jeśli chodzi o statyczną analizę - instrukcje mogą być różnej długości i zaczynać się w dowolnym miejscu. To drastycznie utrudnia deasemblację. Każdy skok może skoczyć w dowolne miejsce wewnątrz dozwolonej przestrzeni adresowej i przez to statyczny analizator może przeoczyć występujące instrukcje wymagające wysokich uprawnień (czyli chociażby dostępu do zabronionego obszaru pamięci).


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Pokaż pozostałe 4 komentarze
Owszem, potrzebuję pewnej pomocy sprzętu, choćby po to by wykonać jakikolwiek kod ;). Pewne rzeczy można obudować programowo, pewne nie, ale pod spodem msi być minium wsparcia ze strony sprzętu. Trend jest taki, że jak coś jest często używane to prawdopodobnie pojawi się wsparcie w sprzęcie, oile jest to opłacalne. - nalik 2016-02-18 15:14
@Wibowit: jeśli adres pod który dokonane jest odwołanie pamięci nie jest stały, tylko wynika z obliczeń, to nie da się tego przeanalizować inaczej niż przeprowadzając symulację działania programu. I mamy klasyczny problem stopu. - Azarien 2016-02-18 16:41
W tych specjalnych funkcjach byłoby sprawdzanie poprawności adresów w czasie wykonania, więc żadnej symulacji nie trzeba by było robić. Po to w ogóle wymyśliłem te funkcje. Oczywiście spowolniłoby to działanie programu. W ogólności pomysł polega na tym, że zamiast próbować transparentnie instrumentować kod w czasie ładowania czy też statycznie go analizować, można wymusić dostarczanie kodu z wbudowaną instrumentacją. - Wibowit 2016-02-18 17:02
musiałbyś i tak przeanalizować czy program nie odwołuje się do pamięci z pominięciem funkcji sprawdzających (zakazanie programowi wykonania instrukcji mov nie wchodzi w grę, bo wymaga obsługi ze strony sprzętu). tak samo musiałbyś opakować obsługę stosu, więc komplikuje się chociażby call. - Azarien 2016-02-18 17:30
Dlaczego zakazanie instrukcji mov odwołujących się do pamięci nie wchodzi w grę? Już napisałem, żeby zastąpić je wywołaniami funkcji odczytajBajt i zapiszBajt. Stos też można by za pomocą tych funkcji obsługiwać. Parametry do tych funkcji można przekazywać przez rejestry. Samo zakazanie to odmowa załadowania czy uruchomienia programu. - Wibowit 2016-02-18 18:25

Pozostało 580 znaków

2016-02-18 14:05
0

Nie tylko x86 istnieje. ARM na staly rozmair instrukcji. Poza tym statyczna analzia nie musi odbywać się na poziomie asemblera, może na reprezentacji posredniej.
Wchodząc na wyższy poziom abstrackji, system nie musi nawet pozwalać na wykonywanie natywnego kodu z poziomu userspaca.

Mam nadzieję, że autor tematu rozumie o czym mówimy. Najlepiej jakby zainwestował własny czas nad pogłębienie wiedzy o architekturze komputerów.

edytowany 2x, ostatnio: nalik, 2016-02-18 14:06

Pozostało 580 znaków

2016-02-18 18:09
Pod łzawym spawacze
0
kmph napisał(a):

...

"
Ochrona pamięci polega na ograniczeniu zakresu dostępnych adresów do pewnego podzbioru ograniczonego poprzez podanie najwyższego i najniższego dopuszczalnego adresu. W tym schemacie, najniższy adres jest przechowywany w rejestrze bazowym. Rejestr graniczny z kolei, określa wielkość dostępnego obszaru pamięci. Musi zostać zapewniona pamięć co najmniej dla przerwania sprzętowego oraz systemowych procedur obsługi przerwań. Pamięć poza zdefiniowanym zakresem jest chroniona."

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0