Was sind die Auswirkungen des Linux-Makros __user?

Lesezeit: 4 Minuten

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

Erstmal das Makro:

# define __user         __attribute__((noderef, address_space(1)))

Nun, nach einigem Googeln habe ich gelesen, dass dieses Makro es einem ermöglicht, einen Zeiger als zum Benutzeradressraum gehörig zu kennzeichnen, und dass er nicht dereferenziert werden sollte.

Mir fehlen 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 nützlich wäre? Nochmals, vergib mir, wenn ich etwas Offensichtliches übersehe.

Um dies in einen Zusammenhang zu bringen, bin ich beim Untersuchen von USB-Code (linux/usbdevice_fs.h) auf das Makro gestoßen. Ich suche nur nach einem allgemeinen Verständnis für die Verwendung dieser Makros (oder anderer ähnlicher) innerhalb des Kernels.

Danke fürs Suchen!

  • Ein gutes Beispiel finden Sie in der Quelle do_execve(). Sehen Sie, wie argv in count() verwendet wird. Wenn Sie einfach dereferenzieren würden (*argv[0]) oder so etwas, sparse(1) wird davor warnen. address_space besagt, dass nicht alle Zeiger gleich sind, unterschiedliche (Dereferenzierungs-)Regeln erfordern und nicht gemischt werden sollten.

    – Adobebryan

    24. Dezember 2010 um 17:12 Uhr


  • @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 reicht

    – Hirte

    9. Mai 2020 um 21:04 Uhr

Es ermöglicht Tools wie spärlich um Kernel-Entwicklern mitzuteilen, dass sie möglicherweise einen nicht vertrauenswürdigen Zeiger (oder einen Zeiger, der in der aktuellen virtuellen Adresszuordnung möglicherweise ungültig ist) falsch verwenden.

  • So __attribute__() kann jeder beliebige Text als “Attribut” verwendet werden? Es ist nicht auf einen festen Satz beschränkt, der für GCC selbst von Bedeutung ist?

    – Alex D

    23. März 2015 um 20:10 Uhr

  • @AlexD Von der Syntaxhandbuch für GCC-Attribute: 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 der Namenskonventionen für Bezeichner).

    – Enzo Ferber

    30. Dezember 2015 um 18:45 Uhr

Ich denke, __user markiert User-Space-Zeiger und sagt dem Entwickler/System, 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 es kann seinen eigenen Bereich beschädigen.

Zum Beispiel sollte in “read” (in dir 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, der mir bekannt ist.

  • ja, das macht copy_to_user Sinn

    – hukeping

    9. Juli 2014 um 4:12 Uhr

Benutzeravatar von Chintan Shah
Chintan Schah

Das __user Makro wird mit einigen anderen Makros wie definiert __force/__kernel usw. in der header-Datei compiler.h. Sie sind für traditionelle Compiler, einschließlich GCC/ICC usw., eigentlich nicht von Nutzen. Aber sie sind nützlich für Tools zur statischen Kernelanalyse wie Sparse (weitere Informationen hier: Sparse – Linux Kernel Newbies). Wenn Sie die Makros wie erwähnen __user/__kernel/__force usw. behält es eine besondere Bedeutung für spärlich. In der Linux-Kernel-Mailingliste erklärt Linus Torvalds die Verwendung folgendermaßen:

Es ist wichtig, sich daran zu erinnern: Für gcc sind die spärlichen Anmerkungen bedeutungslos. Sie können immer noch nützlich sein, nur um das zu sagen Programmierer dass “hey, dieser Zeiger, den Sie bekommen haben, kein normaler Zeiger war” auf eine ziemlich lesbare Weise, aber am Ende tun sie es nicht, es sei denn, Sie verwenden Sparse tun irgendetwas.

JEDOCH. Wenn du tun parse verwenden, das ist eine ganz andere Sache. Für “spärlich” hat “__iomem” viel Bedeutung:

# define __iomem __attribute__((noderef, address_space(2)))

dh “iomem” bedeutet zwei verschiedene Dinge: es bedeutet, dass spärlich sich beschweren sollte

wenn der Zeiger jemals direkt dereferenziert wird (es ist ein “noderef”-Zeiger) und sich im “Adressraum 2” im Gegensatz zum normalen Adressraum (0) befindet.

Nun, das bedeutet das spärlich wird sich beschweren, wenn ein solcher Zeiger jemals an eine Funktion übergeben wird, die einen regulären Zeiger haben möchte (weil dies der Fall ist nicht ein normaler Zeiger, und Sie sollten offensichtlich keine Dinge wie “strcmp()” usw. darauf tun), und Sparse wird sich auch beschweren, wenn Sie versuchen, ihn auf einen anderen Zeiger in einem anderen Adressraum umzuwandeln.

1417720cookie-checkWas sind die Auswirkungen des Linux-Makros __user?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy