9
votes

Ld_profoad affecte le nouvel enfant même après la nonsetv ("ld_preload")

Mon code est comme suit: Preload.c, avec le contenu suivant:

LD_DEBUG=all LD_DEBUG_OUTPUT=/tmp/ld-debug LD_PRELOAD=./mylib.so bash


12 commentaires

De quelle langue parle-t-on?


Nous parlons du langage C


@ user395074, vous auriez peut-être peut-être réglé vos balises pour refléter la langue (cliquez sur le lien "Modifier"). De plus, la balise [précharge] ne semble pas être reflétée par la composante du système d'exploitation que nous discutons.


Veuillez partager votre code et pouvez-vous remplacer la commande avec un script simple contenant #! / bin / sh et exporter ? Vérifiez-vous la valeur de retour de nonsetenv () ?


Que signifie "rester avec l'effet de ld_preload"? Vous ne venez-vous pas de compiler contre MyLib.so, il sera donc chargé de toute façon? Utilisez la strace pour voir ce qui se passe dans la phase de liaison.


Veuillez mettre le code dans la question plutôt que dans les commentaires. Et s'il vous plaît ne pas démarrer ls mais un script sortie de l'environnement afin que vous puissiez réellement voir quel est l'environnement.


Vous pouvez modifier et revenir de vos propres questions, @avner, même en tant que nouveau venu complet sur le site. J'ai transcrit votre commentaire pour vous; Je recommande de supprimer votre commentaire ci-dessus, puis de me faire savoir quand vous l'avez fait pour que je puisse supprimer ce commentaire.


Exécutez-vous fichier ? Pas ./ fichier ? ne pas être un nitpick mais je ne connais pas votre $ chemin


J'ai utilisé ./file ou ./prog (j'ai édité la question de réfléchir à cela)


Mec tu fais des choses étranges! Et vous ne pouvez pas la ranger sans prudence ni précharger strace aussi. Si j'exécute strace -f -e ld_preload = mylib.so / bin / echo 2> & 1 | Moins Je vois myLib.so Ouver une seule fois, et une fois seulement une fois que je Voir "Défaut LD_PRÉLOAD" étant imprimé. (Ajouter fflush (stdout) pour voir le printf comme vous le faites, il peut être tamponné sinon!)


OK, reproduits avec strace -f -s 10240 -v -e ld_preload = mylib.so / bin / bash 2> & 1 | Moins , où vous voyez clairement la LD_PRÉLOAD dans la seconde . Vous problème est que le Bash Binary fait apparemment son propre chose spéciale avec l'environnement, donc dans Bash Vous ne pouvez pas compter sur nonsetenv () . N'oubliez pas que vous êtes en train de jouer dans le Bash binaire! (Par exemple, UNETENV () dépend d'une autre variable que extern Char ** Environ - Dump Environ après votre nonsetenv et vous verrez ld_preload debout là-bas, tout le même .. .)


Concernant mon dernier commentaire, voir ma réponse: Pour être précis, ce n'est pas nonsetenv () ne pas agir sur Environ , mais nonsetenv ne pas être le "Real" nonsetenv dans le binaire Barin et ne joue donc pas sur environnement .


3 Réponses :


3
votes

(la réponse est une spéculation pure et peut être est incorrecte).

peut-être, lorsque vous fourrez votre processus, le contexte des bibliothèques chargées persiste. Donc, mylib.so a été chargé lorsque vous avez appelé le programme principal via ld_preload . Lorsque vous désintérez la variable et la fourchette, il n'a plus été chargé; Cependant, il a déjà été chargé par le processus parent. Peut-être que vous devriez le décharger explicitement après le fourchette.

Vous pouvez également essayer de "modifier" symboles dans myLib.so . Pour ce faire, rouvez-le via dlopen Avec des drapeaux qui le placent à la fin de la file d'attente de résolution de symboles: xxx


8 commentaires

Merci pour le commentaire de Pavel. Cela semble raisonnable; Cependant, dans mon cas, cette solution de contournement est impossible. Je ne peux rien changer après la fourche, car j'utilise Popen, qui fait la fourchette / EXED pour moi. (Néanmoins, Fork & Exec est une option de replie si je ne peux pas le faire avec popen). Le processus parent doit rester avec l'environnement LD_PRÉLOAD (c'est un processus client avec plusieurs threads).


Dites-vous qu'après EXEC Les bibliothèques chargées persistent? Je vois dans une ronde que même libc est re-ouverte après EXEC , impossible d'imaginer une autre bibliothèque prévaudra.


@mvds, être rouvert et être déchargé / chargé sont des choses différentes. Vous pouvez rouvrir une bibliothèque déjà chargée.


Je me demandais simplement comment une bibliothèque chargée survivrait (directrice de citation (2)): "Expétuelle () ne revient pas sur le succès, et le texte, les données, les BSS et la pile du processus d'appel sont écrasés par celui du programme chargé. "


Bellow est exemple capturé à l'aide de "ld_debug = symboles". Il montre clairement que les symboles sont recherchés dans mylib.so avant que libc et tout autre lieu: 4779: symbole = __ cxa_finalize; Recherche dans File = LS [0] 4779: Symbole = __ Cxa_Finalize; Recherche dans File = / USR / LIB64 / LIBMYLIB.SO [0] 4779: Symbole = __ CXA_Finalize; Recherche dans File = / Lib64 / Lib64 / Librt.so.1 [0] 4779: Symbole = __ cxa_finalize; Recherche dans le fichier = / lib64 / libaCl.so.1 [0] 4779: symbole = __ cxa_finalize; recherche dans le fichier = / lib64 / libelinux.so.1 [0] 4779: symbole = __ cxa_finalize; Recherche dans le fichier = / lib64 / libc.so.6 [0]


@mvds, merci beaucoup pour votre réponse éducative. Cela m'a perplexe et m'a beaucoup aidé à concentrer ma question. J'ai réussi à l'écrire dans 4 lignes de code. J'ai édité ma question et a fourni un code exact qui reproduit le problème!


En ce qui concerne la survie de la théorie des bibliothèques chargées, je pense que nous pourrions le rejeter en toute sécurité.


@mvds, ok, corrigé la réponse :-)



8
votes

EDIT: STRUT> Donc, le problème / la question était donc le suivant: le savoir-faire ne peut pas vous non défini ld_preload code> à l'aide d'un Main_Init préchargé () code> de l'intérieur bash code>.

La raison est que exécut code>, qui est appelé après que vous popen code>, prend l'environnement de (probablement) p>

execve("/bin/sh", ["sh", "-c", "ls"], [... "DD_PRELOAD=mylib.so" ...]) = 0


9 commentaires

Ld_preload n'est pas dans l'environnement du processus de l'enfant (ni dans le parent après le désétène). Réponse de Pavel Conseils sur la raison: LD_ProLoad est utilisé par le chargeur et non par mon programme. myLib.so est déjà chargé et le chargeur conserve probablement son comportement sans relire LD_PRÉLOAD. Fork & Calle est une option; Cependant, Popen est beaucoup préféré depuis cela, je me suis laissé lire la sortie du processus d'enfant de manière simple. Gace de la strace Beaucoup d'informations qui ne m'ont pas aidé. J'ai utilisé: Exporter ld_debug = Symnols et vu clairement que tous les symboles sont recherchés dans Mylib.So avant tout autre lib.


Cela devient toujours plus intéressant, vient de mettre à jour ma réponse avec quelques suggestions supplémentaires


@avner: Encore plus de suggestions dans la réponse, construit mon propre .so et ne peut toujours pas voir ce que vous voyez ...


@avner: Même avec popen ("/ bin / ls", "r"); comme vous l'avez fait, j'ai reçu les mêmes résultats. Êtes-vous vraiment sûr de ne rien manquer d'autre chose?


@mvds - Merci d'abord beaucoup pour les exemples et explications détaillés. Votre code travaille pour moi comme vous l'avez écrit (c'est-à-dire que LD_PRELOAD n'avait aucun effet sur l'enfant comme prévu). Votre réponse mérite sûrement de voter. J'ai essayé de voter, mais j'ai échoué parce que le vote nécessite une réputation que je n'ai pas encore) -: de toute façon, je suis désormais perplexe pourquoi dans mon code (le vrai, pas le court exemple) Je souffre toujours de ce problème . Une différence est que mon problème est avec la «bash» que popen commence et non avec le commandement lui-même. Pourtant, cela n'explique pas assez la différence dans le comportement.


Je pense que vous avez 16 répétitions maintenant ;-) J'ai fait un échantillon ici avec popen () comme je l'ai dit et que ça va aussi. Même avec popen ("/ bin / sh testscript", "r"); et testScript contenant export et / bin / ls . Qu'est-ce que tu fais de l'homme ?! Avez-vous été salué avec /etc/ld.so. * ?


Avez-vous essayé export ld_preload = , puis ldd ./prog pour vérifier s'il n'est pas lié pour une autre raison?


Résolu! Voir ma réponse mise à jour. Voir l'histoire de la révision pour des exemples de préchargement, je les ai tous effondrés.


@mvds, je suis iprimé! 1) Votre explication a clarifié le mystère 2) Votre solution de contournement "my_unsetenv" a travaillé comme un charme 3) J'ai trouvé ce qui suit dans la sortie que j'ai déjà eu avec ld_debug = tout 1.15414- 15414: appelant init :./mylib.so 1.15414- 15414: 1.15414: 15414: Symbole = nonsetenv; Recherche dans File = Bash [0] 1.15414- 15414: Fichier de liaison ./MYLIB.SO [0] à BASH [0]: Symbole normal `nonsetenv '[glibc_2.2.5] Ceci propose certainement votre solution !!



0
votes

La réponse de MVDS est incorrecte!

Popen () va frayer un processus enfant qui hérite de la précharge .so menti au processus parent. Ce processus enfant ne fiche pas d'environnement LD_PRÉLOAD.


0 commentaires