Dieser Artikel ist der Artikel zum 10. Tag des Linux-Adventskalenders 2016.
Uprobes, die von ftrace, eBPF / bcc, Systemtap usw. verwendet werden können. Ich kann kein Beispiel (Kernelmodul) finden, das von Uprobes allein wie kprobes ausgeführt werden kann. Da Weihnachten kurz vor der Tür steht, werde ich eine Auswahl von Urobes vorstellen, die jeder leicht verwenden kann (ich sage nicht, dass Sie sich frei fühlen sollten, ein Kernelmodul zu erstellen). Die ausführliche Erklärung zur Implementierung wird weggelassen, aber die entsprechende Anweisung wird in 0xcc umgeschrieben und übersprungen.
Verbreitung: Ubuntu 16.04 Kernel zur Untersuchung und Verifizierung: 4.4.0-45-generic
uprobes ist ein Linux-Kernelmechanismus, der Benutzerprozesse aus dem Kernelraum abfragt. Uprobes werden normalerweise über konfigurierbare Benutzeroberflächen wie ftrace verwendet Ein Kernelmodul, das Uprobes verwendet, wird aus einem eindeutigen Skript wie Systemtap generiert und darin verwendet.
Da Weihnachten kurz vor dieser Zeit steht, werde ich ein Kernelmodul für den direkten Kontakt mit Urobes schreiben.
Schauen wir uns zunächst die kernelseitige API für die Verwendung des Uprobes-Mechanismus an.
/*
* uprobe_register - register a probe
* @inode: the file in which the probe has to be placed.
* @offset: offset from the start of the file.
* @uc: information on howto handle the probe..
*
* Apart from the access refcount, uprobe_register() takes a creation
* refcount (thro alloc_uprobe) if and only if this @uprobe is getting
* inserted into the rbtree (i.e first consumer for a @inode:@offset
* tuple). Creation refcount stops uprobe_unregister from freeing the
* @uprobe even before the register operation is complete. Creation
* refcount is released when the last @uc for the @uprobe
* unregisters.
*
* Return errno if it cannot successully install probes
* else return 0 (success)
*/
int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
Es ist ersichtlich, dass die Informationen, die eingestellt werden müssen, ungefähr der Inode der Sondenzieldatei, der Sondenzielversatz der Sondenzieldatei und der Handler sind, der ausgeführt werden soll, wenn die Sonde ausgeführt wird.
Schauen wir uns als nächstes die uprobe_consumer-Struktur an, die die Funktion zum Zeitpunkt der Prüfung festlegt.
struct uprobe_consumer {
int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
int (*ret_handler)(struct uprobe_consumer *self,
unsigned long func,
struct pt_regs *regs);
bool (*filter)(struct uprobe_consumer *self,
enum uprobe_filter_ctx ctx,
struct mm_struct *mm);
struct uprobe_consumer *next;
};
Aus der Definition der uprobe_consumer-Struktur ist ersichtlich, dass die pt_regs-Struktur zum Zeitpunkt der Prüfung über den Handler übergeben wird.
Führen Sie dieses Mal die entsprechende C-Beispiel-App aus, um den Funktionsaufruf debuggee_func zu testen.
#include <stdio.h>
int debuggee_func(int a, int b)
{
int result;
result = a + b;
return result;
}
void main()
{
int result;
result = debuggee_func(1, 2);
printf("result: %d", result);
}
Als nächstes wird das Beispiel-Kernelmodul, das Uprobes verwendet, unten platziert. Bitte überprüfen Sie den folgenden Beispielcode für die Verarbeitung, z. B. die Konvertierung vom Dateipfad zum Inode.
https://github.com/kentaost/uprobes_sample/blob/master/uprobes_sample.c
Das folgende DEBUGGEE_FILE in diesem Beispiel-Kernelmodul für das Uprobes repräsentiert die zu debuggende Datei, und DEBUGGEE_FILE_OFFSET repräsentiert den Offset. Der Versatz wird aus der Adresse der Zielfunktion und der Startadresse des Textsegments für die Zielbinärdatei unter Verwendung von readelf oder dergleichen erhalten. In meiner Umgebung war die Funktion debuggee_func 0x526 (0x400526 --0x400000), daher habe ich diesen Wert eingebettet und erstellt.
#define DEBUGGEE_FILE "/home/kentaost/debuggee_app"
#define DEBUGGEE_FILE_OFFSET (0x526)
Nachdem Sie dieses Beispielkernelmodul modifiziert haben, führen Sie die Beispiel-App aus und sehen Sie sich dmesg an. Sie werden Hinweise auf die Prüfung sehen, wie unten gezeigt.
…
[xxxx.xxxxxx] handler is executed
[xxxx.xxxxxx] ret_handler is executed
Wie Sie der Funktion uprobe_register entnehmen können, handelt es sich nicht um einen Mechanismus zum Festlegen der Sonde für jeden Benutzerprozess. Beispielsweise ist ersichtlich, dass die Sonde auch dann geprüft wird, wenn dasselbe Programm mehrmals gestartet wird.
Abgesehen davon können Sie, wenn Sie Ihr Bestes geben, einen User Space Stack Trace wie den folgenden Systemtipp vorbereiten. (Systemtap bereitet Tapset so vor, dass Sie nicht hart arbeiten müssen. Verwenden Sie daher normalerweise Systemtap und Tapset.)
http://qiita.com/kentaost/items/a2e882d2978fba9e17d3
Wenn Sie diesmal auch die interne Implementierung von Uprobes verstehen, können Sie das Verhalten beim Prüfen eines Benutzerprozesses mit Systemtap usw. (bei Verwendung von Uprobes) verstehen. Es gibt keine Verwendung für die direkte Verwendung, aber Sie sollten ftrace und Systemtap gehorsam verwenden, außer zu Weihnachten.