Skip to content
Snippets Groups Projects
Commit d02785e6 authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Notizen, Beispiel-Programm und Termine 13.5.2024

parent 08208321
Branches
No related tags found
No related merge requests found
Von "Hello, world!\n" bis zum Kernel, 15.05.2023, 16:20:31
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- printf ("Hello, world!\n"); wird zu puts ("Hello, world!"); optimiert.
- Quelltext von puts(): apt-get source glibc
- "virtuelle Methoden" in C
- spezielle Compiler-Befehle: __attribute__((..)), weak alias, Pipelining-Optimierung
- plattformunabhängige Programmierung: Präprozessor-"Hook"s
- Kernel-nächste Funktion: write()
- Systemaufruf: _IO_SYSWRITE() --> syscall: spezieller Assembler-Befehl
Hardware-Unterstützung für den Übergang Kernel<-->Userspace
Im Kernel, 06.05.2024, 18:24:25
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fs/read_write.c:
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, size_t, count)
--> ruft ksys_write() auf
--> ruft vfs_write() auf
fs/open.c:
Öffnen der Datei: do_dentry_open()
- bekommt einen inode übergeben,
- ordnet einem Datei-struct den inode zu,
- übergibt die fops (Callbacks) aus dem inode an das Datei-struct.
vfs_write(): Aufruf des Callbacks aus dem Kernel-Modul
if (file->f_op->write)
ret = file->f_op->write(file, buf, count, pos);
Die Funktion inode_permission() aus fs/namei.c prüft, ob geeignete
Zugriffsrechte zum Lesen, Schreiben oder Ausführen gegeben sind.
Vom Syscall-Befehl bis zum Aufruf vom ksys_write(), 13.05.2024, 17:39:34
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/x86/entry/syscall_64.c:
mehrfach: #include <asm/syscalls_64.h>
davor jeweils: #define __SYSCALL(nr, sym) [...]
--> Liste von Externdeklarationen
Aufruf-Funktion x64_sys_call() für Syscall-Funktionen mit großem switch()
historisch: Tabelle mit Zeigern auf Syscall-Funktionen
scripts/syscalltbl.sh:
Skript, das asm/syscalls_64.h aus arch/x86/entry/syscalls/syscall_64.tbl erstellt,
aufgerufen von arch/x86/entry/syscalls/Makefile
(Dieses Makefile macht noch mehr, z.B. Verwaltung der ABIs.)
arch/x86/entry/common.c:
do_syscall_64(struct pt_regs *regs, int nr)
ruft do_syscall_x64(regs, nr) auf,
ruft x64_sys_call() auf.
arch/x86/entry/entry_64.S: (.S = Assembler mit Präprozessor)
Definition einer Funktion entry_SYSCALL_64
Registerinhalte in einem struct abspeichern
Dieser struct ist eine lokale Variable - auf dem Stack.
Jeder push-Befehl reserviert Speicher auf dem Stack
und speichert dort den Inhalt des Registers.
movq %rsp, %rdi
Zeiger auf das Struct ins rdi-Register packen
--> Parameter für C-Funktionsaufruf
movslq %eax, %rsi
"move signed from long to quadword"
32-Bit-Zahl nach 64-Bit-Zahl kopieren, mit Vorzeichen
--> Parameter für C-Funktionsaufruf: Nr. des Syscalls
Finale: Wer ruft entry_SYSCALL_64 auf?
--> Nach der Pause.
_____________________
< Pause bis 18:28 Uhr >
---------------------
\
\
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
Wer ruft entry_SYSCALL_64 auf?
grep -r entry_SYSCALL_64 *
--> arch/x86/kernel/cpu/common.c: wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
Die Funktion void syscall_init(void) enthält:
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
Hier hinterlegen wir die Adresse von entry_SYSCALL_64 (als 64-Bit-Zahl)
in einem internen Prozessorregister, das genau für diesen Aufruf (syscall-Befehl)
zuständig ist.
wrmsrl: In ein solches Register schreiben
MSR_STAR: Nummer des Registers, das dafür zuständig ist, sich die Segmente zu merken
(__KERNEL_CS = Code-Segment des Kernels)
MSR_LSTAR: Nummer des Registers, das dafür zuständig ist, sich das Offset zu merken
--> Die Adresse besteht aus 2 Teilen:
- Segment - Speicherschutzmechanismus: Jedes Programm sieht seinen eigenen Speicher.
- Offset - "normale" Speicheradresse
--> Damit sind wir am Ziel. :-)
Was ist ein Trampolin? 13.05.2024, 18:44:25
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Wikipedia (Begriffsklärung): ein Stück Code, das eine andere Funktion aufruft
void bla (void) // sehr einfaches Trampolin ("wrapper")
{
blubb (42); // Die Funktion, die ich aufrufen will, erwartet einen Parameter
} // ("andere Signatur")
int main (void)
{
do_something_with_callback (bla); // Bibliothek erwartet void-Funktion
} // Beispiel: Sortier-Funktion erwartet
// Vergleichs-Funktion als Callback
Manche Sprachen (z.B. Pascal) erlauben geschachtelte Funktionen, z.B.:
int main (void)
{
int answer = 42;
void bla (void) // sehr einfaches Trampolin ("wrapper")
{
blubb (answer); // Die Funktion, die ich aufrufen will, erwartet einen Parameter
} // ("andere Signatur")
do_something_with_callback (bla); // Bibliothek erwartet void-Funktion
}
Problem: bla() wird von "außen" (z.B. Bibliothek) aufgerufen.
Die Variable answer ist dort aber nicht bekannt.
--> Eine Wrapper-Funktion ist ungeeignet, da der beim Aufruf aktuelle Wert
von "answer" nicht zur Compile-Zeit, sondern erst zur Laufzeit bekannt ist.
Lösung (Trampolin): Ausführung von Code auf dem Stack
Der Aufrufer (hier: main()) erzeugt spontan eine neue Funktion.
Die braucht Speicherplatz. --> Auf dem Stack reservieren.
Neues Problem: Ausführbarer Code auf dem Stack ist ein Sicherheitsrisiko.
--> Wird heutzutage mit Hardware-Unterstützung verhindert.
Neue Lösung: sehr aufwendig
"Mit Objektorientierung wird alles gut."
Wenn die Bibliothek mitspielt, kann man ihr ein Objekt übergeben --> Problem gelöst
--> "command pattern"
#include <unistd.h>
int main (void)
{
write (1, "Hello, world!\n", 14);
return 0;
}
Mo 22.07. 11:00 CVH: Präsentationen bs/nit
Wer sich jetzt zur Prüfung anmeldet,
muß bis zum 20.9.2024 sowohl eine Präsentation gehalten
als auch die Endfassung der Dokumentation abgegeben haben.
Wer das nicht schafft, sollte sich rechtzeitig (also vermutlich
bis 1 Woche vor dem 20.9.2024) wieder von der Prüfung abmelden.
Ansonsten gilt die Prüfung als "nicht bestanden".
Wir werden dafür sorgen, daß man sich in jedem Semester
für die Prüfung wieder anmelden kann (anstatt, wie bisher,
nur in jedem Sommersemester).
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment