Fragen? Antworten! Siehe auch: Alternativlos
getrandom ist ein neuer Syscall, der im Wesentlichen dasselbe macht wie open("dev/urandom") + read + close.
Wieso braucht man dafür einen neuen Syscall? Für viele Krypto-Verfahren braucht man ordentlichen Zufall, und ein Angreifer kann möglicherweise dafür sorgen, dass auf dem System die Ressourcen alle sind (Dateideskriptoren sind eine endliche Ressource!). Man will nicht, dass so Krypto-Bibliotheken angegriffen werden können, also macht man einen Syscall, der auch funktioniert, wenn man z.B. in einem chroot ohne /dev läuft oder wenn ein Angreifer die File Descriptor Table gefüllt hat.
Die VDSO ist eine Shared Library, die der Kernel jedem Prozess ungefragt in den Speicher mappt, und da sind ein paar Syscalls im User Space implementiert. Bislang ging es dabei nur um Syscalls, bei denen man Zeit sparen wollte, also sowas wie gettimeofday (der Kernel mappt dann auch eine Page mit der aktuellen Uhrzeit read-only in den Prozess) und so.
Wieso muss da getrandom hin, wenn es das doch als unabhängigen Syscall schon gibt? War umstritten. Ein Argument könnte sein, dass /dev/urandom eh ein Zufallszahlengenerator ist, und den könnte man auch einfach komplett im User Space machen. Nur der Seed dafür ist dann wichtig. Da gibt es auch schon einen Kernel-Mechanismus für, um ein paar Byte Zufall in den User Space zu schieben.
Ich implementiere das jetzt also und lasse strace auf den Prozess laufen, und was sehen meine entzündeten Augen? Immer noch Aufrufe vom getrandom-Syscall. Der Code in der VDSO ruft also den Kernel auf. Wut?
Na DAS war ja mal antiklimaktisch.
Hmm, vielleicht ruft er das nur einmal am Anfang auf und danach hat er geseedet? Nope. Wenn ich zehnmal getrandom in der VDSO aufrufe, sehe ich 10 Aufrufe des Syscalls.
m(
Update: Oh. Pilotenfehler, stellt sich raus. In allen anderen VDSO-Funktionen (sind nur 5) ruft man einfach eine Funktion auf, und die hat denselben Funktionsprototypen wie der Syscall. Bei getrandom ist das anders. Die Funktion in der DSO heißt zwar getrandom aber will nicht 3 sondern 5 Argumente haben, und die muss man dann auch speziell initialisiert haben. m(