6
votes

Problèmes liés aux interpositions LD_PRÉLOAD et CALLOC () pour certains exécutables

Relatif à un précédent Question de la mine

J'ai interposé avec succès malloc , mais calloc semble être plus problématique.

c'est avec certains hôtes, calloc se bloque dans une boucle infinie avec un possible interne calloc appel interne dlsym . Cependant, un hôte de test de base n'expose pas ce comportement, mais la commande "ls" de mon système fait.

voici mon code: xxx

maintenant, quand Je fais ce qui suit, je reçois une boucle infinie suivie d'une faute SEG, par exemple: xxx

Toutefois si je commencez le interposeur de calloc interposant, il Presque semble fonctionner: xxx

alors peut-être avec "LS" qui signifie init () est appelé deux fois.

éditer Notez que le programme hôte suivant fonctionne correctement - init () est uniquement appelé une seule fois, et calloc est interposé avec succès, comme vous pouvez le constater à partir de la sortie. xxx


1 commentaires

Vérifiez cette solution: blog.bigpixel.ro/2010/09/interpose -Calloc-on-Linux ça marche même que ça ne devrait pas ...


5 Réponses :


3
votes

En ce qui concerne __ nano_init () être appelé deux fois: vous avez déclaré la fonction en tant que constructeur, il est donc appelé lorsque la bibliothèque est chargée et qu'elle s'appelle une seconde fois explicitement lorsque votre MALLOC () et calloc () Les implémentations sont d'abord appelées. Choisir un.

En ce qui concerne le calloc () Interposeur Crashing Votre application: certaines des fonctions que vous utilisez, y compris dlsym () et fprintf () < / Code> peut-être eux-mêmes tenter d'allouer de la mémoire, appelant vos fonctions d'interpose. Considérez les conséquences et agissez en conséquence.


3 commentaires

Voir mon édition avec un exemple d'hôte qui semble fonctionner correctement.


La deuxième partie de votre réponse est correcte. La première partie sur le constructeur n'est pas, car le remplacement se produit avant le constructeur - uniquement pour certains exécutables, qui finissent par appeler l'init deux fois directement (pas via constructeur).


Il est possible que ce qui se passait la première fois autour était que certains exécutables appelleraient masloc () / calloc () dans leurs propres initialisateurs avant le tour de la vôtre.



2
votes

Utilisation de dlsym L'accrochage basé sur le dlsym peut entraîner des crashs, comme dlsym rappelle dans l'allocator de la mémoire. Au lieu d'utiliser Hooks MALLOC , comme je l'ai suggéré dans votre question préalable ; Ceux-ci peuvent être installés sans invoquer dlsym du tout.


7 commentaires

Ok je vais juste supposer dans ce cas dlsym ne fonctionnera pas - malgré les nombreux exemples sur Internet qui montrent de remplacer les fonctions de mémoire avec elle. Je vais essayer de formuler une nouvelle question alors montrant l'un de ces exemples.


@Justicle, juste parce que cela pourrait avoir travaillé si vous n'avez accroché que certaines des fonctions, ou peut-être avoir travaillé à un moment donné dans le passé, cela ne signifie pas que cela fonctionnera avec de nouvelles versions de Glibc. Utilisez les fonctions de crochet; Ce sont les seuls ceux qui sont garantis pour fonctionner correctement.


En outre, il n'y a aucune mention de problèmes avec dlsym dans tous les exemples que je peux trouver, et jusqu'à présent, je n'ai pas trouvé personne indiquant pourquoi les crochets seraient meilleurs que le précharge. Je suppose que je ne peux pas croire que je suis la première personne à essayer ceci ...


Peut-être qu'ils n'essayent pas avec calloc ? En tout cas, il est suffisamment clair que cela ne fonctionne pas, et glibc a cette belle fonctionnalité qui fait ce que vous voulez de manière prise en charge, alors utilisez-le déjà :)


OK Le centime vient de laisser tomber: d Allocators de remplacement qui fonctionnent via LD_ProLoad fournissent un remplacement complet pour les fonctions de mémoire, pas seulement un passage à travers. Donc, 1) Il n'y a pas de question "my_awesum_calloc" impliquée par libc fonctionne comme dlsym . et 2) L'appel DLSYM n'est pas nécessaire, car vous n'avez pas besoin de l'ancienne mise en œuvre.


@Justicule, et il fournit un pointeur de fonction directe à la mise en œuvre originale sans vous déranger avec DLSYM :) [Notez que DLSym et vos amis retourneront dans votre calloc de remplacement - mais depuis Vous avez le pointeur à l'original sans utiliser dlsym, ce n'est pas un problème]


Les crochets sont obsolètes, car ils ne sont pas un fil de sécurité. Voir la section Notes dans ce lien Man7.org/Linux/man-pages/ Man3 / Malloc_hook.3.html . De plus, je ne pense pas que les crochets couvrent CalloC.



1
votes

Vous pouvez vous éloigner d'un calloc pauvre préliminaire qui retourne simplement NULL. Cela fonctionne réellement sur Linux, YMMV.

static void* poor_calloc(size_t nmemb, size_t size)
{
    // So dlsym uses calloc internally, which will lead to infinite recursion, since our calloc calls dlsym.
    // Apparently dlsym can cope with slightly wrong calloc, see for further explanation:
    // http://blog.bigpixel.ro/2010/09/interposing-calloc-on-linux
    return NULL; // This is a poor implementation of calloc!
}


0 commentaires

6
votes

Je sais que je suis un peu en retard (6 ans). Mais je voulais remplacer calloc () aujourd'hui et faire face à un problème car dlsym () utilise en interne calloc () . J'ai résolu l'utilisation d'une technique simple et j'ai pensé à le partager ici: xxx

tampon satisfait à la nécessité de dlsym () jusqu'à ce que le vrai calloc () a été localisé et mon "code> pointeur de fonction calloc_ptr initialisé"


0 commentaires

1
votes

Vous pouvez également utiliser SBRK pour allouer la mémoire pour "Mauvais CalloC".


0 commentaires