Cosa impedisce a un programma di assemblaggio di arrestare in modo anomalo il sistema operativo? [chiuso]


18

Prima di tutto, sono un principiante, quindi se questa domanda sembra sciocca, ti preghiamo di sottolineare le ipotesi errate.

Da quello che ho capito, il lavoro di un sistema operativo è gestire l'hardware e il software che gira sul sistema operativo. Inoltre, da quanto ho capito, i programmi di assemblaggio consentono di controllare l'hardware quasi direttamente. In un programma di assemblaggio, è possibile leggere e scrivere i dati nei registri e leggere e scrivere i dati nella RAM.

Data questa libertà di pasticciare con registri e RAM, non sarebbe possibile per i programmi di assemblaggio influenzare il sistema operativo? Supponiamo che un sistema operativo stia utilizzando il registro A per memorizzare informazioni cruciali e supponiamo che io esegua un programma assemblato su quel sistema operativo. Se il programma scrive correttamente la posta indesiderata nel registro A, il sistema operativo sarà sicuramente interessato.

Domande:

  1. È possibile pasticciare con il registro A nel modo sopra descritto?

  2. In caso contrario, cosa impedisce ai programmi di assemblaggio di modificare i registri utilizzati dal sistema operativo?


13
programmatori intelligenti ...
Tony Stewart Sunnyskyguy EE75

Ci sono molte architetture di computer adesso ed erano in passato, così come molti sistemi operativi sono stati sviluppati. A quale architettura / sistema operativo ti riferisci esattamente? Su alcune (vecchie) architetture non era possibile interrompere il programma da quello che stava facendo dopo l'avvio, è corretto. Ma l'hardware / sistema operativo moderno ha incorporato strumenti hardware che forniscono solo la parte della memoria per il programma in modalità "normale" (non superutente) e non possono accedere alla memoria oltre questo limite. I registri sono gratuiti, poiché il sistema operativo non memorizza alcuna informazione utile nei registri, solo in memoria / su disco.
cyclone125

2
In un microprocessore il programma viene eseguito in "modalità utente", i sistemi operativi vengono eseguiti in "modalità di sistema". Se un programma in modalità utente eseguisse un'istruzione di arresto, ad esempio, la macchina non si fermerebbe. L'arresto sarebbe bloccato e il sistema operativo invocato. Per quanto riguarda la RAM, il sistema operativo creerebbe un ambiente per il programma in modalità utente in modo che, tramite l'hardware di gestione della memoria, ciò che il programma utente vede come indirizzo RAM X non sia in realtà l'indirizzo RAM X.
George White

1
@flux Ho aggiornato il mio commento. La risposta sarebbe: non esiste una risposta "generale" alla tua domanda, dato che esistono / erano architetture / sistemi operativi di computer diversi. Può essere in diversi modi.
cyclone125

2
... Molto tempo fa scrivevo nel codice macchina grezzo. Yee ah !!! :-)
Russell McMahon

Risposte:


33

Alla fine, tutti i programmi sono codice macchina, indipendentemente dal fatto che la lingua di origine fosse assembler o un linguaggio di alto livello.

La cosa importante è che ci sono meccanismi hardware che limitano ciò che un determinato processo può fare, tra cui i registri "pasticciare" che potrebbero influenzare altri programmi o il sistema operativo stesso.

Ciò è iniziato con una semplice distinzione tra le modalità di funzionamento "utente" e "supervisore" e da allora si è evoluta in un'architettura di sicurezza con più "anelli" di privilegi.


Ecco un esempio molto generico per renderlo un po 'più concreto:

  • In "modalità utente", un processo non può accedere alla memoria che non è stata assegnata al suo ID processo. La memoria assegnata ad altri processi e il sistema operativo stesso sono bloccati. Ciò include i valori dei registri utilizzati da quegli altri processi. Questo è imposto dall'hardware MMU.

  • Pertanto, in "modalità utente", un processo non può accedere ai registri di controllo MMU.

  • E ovviamente, in "modalità utente", un processo non può cambiare la modalità in "modalità supervisore" se non attraverso un meccanismo molto ben definito che comporta la chiamata di una funzione del sistema operativo.

Il sistema operativo ottiene il controllo se il processo tenta di violare una di queste regole. Una volta che ciò accade, il sistema operativo può semplicemente interrompere il processo offensivo, senza mai eseguire più le sue istruzioni.


2
Se ho capito bene, quello che stai dicendo è: alcuni processori hanno "modalità utente" e "modalità supervisore". Il sistema operativo funziona in "modalità supervisore" e mette il processore in "modalità utente" per eseguire il mio programma di assemblaggio immaginario. In "modalità utente", ci sono registri e indirizzi RAM a cui il programma di assemblaggio non può accedere a causa della progettazione deliberata dell'hardware.
Flusso

3
Fondamentalmente, questa risposta descrive le architetture moderne "simili a i386" con MMU e modalità protetta. Ma per essere veri ci sono molte architetture vecchie (i8080, MOS 6502 ecc.) E moderne (AVR, ARM Cortex-M ecc.) Che non hanno queste caratteristiche e se viene usato un qualche tipo di sistema operativo (ad es. Vecchio CP / M, FreeRTOS moderno, ChibiOS ecc.) Nulla può fermare il programma da ciò che sta facendo.
cyclone125

2
@Flux Le architetture i386 (e successive) forniscono dettagli per l'apprendimento. L'architettura x86 non ha solo indirizzi di memoria che possono essere protetti, ma anche indirizzi di I / O. (Esistono diverse istruzioni per l'accesso alla memoria rispetto all'accesso I / O.) Nell'i386 + sono presenti tre indirizzi di memoria. L'indirizzo segmentato / basato su selettore utilizza un registro di selezione che fa riferimento a una voce di tabella (GDT o LDT) per mappare la coppia in un singolo indirizzo lineare a 32 bit. Le tabelle di paging traducono quindi l'indirizzo lineare a 32 bit in un indirizzo fisico a 36 bit (P-II.) La protezione esiste in entrambe le fasi della traduzione.
Jon

4
@flux il tuo riepilogo è corretto. Un programma in un sistema di memoria protetto con un sistema operativo multitasking adatto non dovrebbe essere in grado di arrestare il sistema con alcun flusso di istruzioni. Anche quelli non validi - quelli finiscono in un gestore speciale.
pjc50,

Anche se ci sono più anelli (almeno in x86), è molto, molto raro che vengano utilizzati più di due.
foresta

10

Molti sistemi operativi multitasking utilizzano una struttura di dati chiamata Process Control Block (PCB) per risolvere il problema di sovrascrittura del registro. Quando si esegue il codice, il sistema operativo crea un nuovo processo per tenerne traccia. Il PCB contiene informazioni sul processo e lo spazio allocato per contenere i contenuti del registro. Supponiamo che il processo A sia attualmente in esecuzione sul processore e che il tuo codice sia in corso B. Cosa succede quando esegui il codice è qualcosa di simile a questo:

  1. I dati di stato del processo A (contenuto del registro, contatore dei programmi, ecc.) Vengono copiati nel suo PCB.

  2. I dati di stato del processo B vengono copiati dal suo PCB nei registri della CPU

  3. Il processo B viene eseguito sul processore fino a quando non termina o viene annullato

  4. I dati sullo stato del processo B vengono copiati nuovamente nel suo PCB

  5. I dati di stato del processo A vengono copiati nuovamente nella CPU e continua a funzionare

Se il sistema operativo è in esecuzione come processo A, puoi vedere come salvare i suoi registri prima dell'esecuzione del programma e copiarli nuovamente nella CPU una volta terminato il programma impedisce ai programmi utente di interferire con ciò che accade in altri processi.

Per evitare che i processi dell'utente scrivano sui dati del sistema operativo in memoria, la maggior parte delle piattaforme utilizza la segmentazione della memoria. Fondamentalmente, usando la memoria virtuale, lo spazio degli indirizzi che un processo vede può essere mappato su qualsiasi intervallo arbitrario di indirizzi fisici. Finché gli spazi di memoria fisica dei processi non si sovrappongono, è impossibile per un processo sovrascrivere i dati di un altro.

Naturalmente, diversi sistemi operativi fanno le cose in modo diverso, quindi questo non si applica in tutti i casi. Inoltre, sulla maggior parte delle piattaforme, i processi del sistema operativo vengono eseguiti in una modalità diversa rispetto ai processi dell'utente e vi sono alcune complessità.


4

Dipende dalla piattaforma di cui stai parlando.

  • Su un processore più semplice, il processore esegue semplicemente le istruzioni che il programma gli dice di eseguire.

  • Su un processore più sofisticato, ci sono (almeno) due modalità. In una modalità, il processore fa qualunque cosa il programma gli dica di fare. Nell'altra modalità, il processore stesso rifiuta di eseguire determinate istruzioni.

Cosa impedisce a un programma di arrestare l'intero sistema? Con il primo tipo di processore, la risposta è "niente". Con un processore di base, un singolo programma canaglia può effettivamente arrestare l'intero sistema. Tutti i primi computer domestici a 8 bit e molti di quelli a 16 bit rientrano in questa categoria.

Su un PC moderno, il processore ha hardware di "protezione". Fondamentalmente il sistema operativo viene eseguito in una modalità speciale che consente di fare qualsiasi cosa, mentre i normali programmi vengono eseguiti in una modalità in cui il processore consentirà solo determinate azioni (in base alle impostazioni che il sistema operativo ha configurato sul processore). Cose come l'accesso solo a determinati registri o l'accesso solo a determinati intervalli di memoria.

Ovviamente, consentire a un singolo programma canaglia di arrestare l'intero sistema è un problema. (Esistono anche gravi implicazioni per la sicurezza nel consentire a un programma non autorizzato di accedere a tutti i dati che desidera.) Per evitare ciò, sono necessarie due cose:

  1. Un processore che in realtà ha un hardware di protezione (cioè può essere configurato per rifiutare di eseguire determinate istruzioni).

  2. Un sistema operativo che utilizza effettivamente queste funzionalità per proteggersi. (Non va bene avere un chip con circuiti di protezione se il sistema operativo non lo usa mai!)

Quasi tutti i moderni sistemi operativi desktop che puoi nominare (Windows, Linux, Mac OS, BSD ...) un sistema operativo in modalità protetta in esecuzione su un processore con hardware di protezione. Se stai eseguendo uno sviluppo integrato su un microcontrollore a 8 bit, probabilmente non ha alcun hardware di protezione. (O qualsiasi sistema operativo, del resto ...)


1

D. Cosa impedisce a un programma di assemblaggio di arrestare in modo anomalo il sistema operativo?

A. Niente.

Tuttavia, molti programmatori molto intelligenti hanno provato molto negli anni a renderlo sempre più difficile. Sfortunatamente, per ogni programmatore intelligente, ce ne sono molti, molti altri che tra loro sono più creativi, più ambiziosi e talvolta solo più fortunati di quelli intelligenti. Ogni volta che un abile programmatore dice che nessuno dovrebbe, vorrebbe o potrebbe fare qualcosa, qualcuno là fuori troverà un modo per farlo. Microsoft Windows (come esempio) è in circolazione da quasi 35 anni e abbiamo ancora BSoD (Blue Screens of Death), che sono solo istruzioni che hanno causato l'arresto anomalo del sistema operativo.

Cominciamo con un po 'di terminologia. Tutto ciò che gira su un computer lo fa nel codice macchina. Il bit che legge le sequenze di tasti o il movimento del puntatore del mouse, il bit che cambia il colore di un pixel sul display o legge un byte da un file e il bit che calcola se il tuo proiettile ha colpito il cattivo o il bit che decide se la tua richiesta di carta di credito sarà accettata, saranno tutti eseguiti come una sequenza di istruzioni del codice macchina. Alcuni lavori sono così comuni e vengono eseguiti così spesso che ha senso assemblare le istruzioni necessarie per farli e far sì che tutti usino quell'assemblea. Il gruppo di questi lavori che consente o aiuta gli altri a utilizzare il computer tende ad essere chiamato il sistema operativo, ma non c'è nulla di intrinsecamente diverso tra loro e qualsiasi altro programma. Sono solo sequenze di istruzioni sul codice macchina.

Ciò che rende i sistemi operativi più complicati (e quindi soggetti a crash) è che devono tenere conto di cose a cui normalmente non si deve pensare. Prendi il lavoro più semplice come esempio. Voglio scrivere un messaggio alla fine di un file. In una lingua di alto livello dovresti scrivere qualcosa del tipo:

  with open("myFile.txt", "w+") as f:
      # do some really clever things
      f.write("Goodbye cruel world!")

Ignoriamo tutti i dettagli su come si accede e si modificano gli stati fisici o su come vengono interpretati come bit e byte o su come questi byte vengono trasferiti da e verso la memoria e la CPU e si fida che tutto ciò che viene gestito dai programmi forniti dal sistema operativo dietro le quinte. Pensiamo solo a come aggiungere alla fine di un file. 1) Scopri dove si trova la fine del file, 2) scrivi qualcosa in quella posizione. Che cosa potrebbe andare storto? In realtà, abbastanza. Pensa a cos'altro succede sul computer mentre fai cose intelligenti. Se qualcos'altro viene fatto da qualcun altro (incluso il sistema operativo stesso) cambia il file su cui stai lavorando in qualche modo, allora questo lavoro davvero semplice diventa improvvisamente molto più complicato. Il file è più lungo, il file è più corto. Il file non è più lì. Il disco è pieno,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.