Was bedeutet das Linux __user-Makro?

70

Ich hatte gehofft, jemand könnte die Nuancen des in der Linux-Kernel-Quelle verwendeten __user-Makros erklären.

Zunächst das Makro:

Nach einigem googeln habe ich nun gelesen, dass man mit diesem Makro einen Zeiger als zum Benutzeradressraum gehörend festlegen kann und dass er nicht dereferenziert werden sollte.

Ich vermisse vielleicht einige offensichtliche Fakten, aber könnte jemand bitte die Auswirkungen eines solchen Makros erklären? Was ist zum Beispiel ein gutes Beispiel dafür, wo dieses Makro von Nutzen sein würde? Nochmals, vergib mir, wenn mir etwas Offensichtliches fehlt.

Um dies in einen Zusammenhang zu bringen, bin ich beim Untersuchen eines USB-Codes (linux / usbdevice_fs.h) auf das Makro gestoßen. Ich suche nur nach einem allgemeinen Verständnis dieser Makros (oder ähnlicher), die im Kernel verwendet werden.

Danke fürs schauen!

Mr. Shickadance
quelle
3
Ein gutes Beispiel finden Sie in der Quelle do_execve (). Sehen Sie, wie argv in count () verwendet wird. Wenn Sie einfach dereferenzieren (* argv [0]) oder so, warnt sparse (1) davor. address_space sagt, dass nicht alle Zeiger gleich sind, unterschiedliche (Dereferenzierungs-) Regeln erfordern und nicht gemischt werden sollten.
Adobriyan
@adobriyan In welcher Header- oder Quelldatei kann ich diese Funktion finden? Ich möchte nicht während des Dateisystems grep, um es zu finden. Ein Weg wird ausreichen
Herdsman

Antworten:

48

Tools wie sparse können Kernel-Entwicklern mitteilen, dass sie möglicherweise einen nicht vertrauenswürdigen Zeiger (oder einen Zeiger, der in der aktuellen Zuordnung virtueller Adressen ungültig ist) nicht ordnungsgemäß verwenden.

Michael Burr
quelle
So __attribute__()kann jeden beliebigen Text als ein „Attribut“ verwenden? Es ist nicht auf einen festen Satz beschränkt, der für GCC selbst von Bedeutung ist?
Alex D
1
@AlexD Aus dem GCC Attribute Syntax Manual : An attribute specifier is of the form __attribute__ ((attribute-list)). An attribute list is a possibly empty comma-separated sequence of attributes, where each attribute is one of the following: 1. Empty. Empty attributes are ignored. **2. An attribute name (which may be an identifier such as unused, or a reserved word such as const).** (...). Es scheint, als könnte es sich um einen beliebigen Bezeichner handeln (unter Verwendung von Bezeichner-Namenskonventionen).
Enzo Ferber
37

Ich denke, __user markiert User-Space-Zeiger und weist den Entwickler / das System an, ihm nicht zu vertrauen. Wenn der Benutzer Ihnen einen "ungültigen" Zeiger gibt, versucht der Kernel, darauf zu verweisen (beachten Sie, dass der Kernel überall verweisen kann), und er kann seinen eigenen Speicherplatz beschädigen.

Zum Beispiel sollte in "read" (in you usbdevice_fs.h) ein (__user) Puffer bereitgestellt werden, in den das Ergebnis geschrieben werden kann. Sie müssen also copy_to_user verwenden, aber nicht memcopy, strcpy oder ähnliches.

Hinweis: Dies ist keine formale Definition / Beschreibung, sondern der einzige Teil, den ich kenne.

Azho KG
quelle
Ja, das ließ den copy_to_user Sinn machen
hukeping
11

Das __userMakro wird mit einigen anderen Makros wie __force/ __kerneletc in der Header-Datei compiler.h definiert. Sie sind für herkömmliche Compiler, einschließlich GCC / ICC usw., eigentlich nicht von Nutzen. Sie sind jedoch nützlich für statische Kernel-Analysetools wie Sparse (weitere Informationen hier: Sparse - Linux Kernel Newbies). Wenn Sie Makros wie __user/ __kernel/ __forceetc erwähnen , hat dies eine besondere Bedeutung für Sparse. In der Linux-Kernel-Mailingliste erklärt Linus Torvalds die Verwendung folgendermaßen:

Dies ist wichtig zu beachten: Für gcc sind die spärlichen Anmerkungen bedeutungslos. Sie können nach wie vor sinnvoll sein , nur das zu sagen , Programmierer , dass „hey, das Zeiger Sie bekommen , war kein normaler Zeiger“ in einer ziemlich lesbar Weise, aber am Ende, es sei denn , Sie spärlich verwenden, sie nicht wirklich tun nichts.

JEDOCH. Wenn Sie tun Verwendung Parse ist es eine ganz andere Sache. Für "spärlich" hat dieses "__iomem" viele Bedeutungen:

dh "iomem" bedeutet zwei getrennte Dinge: es bedeutet, dass sich spärlich beschweren sollte

Wenn der Zeiger jemals direkt dereferenziert wird (es ist ein "Noderef" -Zeiger) und sich im Gegensatz zum normalen Adressraum (0) im "Adressraum 2" befindet.

Das bedeutet, dass sich sparse beschwert, wenn ein solcher Zeiger jemals an eine Funktion übergeben wird, die einen regulären Zeiger möchte (da es sich nicht um einen normalen Zeiger handelt und Sie offensichtlich keine Dinge wie "strcmp ()" usw. darauf ausführen sollten). und sparse wird sich auch beschweren, wenn Sie versuchen, es auf einen anderen Zeiger in einem anderen Adressraum umzuwandeln.

Chintan Shah
quelle