IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèque standard C Discussion :

Redéfinition des appels systèmes


Sujet :

Bibliothèque standard C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2003
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 67
    Par défaut Redéfinition des appels systèmes
    Bonjour,

    Je suis entrain de développer une API qui doit faire en sorte que tous les appels systèmes agissant sur le système de fichiers se fassent à distance (rpc ou socket). Pour ce faire, je dois redéfiir les appels systèmes open, write, read... ce qui est déjà fait. Par contre pour le code user, rien ne doit être modifié, excepté au pire des cas, l'ajout d'une directive include, et la recompilation des sources en les linkant avec ma librairie.
    Ce que j'ai essayé de faire, c'est de faire des remplacement par le préprocesseur de tous ces appels par des appels correspondant à ma librairie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define write my_write
    Ceci, fonctionne correctement. Seulement, dès qu'il s'agit d'appels de fonctions de la libc faisant des appels systèmes, ce sont les versions originales qui sont utilisées, ce qui est normal car le printf par exemple ne voit jamais mon #define write my_write.

    Comment pourrais-je faire ?

    Merci d'avance !

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2003
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 67
    Par défaut
    Pour ceux qui sont intéressés, j'ai posé ma question sur linuxquestions.org, voici la réponse qui m'a été donnée :

    There are two approaches to this, non of which is trivial. The first is to have a preloaded library (with LD_PRELOAD) which has access to the original C library through dlopen(). You can read about this approach if you study the sources of say installwatch (part of src2pkg maintained by Gilbert Ashley—gnashley).

    The other approach is to use ptrace to intercept system calls as they happen, and alter them. This is also nontrivial, but much more elegant. There are at least a few pieces of software which already do this (I cannot think of one offhand).

    J'ai finalement opté pour l'approche ptrace.

  3. #3
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 145
    Par défaut
    Pour changer sur tout le système : il faut manipuler le fichier /etc/ld.so.preload ou /etc/ld.so.conf et utiliser ldconfig.

    Sinon, pour modifier juste une ou certaines applications, il faut mettre à jour la variable LD_PRELOAD. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    export LD_PRELOAD=/lib/mylib.so
    Inutile je suppose de vous rappeler la prudence avec ce type de commande

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 145
    Par défaut
    Disons que la première méthode a justement été prévue pour ce genre de choses, elle est donc standard. Par ailleurs, elle est très simple à implémenter.

    L'approche ptrace() me semble bien plus compliquée à mettre en oeuvre et elle n'est de toute façons pas prévue pour faire ce genre de choses. J'ai donc un peu de mal à voir en quoi elle est plus élégante

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2003
    Messages
    67
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 67
    Par défaut
    J'ai pris la deuxième solution non pas qu'elle me semblait plus élegante, mais plus intéressante car je n'avais jamais utilisé ptrace. De plus, je ne vois pas comment faire pour la première approche, j'ai l'impression que j'aurais le même problème pour les appels de la librairie c qui font appel à mes fonctions redéfinis.
    Je m'explique. Si dans mon main.c
    J'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <unistd.h>
    #include <string.h>
    int main(){
      write(1, "Hello World", strlen("Hello World"));
    }
    et que dans mon libc_stub.c, à partir duquel je vais construire ma lib dyn, j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include <unistd.h>
    #include <sys/syscall.h>
    #include <string.h>
     
    ssize_t write(int fd, const void *buf, size_t count){
      return syscall(SYS_write, fd, "Hello World from Stub" , strlen("Hello World from Stub"));
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    LD_PRELOAD=/opt/lib/libc_stub.so ./main
    affiche bien "Hello World from Stub"

    Par contre, ce main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <stdio.h>
    int main(){
      printf("Hello World\n");
      return 0;
    }
    affiche "Hello World" !

    Le write invoqué par le printf n'est pas celui de ma librairie mais le write de la libc.

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 145
    Par défaut
    Le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #include <stdio.h>
    int main(){
      printf("Hello World\n");
      return 0;
    }
    Si on compile et on regarde la fonction appelée dans la libc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    $ gcc foo.c
    $ nm -u a.out
             w _Jv_RegisterClasses
             w __gmon_start__
             U __libc_start_main@@GLIBC_2.0
             U puts@@GLIBC_2.0
    On voit que printf ne fait pas appel à write mais à puts

    Note : je viens de relire le post dès le début et de réaliser que la méthode ci-dessus ne fait que remplacer des fonctions standard de la libc. Si on veut réellement insérer un bout de code avant l'appel système (sys_)write, cela force donc à réimplémenter toutes les primitives de la libc qui font une écriture (write, puts...). Je comprends mieux alors pourquoi ptrace est une bonne solution. Maxi mea culpa.

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    145
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 145
    Par défaut
    En farfouillant sur la toile :
    Playing with ptrace
    L'exemple est super clair et l'implémentation est vraiment très simple

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 28/10/2011, 23h38
  2. [linux] utilisation des appels système
    Par Invité dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 21/05/2011, 23h53
  3. Réponses: 2
    Dernier message: 16/08/2009, 13h31
  4. Réponses: 1
    Dernier message: 14/03/2007, 15h56
  5. appeler des API système
    Par pierre.zelb dans le forum VBScript
    Réponses: 12
    Dernier message: 29/11/2006, 13h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo