Qu'est-ce que l'astuce LD_PRELOAD?

342

Je suis tombé récemment sur une référence à ce sujet sur proggit et (pour l'instant), il n'est pas expliqué.

Je soupçonne que ce pourrait être ça, mais je ne sais pas avec certitude.

Hank Gay
la source
1
Ce n'est pas vraiment une réponse, donc je ne la posterai pas comme une seule mais ... Stephen Kell utilise LD_PRELOAD pour sa bibliothèque liballocs dans cette vidéo et si vous regardez les bits précédents, vous pourrez mieux comprendre comment / pourquoi. liballocs semble être utilisé pour que d'autres langages dynamiques puissent se parler. Cet exposé contient des informations internes approfondies. youtu.be/LwicN2u6Dro?t=24m10s
Elijah Lynn

Réponses:

415

Si vous définissez LD_PRELOADle chemin d'un objet partagé, ce fichier sera chargé avant toute autre bibliothèque (y compris le runtime C, libc.so). Donc, pour exécuter lsvotre malloc()implémentation spéciale , procédez comme suit:

$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls
JesperE
la source
12
Je ne savais pas que cela existait ... il semble que ce serait un vecteur majeur d'attaques de sécurité. Une idée de comment il est sécurisé?
rmeador
141
Il est sécurisé par le fait que le chargeur ignorera LD_PRELOAD si ruid! = Euid - Joshua
Joshua
18
@Joshua: qu'est-ce que ruid et euid?
heinrich5991
20
@ heinrich5991 Identifiants d'
gsingh2011
59
Une chose importante à garder à l'esprit: vous voulez généralement spécifier un chemin absolu vers LD_PRELOAD. La raison en est qu'il s'agit d'une variable d'environnement, elle est héritée par les processus enfants - qui peuvent avoir un répertoire de travail différent de celui du processus parent. Ainsi, tout chemin relatif ne parviendrait pas à localiser la bibliothèque à précharger.
Frerich Raabe
49

Vous pouvez remplacer les symboles dans les bibliothèques de stock en créant une bibliothèque avec les mêmes symboles et en spécifiant la bibliothèque dans LD_PRELOAD.

Certaines personnes l'utilisent pour spécifier des bibliothèques dans des emplacements non standard, mais LD_LIBRARY_PATHc'est mieux à cette fin.

Joshua
la source
17
"Certaines personnes l'utilisent pour spécifier des bibliothèques dans des emplacements non standard" ... Vraiment? Cela ressemble à "certaines personnes l'utilisent mal"!
Tom
6
LD_PRELOAD peut, en raison de l'ordre de chargement, intercepter les chemins codés en dur spécifiés par l'application.
Joshua
1
Serait-ce une mauvaise utilisation de précharger une version différente d'une bibliothèque - en supposant qu'elles soient compatibles?
z0r
2
Je l'ai vu utilisé pour charger un débogage ou une variante instrumentée, ou pour charger une bibliothèque qui fait quelque chose de radicalement différent de la bibliothèque de base comme pour émuler un autre système.
Joshua
1
Dans le cas où les bibliothèques ne sont pas compilées correctement (utilisé pour exécuter cela avec mysql tout le temps où il y avait un couplage lâche à un libmysql_client générique qui a écrasé le lien symbolique d'une ancienne version - selon la version de perl que vous avez utilisée, vous devez spécifier / forcez-le avec LD_PRELOAD .. astuce utile. Si je me souviens bien, valgrind utilise cette technique pour fournir une capacité de débogage aux binaires sans avoir besoin de recompiler .. c'est assez utile.
synthesizerpatel
37

Avec, LD_PRELOADvous pouvez donner la priorité aux bibliothèques.

Par exemple, vous pouvez écrire une bibliothèque qui implémente mallocet free. Et en les chargeant avec LD_PRELOADvotre mallocet freesera exécuté plutôt que les standards.

Ronny Brendel
la source
mais que faire si le programme utilise calloc? cela ne gâcherait-il pas tout?
Janus Troelsen
7
@JanusTroelsen si la bibliothèque que vous écrivez n'implémente pas une certaine partie, cette partie sera chargée à partir de la bibliothèque d'origine.
Woodrow Barlow, du
@JanusTroelsen, En d'autres termes, LD_PRELOAD vous permet de spécifier quelle implémentation d'un symbole spécifique sera utilisée. Si la bibliothèque préchargée n'exporte pas de symbole, il sera trouvé ailleurs.
sherrellbc
1
@JanusTroelsen: Il s'avère que mallocet gratuit sont spécifiquement conçus en glibc pour permettre cela et le stock callocparvient à appeler votre importé malloc. N'essayez pas cela avec d'autres fonctions. Ça ne marchera pas si bien.
Joshua
30

Comme beaucoup de gens l'ont mentionné, utiliser LD_PRELOADpour précharger la bibliothèque. BTW, vous pouvez VÉRIFIER si le paramètre est disponible par lddcommande.

Exemple: supposons que vous deviez précharger le vôtre libselinux.so.1.

> ldd /bin/ls
    ...
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3927b1d000)
    libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f3927914000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f392754f000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f3927311000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f392710c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f3927d65000)
    libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f3926f07000)

Ainsi, définissez votre environnement de préchargement:

  export LD_PRELOAD=/home/patric/libselinux.so.1

Vérifiez à nouveau votre bibliothèque:

>ldd /bin/ls
    ...
    libselinux.so.1 =>
    /home/patric/libselinux.so.1 (0x00007fb9245d8000)
    ...
Patric
la source
9

LD_PRELOADrépertorie les bibliothèques partagées avec des fonctions qui remplacent l'ensemble standard, tout comme le /etc/ld.so.preloadfait. Ceux-ci sont mis en œuvre par le chargeur /lib/ld-linux.so. Si vous souhaitez remplacer uniquement quelques fonctions sélectionnées, vous pouvez le faire en créant un fichier objet et un paramètre de substitution LD_PRELOAD; les fonctions de ce fichier objet remplaceront uniquement ces fonctions en laissant les autres telles qu'elles étaient.

Pour plus d'informations sur les bibliothèques partagées, visitez http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Rajesh
la source
3

Voici un article de blog détaillé sur le préchargement:

https://blog.cryptomilk.org/2014/07/21/what-is-preloading/

asn
la source
13
Merci d'avoir posté votre réponse! Veuillez noter que vous devez publier les parties essentielles de la réponse ici, sur ce site, ou votre publication risque d'être supprimée Voir la FAQ où elle mentionne des réponses qui sont `` à peine plus qu'un lien ''. Vous pouvez toujours inclure le lien si vous le souhaitez, mais uniquement comme «référence». La réponse doit être autonome sans avoir besoin du lien.
Taryn
3

il est facile d'exporter mylib.sovers env:

$ export LD_PRELOAD=/path/mylib.so
$ ./mybin

pour désactiver:

$ export LD_PRELOAD=
JulienGenoud
la source
7
ouunset LD_PRELOAD
Morten
2

lorsque LD_PRELOAD est utilisé, ce fichier sera chargé avant toute autre $export LD_PRELOAD=/path/libbibliothèque à précharger, même cela peut également être utilisé dans les programmes

Sumith Senarathne
la source
1

À l'aide de LD_PRELOADpath, vous pouvez forcer le chargeur d'application à charger l'objet partagé fourni, par rapport à celui fourni par défaut.

Les développeurs l'utilisent pour déboguer leurs applications en fournissant différentes versions des objets partagés.

Nous l'avons utilisé pour pirater certaines applications, en remplaçant les fonctions existantes à l'aide d'objets partagés préparés.

dnahc araknayirp
la source