windows_ipc.tex 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. % TODO: remplacer confiant
  2. Après la présentation des objectifs liés aux communications inter-processus et à
  3. l'implémentation Linux, nous pouvons essayer de reprendre le même modèle pour
  4. l'implémentation Windows. Malheureusement celle-ci vient nous rappeler qu'un
  5. changement de système implique parfois un changement de paradigme. La
  6. documentation quelque peu hasardeuse va néanmoins nous permettre de mettre en
  7. place une architecture similaire.
  8. \section{Communication inter-processus}
  9. Windows dispose de beaucoup de moyens de communication inter-processus. Parmi
  10. ceux là, aucun ne va avoir les mêmes propriétés que les sockets Unix. Nous
  11. allons même de base éliminer tous les moyens «haut niveau» comme les ports COM
  12. résolvant plutôt des problèmes d'interopérabilité et se concentrer sur les
  13. moyens plus bas niveau.
  14. \subsection{Les sockets Windows}
  15. Les sockets Windows réimplémentent la même interface que les sockets Berkeley
  16. mais ne fournissent pas de sockets locaux ou anonymes. Ceux-ci passent par la
  17. pile réseau pour l'envoi de message. On notera cependant l'implémentation de
  18. «TCP Loopback Fast Path» depuis Windows Server 2012. Cette fonctionnalité
  19. conserve la sémantique du protocole TCP tout en désactivant des fonctionnalités
  20. comme l'algorithme de Nagle.
  21. \footnote{https://blogs.technet.microsoft.com/wincat/2012/12/05/fast-tcp-loopback-performance-and-low-latency-with-windows-server-2012-tcp-loopback-fast-path/}
  22. C'est donc ce qui ressemble le plus aux sockets Unix, excepté l'accès au réseau
  23. et le passage de descripteur de fichiers.
  24. \subsection{Les canaux anonymes}
  25. Les canaux anonymes donnent un moyen de communication unidirectionnel avec un
  26. écrivain et un lecteur. Il faut donc utiliser une paire de canaux anonymes pour
  27. pouvoir discuter en full-duplex, mais également utiliser un mécanisme pour
  28. transmettre le \inltype{HANDLE} d'un processus à l'autre. À noter que la plupart
  29. des fonctions sur les canaux nommés fonctionnent avec les canaux anonymes, ces
  30. derniers étant implémentés comme des canaux nommés avec un nom particulier.
  31. \subsection{Les canaux nommés}
  32. Les canaux nommés sont capables de fonctionner en full-duplex et disposent
  33. pleinement du système d'ACL global de Windows.
  34. Ici, on va plutôt s'intéresser aux canaux nommés et voir comment on peut les
  35. utiliser pour transmettre des messages et des ressources. La création d'un canal
  36. nommé se fait avec avec la famille de fonction \inltype{CreateNamedPipe}. Dans
  37. notre cas, on sera fortement tenté d'utiliser des \inltype{lpSecurityAttributes}
  38. définis avec de bonnes valeurs, mais ce point sera exploré dans la suite du
  39. document.
  40. \begin{code}{c}{Prototype de \inltype{CreateNamedPipe}}
  41. HANDLE CreateNamedPipeA(
  42. LPCSTR lpName,
  43. DWORD dwOpenMode,
  44. DWORD dwPipeMode,
  45. DWORD nMaxInstances,
  46. DWORD nOutBufferSize,
  47. DWORD nInBufferSize,
  48. DWORD nDefaultTimeOut,
  49. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  50. );
  51. \end{code}
  52. \section{Transfert de ressources entre processus}
  53. Windows dispose de trois mécanismes pour partager des ressources entre
  54. processus. Les ressources sont représentées par des objets \inltype{HANDLE}.
  55. La première méthode est l'héritage, qui a lieu lors de la création d'un nouveau
  56. processus. Les descripteurs de fichiers marqués comme héritables, ou bien aucun
  57. si \inltype{bInheritHandles} est précisé à \inltype{FALSE} lors de l'appel de
  58. \inltype{CreateProcess}, seront récupérés dans le nouveau processus avec la même
  59. valeur. Lorsqu'un \inltype{HANDLE} est hérité, il garde la même valeur dans le
  60. nouveau processus et il faut donc le transmettre soit par IPC, soit par
  61. paramètre de la ligne de commande, soit par injection de code dans le nouveau
  62. processus.
  63. La seconde méthode utilise la fonction \inltype{DuplicateHandle} pour injecter
  64. le descripteur de fichier dans le nouveau processus. Dans ce cas-là, si l'appel
  65. est fait depuis le processus parent, une nouvelle valeur est générée pour ce
  66. \inltype{HANDLE} et il faut le transmettre au processus enfant par l'une des
  67. méthodes mentionnées dans le cas de l'héritage.
  68. \begin{code}{c}{Prototype de la fonction \inltype{DuplicateHandle}}
  69. BOOL WINAPI DuplicateHandle(
  70. _In_ HANDLE hSourceProcessHandle,
  71. _In_ HANDLE hSourceHandle,
  72. _In_ HANDLE hTargetProcessHandle,
  73. _Out_ LPHANDLE lpTargetHandle,
  74. _In_ DWORD dwDesiredAccess,
  75. _In_ BOOL bInheritHandle,
  76. _In_ DWORD dwOptions
  77. );
  78. \end{code}
  79. L'exploitation de \inltype{DuplicateHandle} demande à ce que chacun des deux
  80. processus rentrant en jeu dans la fonction, à savoir
  81. \inltype{hSourceProcessHandle} et \inltype{hTargetProcessHandle} disposent du
  82. droit \inltype{PROCESS_DUP_HANDLE}. Étant donné que la fonction peut être
  83. utilisée de la source vers la destination ou depuis la destination récupérant un
  84. \inltype{HANDLE} appartenant à la source, le processus ayant accès à l'autre
  85. processus est capable de copier tout accès existant et dispose donc des mêmes
  86. droits que ce dernier.
  87. Cette remarque est importante pour se rendre compte que l'utilisation de cette
  88. méthode implique nécessairement un broker, qui sera suffisamment privilégié pour
  89. accéder aux deux processus souhaitant partager une ressource. Tenter d'appliquer
  90. cette fonction directement dans les workers impliquerait que chacun des workers
  91. auraient les mêmes droits que ses voisin et, de façon transitive, aurait accès à
  92. toutes les zones de privilèges connexes dans le graphe d'IPC.
  93. Enfin, la troisième méthode consiste à utiliser les objets nommés qui sont
  94. créés d'un côté par le processus parent, puis ouverts par les processus enfants
  95. en les référençant par leur nom.
  96. Dans le prototype, j'ai utilisé des canaux nommés pour faciliter la mise en place
  97. mais j'ai également essayé d'utiliser des paires de canaux anonymes dans d'autres
  98. codes simulant le fonctionnement des IPC. J'ai également prévu de mettre en
  99. place la méthode utilisant \inltype{DuplicateHandle} et donc un broker central
  100. pour pouvoir transférer des ressources de la même façon que sous Linux.
  101. J'essayerai cependant de m'approcher d'un modèle orchestrateur avec d'autres
  102. techniques mais nous allons voir qu'il n'y a pas vraiment d'alternative pour
  103. l'instant.