windows_ipc.tex 6.2 KB

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