unsocket.c 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. unsocket.c
  5. Abstract:
  6. This module implements support for Unix domain sockets.
  7. Author:
  8. Evan Green 15-Jan-2015
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include "iop.h"
  17. #include "unsocket.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // Define the default maximum pending send size for a Unix socket. This is
  23. // how much data a socket can send without the receiver receiving it before the
  24. // sender is blocked.
  25. //
  26. #define UNIX_SOCKET_DEFAULT_SEND_MAX 131072
  27. //
  28. // Define the maximum number of file descriptors that can be passed in a
  29. // rights control message.
  30. //
  31. #define UNIX_SOCKET_MAX_CONTROL_HANDLES 256
  32. //
  33. // Define the maximum size of control data.
  34. //
  35. #define UNIX_SOCKET_MAX_CONTROL_DATA 32768
  36. //
  37. // Define local socket flags.
  38. //
  39. //
  40. // This flag is set when the socket should send and receive credentials in
  41. // control data automatically.
  42. //
  43. #define UNIX_SOCKET_FLAG_SEND_CREDENTIALS 0x00000001
  44. //
  45. // ------------------------------------------------------ Data Type Definitions
  46. //
  47. typedef enum _UNIX_SOCKET_STATE {
  48. UnixSocketStateInvalid,
  49. UnixSocketStateInitialized,
  50. UnixSocketStateBound,
  51. UnixSocketStateListening,
  52. UnixSocketStateConnected,
  53. UnixSocketStateShutdownWrite,
  54. UnixSocketStateShutdownRead,
  55. UnixSocketStateShutdown,
  56. UnixSocketStateClosed
  57. } UNIX_SOCKET_STATE, *PUNIX_SOCKET_STATE;
  58. typedef struct _UNIX_SOCKET UNIX_SOCKET, *PUNIX_SOCKET;
  59. /*++
  60. Structure Description:
  61. This structure defines a set of Unix socket credentials. This structure
  62. matches up with struct ucred in the C library.
  63. Members:
  64. ProcessId - Stores the ID of the process that sent the message, or -1 if
  65. not set.
  66. UserId - Stores the user ID of the process that sent the message, or -1 if
  67. not set.
  68. GroupId - Stores the group ID of the process that sent the message, or -1
  69. if not set.
  70. --*/
  71. typedef struct _UNIX_SOCKET_CREDENTIALS {
  72. PROCESS_ID ProcessId;
  73. USER_ID UserId;
  74. GROUP_ID GroupId;
  75. } UNIX_SOCKET_CREDENTIALS, *PUNIX_SOCKET_CREDENTIALS;
  76. /*++
  77. Structure Description:
  78. This structure defines a Unix socket object.
  79. Members:
  80. ListEntry - Stores pointers to the next and previous packets to be received.
  81. Data - Stores a pointer to the data.
  82. Length - Stores the length of the data, in bytes.
  83. Offset - Stores the number of bytes the receiver has already returned.
  84. Sender - Stores a pointer to the sender. This structure holds a reference
  85. to the sender which must be released when this structure is destroyed.
  86. Credentials - Stores the credentials of the sender.
  87. Handles - Stores an optional pointer to an array of file handles being
  88. passed in this message.
  89. HandleCount - Stores the number of file handles being passed in this
  90. message.
  91. --*/
  92. typedef struct _UNIX_SOCKET_PACKET {
  93. LIST_ENTRY ListEntry;
  94. PVOID Data;
  95. UINTN Length;
  96. UINTN Offset;
  97. PUNIX_SOCKET Sender;
  98. UNIX_SOCKET_CREDENTIALS Credentials;
  99. PIO_HANDLE *Handles;
  100. UINTN HandleCount;
  101. } UNIX_SOCKET_PACKET, *PUNIX_SOCKET_PACKET;
  102. /*++
  103. Structure Description:
  104. This structure defines a Unix socket object.
  105. Members:
  106. KernelSocket - Stores the standard kernel socket portions.
  107. Lock - Stores a pointer to the lock that protects this socket.
  108. State - Stores the current state of the socket.
  109. Name - Stores a pointer to the name of the socket, allocated from paged
  110. pool.
  111. NameSize - Stores the size of the name buffer in bytes, including the null
  112. terminator.
  113. PathPoint - Stores a pointer to the path point where this socket resides if
  114. it is bound. The socket holds a reference on the path point.
  115. ReceiveList - Stores the head of the list of outgoing packets. Entries on
  116. this list are Unix socket packets.
  117. SendListMax - Stores the maximum number of bytes that can be queued on the
  118. send list before the socket blocks.
  119. SendListSize - Stores the current number of bytes queued to be sent.
  120. MaxBacklog - Stores the maximum incoming connection backlog.
  121. CurrentBacklog - Stores the current number of incoming connections.
  122. ConnectionListEntry - Stores a dual-purpose list entry. For servers, this
  123. represents the head of the list of sockets trying to connect to it.
  124. For clients, this is the list entry that goes on the server's incoming
  125. connection list.
  126. Remote - Stores a pointer to the other side of the connection, for a
  127. connection oriented socket.
  128. Flags - Stores a bitfield of flags governing the socket. See
  129. UNIX_SOCKET_FLAG_* definitions.
  130. Credentials - Stores the credentials of the process when the socket was
  131. connected.
  132. --*/
  133. struct _UNIX_SOCKET {
  134. SOCKET KernelSocket;
  135. PQUEUED_LOCK Lock;
  136. UNIX_SOCKET_STATE State;
  137. PSTR Name;
  138. UINTN NameSize;
  139. PATH_POINT PathPoint;
  140. LIST_ENTRY ReceiveList;
  141. UINTN SendListMax;
  142. UINTN SendListSize;
  143. UINTN MaxBacklog;
  144. UINTN CurrentBacklog;
  145. LIST_ENTRY ConnectionListEntry;
  146. PUNIX_SOCKET Remote;
  147. ULONG Flags;
  148. UNIX_SOCKET_CREDENTIALS Credentials;
  149. };
  150. //
  151. // ----------------------------------------------- Internal Function Prototypes
  152. //
  153. KSTATUS
  154. IopUnixSocketEnsureConnected (
  155. PUNIX_SOCKET Socket,
  156. BOOL Write
  157. );
  158. VOID
  159. IopUnixSocketFlushData (
  160. PUNIX_SOCKET Socket
  161. );
  162. KSTATUS
  163. IopUnixSocketCreatePacket (
  164. PUNIX_SOCKET Sender,
  165. PIO_BUFFER IoBuffer,
  166. UINTN Offset,
  167. UINTN DataSize,
  168. PUNIX_SOCKET_PACKET *NewPacket
  169. );
  170. VOID
  171. IopUnixSocketDestroyPacket (
  172. PUNIX_SOCKET_PACKET Packet
  173. );
  174. KSTATUS
  175. IopUnixSocketSendControlData (
  176. BOOL FromKernelMode,
  177. PUNIX_SOCKET Sender,
  178. PUNIX_SOCKET_PACKET Packet,
  179. PVOID ControlData,
  180. UINTN ControlDataSize
  181. );
  182. KSTATUS
  183. IopUnixSocketReceiveControlData (
  184. BOOL FromKernelMode,
  185. PUNIX_SOCKET Socket,
  186. PUNIX_SOCKET_PACKET Packet,
  187. PSOCKET_IO_PARAMETERS Parameters
  188. );
  189. VOID
  190. IopUnixSocketInitializeCredentials (
  191. PUNIX_SOCKET Socket
  192. );
  193. //
  194. // -------------------------------------------------------------------- Globals
  195. //
  196. //
  197. // ------------------------------------------------------------------ Functions
  198. //
  199. KSTATUS
  200. IopCreateUnixSocketPair (
  201. NET_SOCKET_TYPE Type,
  202. ULONG Protocol,
  203. ULONG OpenFlags,
  204. PIO_HANDLE NewSockets[2]
  205. )
  206. /*++
  207. Routine Description:
  208. This routine creates a pair of connected local domain sockets.
  209. Arguments:
  210. Type - Supplies the socket connection type.
  211. Protocol - Supplies the raw protocol value for this socket used on the
  212. network. This value is network specific.
  213. OpenFlags - Supplies a bitfield of open flags governing the new handles.
  214. See OPEN_FLAG_* definitions.
  215. NewSockets - Supplies an array where the two pointers to connected sockets
  216. will be returned.
  217. Return Value:
  218. Status code.
  219. --*/
  220. {
  221. PIO_HANDLE IoHandles[2];
  222. PSOCKET Sockets[2];
  223. KSTATUS Status;
  224. PUNIX_SOCKET UnixSockets[2];
  225. IoHandles[0] = NULL;
  226. IoHandles[1] = NULL;
  227. Status = IoSocketCreate(NetDomainLocal,
  228. Type,
  229. Protocol,
  230. OpenFlags,
  231. &(IoHandles[0]));
  232. if (!KSUCCESS(Status)) {
  233. goto CreateUnixSocketPairEnd;
  234. }
  235. Status = IoSocketCreate(NetDomainLocal,
  236. Type,
  237. Protocol,
  238. OpenFlags,
  239. &(IoHandles[1]));
  240. if (!KSUCCESS(Status)) {
  241. goto CreateUnixSocketPairEnd;
  242. }
  243. Status = IoGetSocketFromHandle(IoHandles[0], &(Sockets[0]));
  244. ASSERT(KSUCCESS(Status));
  245. Status = IoGetSocketFromHandle(IoHandles[1], &(Sockets[1]));
  246. ASSERT(KSUCCESS(Status));
  247. UnixSockets[0] = (PUNIX_SOCKET)(Sockets[0]);
  248. UnixSockets[1] = (PUNIX_SOCKET)(Sockets[1]);
  249. //
  250. // Connect the two sockets directly together.
  251. //
  252. UnixSockets[0]->Remote = UnixSockets[1];
  253. IoSocketAddReference(Sockets[1]);
  254. UnixSockets[1]->Remote = UnixSockets[0];
  255. IoSocketAddReference(Sockets[0]);
  256. UnixSockets[0]->State = UnixSocketStateConnected;
  257. UnixSockets[1]->State = UnixSocketStateConnected;
  258. IopUnixSocketInitializeCredentials(UnixSockets[0]);
  259. IopUnixSocketInitializeCredentials(UnixSockets[1]);
  260. Status = STATUS_SUCCESS;
  261. CreateUnixSocketPairEnd:
  262. if (!KSUCCESS(Status)) {
  263. if (IoHandles[0] != NULL) {
  264. IoClose(IoHandles[0]);
  265. IoHandles[0] = NULL;
  266. }
  267. if (IoHandles[1] != NULL) {
  268. IoClose(IoHandles[1]);
  269. IoHandles[1] = NULL;
  270. }
  271. }
  272. NewSockets[0] = IoHandles[0];
  273. NewSockets[1] = IoHandles[1];
  274. return Status;
  275. }
  276. KSTATUS
  277. IopCreateUnixSocket (
  278. NET_DOMAIN_TYPE Domain,
  279. NET_SOCKET_TYPE Type,
  280. ULONG Protocol,
  281. PSOCKET *NewSocket
  282. )
  283. /*++
  284. Routine Description:
  285. This routine creates a new Unix socket object.
  286. Arguments:
  287. Domain - Supplies the network domain to use on the socket.
  288. Type - Supplies the socket connection type.
  289. Protocol - Supplies the raw protocol value for this socket used on the
  290. network. This value is network specific.
  291. NewSocket - Supplies a pointer where a pointer to a newly allocated
  292. socket structure will be returned. The caller is responsible for
  293. allocating the socket (and potentially a larger structure for its own
  294. context). The kernel will fill in the standard socket structure after
  295. this routine returns.
  296. Return Value:
  297. Status code.
  298. --*/
  299. {
  300. PUNIX_SOCKET Socket;
  301. KSTATUS Status;
  302. ASSERT(Domain == NetDomainLocal);
  303. Socket = MmAllocatePagedPool(sizeof(UNIX_SOCKET),
  304. UNIX_SOCKET_ALLOCATION_TAG);
  305. if (Socket == NULL) {
  306. Status = STATUS_INSUFFICIENT_RESOURCES;
  307. goto CreateUnixSocketEnd;
  308. }
  309. RtlZeroMemory(Socket, sizeof(UNIX_SOCKET));
  310. Socket->KernelSocket.Protocol = Protocol;
  311. Socket->KernelSocket.ReferenceCount = 1;
  312. Socket->KernelSocket.IoState = IoCreateIoObjectState(FALSE);
  313. if (Socket->KernelSocket.IoState == NULL) {
  314. Status = STATUS_INSUFFICIENT_RESOURCES;
  315. goto CreateUnixSocketEnd;
  316. }
  317. IoSetIoObjectState(Socket->KernelSocket.IoState,
  318. POLL_EVENT_IN | POLL_EVENT_OUT,
  319. FALSE);
  320. Socket->Lock = KeCreateQueuedLock();
  321. if (Socket->Lock == NULL) {
  322. Status = STATUS_INSUFFICIENT_RESOURCES;
  323. goto CreateUnixSocketEnd;
  324. }
  325. Socket->State = UnixSocketStateInitialized;
  326. INITIALIZE_LIST_HEAD(&(Socket->ReceiveList));
  327. INITIALIZE_LIST_HEAD(&(Socket->ConnectionListEntry));
  328. Socket->SendListMax = UNIX_SOCKET_DEFAULT_SEND_MAX;
  329. Socket->Credentials.ProcessId = -1;
  330. Socket->Credentials.UserId = -1;
  331. Socket->Credentials.GroupId = -1;
  332. Status = STATUS_SUCCESS;
  333. CreateUnixSocketEnd:
  334. if (!KSUCCESS(Status)) {
  335. if (Socket != NULL) {
  336. if (Socket->Lock != NULL) {
  337. KeDestroyQueuedLock(Socket->Lock);
  338. }
  339. if (Socket->KernelSocket.IoState != NULL) {
  340. IoDestroyIoObjectState(Socket->KernelSocket.IoState);
  341. }
  342. MmFreePagedPool(Socket);
  343. Socket = NULL;
  344. }
  345. }
  346. *NewSocket = &(Socket->KernelSocket);
  347. return Status;
  348. }
  349. VOID
  350. IopDestroyUnixSocket (
  351. PSOCKET Socket
  352. )
  353. /*++
  354. Routine Description:
  355. This routine destroys the Unix socket object.
  356. Arguments:
  357. Socket - Supplies a pointer to the socket.
  358. Return Value:
  359. None.
  360. --*/
  361. {
  362. PUNIX_SOCKET UnixSocket;
  363. UnixSocket = (PUNIX_SOCKET)Socket;
  364. ASSERT(Socket->Domain == NetDomainLocal);
  365. ASSERT(UnixSocket->CurrentBacklog == 0);
  366. ASSERT(UnixSocket->SendListSize == 0);
  367. ASSERT(LIST_EMPTY(&(UnixSocket->ReceiveList)) != FALSE);
  368. if (UnixSocket->PathPoint.PathEntry != NULL) {
  369. IO_PATH_POINT_RELEASE_REFERENCE(&(UnixSocket->PathPoint));
  370. UnixSocket->PathPoint.PathEntry = NULL;
  371. }
  372. if (UnixSocket->Name != NULL) {
  373. MmFreePagedPool(UnixSocket->Name);
  374. }
  375. if (UnixSocket->Lock != NULL) {
  376. KeDestroyQueuedLock(UnixSocket->Lock);
  377. }
  378. UnixSocket->State = UnixSocketStateInvalid;
  379. MmFreePagedPool(UnixSocket);
  380. return;
  381. }
  382. KSTATUS
  383. IopUnixSocketBindToAddress (
  384. BOOL FromKernelMode,
  385. PIO_HANDLE Handle,
  386. PNETWORK_ADDRESS Address,
  387. PSTR Path,
  388. UINTN PathSize
  389. )
  390. /*++
  391. Routine Description:
  392. This routine binds the Unix socket to the given path and starts listening
  393. for client requests.
  394. Arguments:
  395. FromKernelMode - Supplies a boolean indicating if the request is coming
  396. from kernel mode or user mode. This value affects the root path node
  397. to traverse for local domain sockets.
  398. Handle - Supplies a pointer to the handle to bind.
  399. Address - Supplies a pointer to the address to bind the socket to.
  400. Path - Supplies an optional pointer to a path, required if the network
  401. address is a local socket.
  402. PathSize - Supplies the size of the path in bytes including the null
  403. terminator.
  404. Return Value:
  405. Status code.
  406. --*/
  407. {
  408. SOCKET_CREATION_PARAMETERS CreationParameters;
  409. PFILE_OBJECT FileObject;
  410. ULONG OpenFlags;
  411. PSTR PathCopy;
  412. PATH_POINT PathPoint;
  413. PSOCKET Socket;
  414. KSTATUS Status;
  415. PUNIX_SOCKET UnixSocket;
  416. PSTR WalkedPath;
  417. ULONG WalkedPathSize;
  418. PathCopy = NULL;
  419. IO_INITIALIZE_PATH_POINT(&PathPoint);
  420. UnixSocket = NULL;
  421. FileObject = Handle->FileObject;
  422. Status = IoGetSocketFromHandle(Handle, &Socket);
  423. if (!KSUCCESS(Status)) {
  424. return Status;
  425. }
  426. ASSERT(Socket->Domain == NetDomainLocal);
  427. UnixSocket = (PUNIX_SOCKET)Socket;
  428. KeAcquireQueuedLock(UnixSocket->Lock);
  429. //
  430. // If the socket isn't a fresh one, fail.
  431. //
  432. if (UnixSocket->State != UnixSocketStateInitialized) {
  433. Status = STATUS_INVALID_PARAMETER;
  434. goto UnixSocketBindToAddressEnd;
  435. }
  436. if (PathSize != 0) {
  437. if (FromKernelMode != FALSE) {
  438. PathCopy = MmAllocatePagedPool(PathSize,
  439. UNIX_SOCKET_ALLOCATION_TAG);
  440. if (PathCopy == NULL) {
  441. Status = STATUS_INSUFFICIENT_RESOURCES;
  442. goto UnixSocketBindToAddressEnd;
  443. }
  444. RtlCopyMemory(PathCopy, Path, PathSize);
  445. //
  446. // If the request came from user mode, copy the string.
  447. //
  448. } else {
  449. Status = MmCreateCopyOfUserModeString(Path,
  450. PathSize,
  451. UNIX_SOCKET_ALLOCATION_TAG,
  452. &PathCopy);
  453. if (!KSUCCESS(Status)) {
  454. goto UnixSocketBindToAddressEnd;
  455. }
  456. }
  457. }
  458. //
  459. // If the caller wants an anonymous socket, then just bind it.
  460. //
  461. if ((PathSize == 0) || (PathCopy[0] == '\0')) {
  462. UnixSocket->State = UnixSocketStateBound;
  463. Status = STATUS_SUCCESS;
  464. goto UnixSocketBindToAddressEnd;
  465. }
  466. //
  467. // "Create" a socket at the given path, but use this socket rather than
  468. // actually creating a new one. This opens up a new handle whose path entry
  469. // points to the named object.
  470. //
  471. RtlZeroMemory(&CreationParameters, sizeof(SOCKET_CREATION_PARAMETERS));
  472. CreationParameters.ExistingSocket = Socket;
  473. WalkedPath = PathCopy;
  474. WalkedPathSize = PathSize;
  475. OpenFlags = Handle->OpenFlags | OPEN_FLAG_CREATE | OPEN_FLAG_FAIL_IF_EXISTS;
  476. Status = IopPathWalk(FromKernelMode,
  477. NULL,
  478. &WalkedPath,
  479. &WalkedPathSize,
  480. OpenFlags,
  481. IoObjectSocket,
  482. &CreationParameters,
  483. FileObject->Properties.Permissions,
  484. &PathPoint);
  485. if (!KSUCCESS(Status)) {
  486. if (Status == STATUS_FILE_EXISTS) {
  487. Status = STATUS_ADDRESS_IN_USE;
  488. }
  489. goto UnixSocketBindToAddressEnd;
  490. }
  491. Status = IopCheckPermissions(FromKernelMode,
  492. &PathPoint,
  493. IO_ACCESS_READ | IO_ACCESS_WRITE);
  494. if (!KSUCCESS(Status)) {
  495. goto UnixSocketBindToAddressEnd;
  496. }
  497. //
  498. // Take a reference on the path point before closing the named handle.
  499. //
  500. ASSERT(UnixSocket->PathPoint.PathEntry == NULL);
  501. IO_COPY_PATH_POINT(&(UnixSocket->PathPoint), &PathPoint);
  502. IO_INITIALIZE_PATH_POINT(&PathPoint);
  503. //
  504. // Set the state of the socket to be bound.
  505. //
  506. UnixSocket->Name = PathCopy;
  507. UnixSocket->NameSize = PathSize;
  508. PathCopy = NULL;
  509. UnixSocket->State = UnixSocketStateBound;
  510. Status = STATUS_SUCCESS;
  511. UnixSocketBindToAddressEnd:
  512. KeReleaseQueuedLock(UnixSocket->Lock);
  513. if ((PathCopy != NULL) && (PathCopy != Path)) {
  514. MmFreePagedPool(PathCopy);
  515. }
  516. if (PathPoint.PathEntry != NULL) {
  517. IO_PATH_POINT_RELEASE_REFERENCE(&PathPoint);
  518. }
  519. return Status;
  520. }
  521. KSTATUS
  522. IopUnixSocketListen (
  523. PSOCKET Socket,
  524. ULONG BacklogCount
  525. )
  526. /*++
  527. Routine Description:
  528. This routine adds a bound socket to the list of listening sockets,
  529. officially allowing sockets to attempt to connect to it.
  530. Arguments:
  531. Socket - Supplies a pointer to the socket to mark as listening.
  532. BacklogCount - Supplies the number of attempted connections that can be
  533. queued before additional connections are refused.
  534. Return Value:
  535. Status code.
  536. --*/
  537. {
  538. KSTATUS Status;
  539. PUNIX_SOCKET UnixSocket;
  540. ASSERT(Socket->Domain == NetDomainLocal);
  541. UnixSocket = (PUNIX_SOCKET)Socket;
  542. KeAcquireQueuedLock(UnixSocket->Lock);
  543. //
  544. // Only connection-oriented sockets can listen.
  545. //
  546. if ((Socket->Type != NetSocketStream) &&
  547. (Socket->Type != NetSocketSequencedPacket)) {
  548. Status = STATUS_NOT_SUPPORTED;
  549. goto UnixSocketListenEnd;
  550. }
  551. //
  552. // The socket had better have just been bound and that's it. Allow folks
  553. // that have already called listen to call listen again with a new backlog
  554. // parameter.
  555. //
  556. if ((UnixSocket->State != UnixSocketStateBound) &&
  557. (UnixSocket->State != UnixSocketStateListening)) {
  558. Status = STATUS_INVALID_PARAMETER;
  559. goto UnixSocketListenEnd;
  560. }
  561. UnixSocket->MaxBacklog = BacklogCount;
  562. if (UnixSocket->State != UnixSocketStateListening) {
  563. IoSetIoObjectState(Socket->IoState, POLL_EVENT_IN, FALSE);
  564. IoSetIoObjectState(Socket->IoState, POLL_EVENT_OUT, TRUE);
  565. UnixSocket->State = UnixSocketStateListening;
  566. }
  567. IopUnixSocketInitializeCredentials(UnixSocket);
  568. Status = STATUS_SUCCESS;
  569. UnixSocketListenEnd:
  570. KeReleaseQueuedLock(UnixSocket->Lock);
  571. return Status;
  572. }
  573. KSTATUS
  574. IopUnixSocketAccept (
  575. PSOCKET Socket,
  576. PIO_HANDLE *NewConnectionSocket,
  577. PNETWORK_ADDRESS RemoteAddress,
  578. PSTR *RemotePath,
  579. PUINTN RemotePathSize
  580. )
  581. /*++
  582. Routine Description:
  583. This routine accepts an incoming connection on a listening connection-based
  584. socket.
  585. Arguments:
  586. Socket - Supplies a pointer to the socket to accept a connection from.
  587. NewConnectionSocket - Supplies a pointer where a new socket will be
  588. returned that represents the accepted connection with the remote
  589. host.
  590. RemoteAddress - Supplies a pointer where the address of the connected
  591. remote host will be returned.
  592. RemotePath - Supplies a pointer where a string containing the remote path
  593. will be returned on success. The caller does not own this string, it is
  594. connected with the new socket coming out.
  595. RemotePathSize - Supplies a pointer where the size of the remote path in
  596. bytes will be returned on success.
  597. Return Value:
  598. Status code.
  599. --*/
  600. {
  601. BOOL LockHeld;
  602. PIO_HANDLE NewSocketHandle;
  603. PUNIX_SOCKET NewUnixSocket;
  604. ULONG ReturnedEvents;
  605. KSTATUS Status;
  606. PUNIX_SOCKET UnixSocket;
  607. ASSERT(Socket->Domain == NetDomainLocal);
  608. LockHeld = FALSE;
  609. NewSocketHandle = NULL;
  610. UnixSocket = (PUNIX_SOCKET)Socket;
  611. //
  612. // Only connection-oriented sockets can accept.
  613. //
  614. if ((Socket->Type != NetSocketStream) &&
  615. (Socket->Type != NetSocketSequencedPacket)) {
  616. Status = STATUS_NOT_SUPPORTED;
  617. goto UnixSocketAcceptEnd;
  618. }
  619. //
  620. // Wait for a new connection to come in.
  621. //
  622. while (TRUE) {
  623. //
  624. // Race to acquire the lock and be the one to win the new connection.
  625. //
  626. KeAcquireQueuedLock(UnixSocket->Lock);
  627. LockHeld = TRUE;
  628. //
  629. // The socket had better be listening.
  630. //
  631. if ((UnixSocket->State != UnixSocketStateListening) &&
  632. (UnixSocket->State != UnixSocketStateShutdown)) {
  633. Status = STATUS_INVALID_PARAMETER;
  634. goto UnixSocketAcceptEnd;
  635. }
  636. //
  637. // If there's a connection ready, break out with the lock held and get
  638. // it.
  639. //
  640. if (UnixSocket->CurrentBacklog != 0) {
  641. break;
  642. }
  643. //
  644. // If the socket is shut down, don't wait.
  645. //
  646. if (UnixSocket->State != UnixSocketStateListening) {
  647. Status = STATUS_INVALID_PARAMETER;
  648. goto UnixSocketAcceptEnd;
  649. }
  650. //
  651. // Whoever did win the new connection better have reset the event.
  652. //
  653. ASSERT((Socket->IoState->Events & POLL_EVENT_IN) == 0);
  654. KeReleaseQueuedLock(UnixSocket->Lock);
  655. Status = IoWaitForIoObjectState(Socket->IoState,
  656. POLL_EVENT_IN,
  657. TRUE,
  658. WAIT_TIME_INDEFINITE,
  659. &ReturnedEvents);
  660. if (!KSUCCESS(Status)) {
  661. goto UnixSocketAcceptEnd;
  662. }
  663. ASSERT((ReturnedEvents & POLL_EVENT_IN) != 0);
  664. }
  665. //
  666. // Grab the new server side socket.
  667. //
  668. ASSERT(LIST_EMPTY(&(UnixSocket->ConnectionListEntry)) == FALSE);
  669. NewUnixSocket = LIST_VALUE(UnixSocket->ConnectionListEntry.Next,
  670. UNIX_SOCKET,
  671. ConnectionListEntry);
  672. LIST_REMOVE(&(NewUnixSocket->ConnectionListEntry));
  673. Status = STATUS_SUCCESS;
  674. ASSERT(NewUnixSocket->State == UnixSocketStateConnected);
  675. ASSERT(UnixSocket->CurrentBacklog != 0);
  676. UnixSocket->CurrentBacklog -= 1;
  677. if (UnixSocket->CurrentBacklog < UnixSocket->MaxBacklog) {
  678. IoSetIoObjectState(Socket->IoState, POLL_EVENT_OUT, TRUE);
  679. }
  680. //
  681. // Unsignal the server if that was the last connection.
  682. //
  683. if (LIST_EMPTY(&(UnixSocket->ConnectionListEntry)) != FALSE) {
  684. IoSetIoObjectState(UnixSocket->KernelSocket.IoState,
  685. POLL_EVENT_IN,
  686. FALSE);
  687. }
  688. RtlZeroMemory(RemoteAddress, sizeof(NETWORK_ADDRESS));
  689. RemoteAddress->Domain = NetDomainLocal;
  690. *RemotePath = NewUnixSocket->Remote->Name;
  691. *RemotePathSize = NewUnixSocket->Remote->NameSize;
  692. NewSocketHandle = NewUnixSocket->KernelSocket.IoHandle;
  693. UnixSocketAcceptEnd:
  694. if (LockHeld != FALSE) {
  695. KeReleaseQueuedLock(UnixSocket->Lock);
  696. }
  697. if (!KSUCCESS(Status)) {
  698. NewSocketHandle = NULL;
  699. }
  700. *NewConnectionSocket = NewSocketHandle;
  701. return Status;
  702. }
  703. KSTATUS
  704. IopUnixSocketConnect (
  705. BOOL FromKernelMode,
  706. PSOCKET Socket,
  707. PNETWORK_ADDRESS Address,
  708. PSTR RemotePath,
  709. UINTN RemotePathSize
  710. )
  711. /*++
  712. Routine Description:
  713. This routine attempts to make an outgoing connection to a server.
  714. Arguments:
  715. FromKernelMode - Supplies a boolean indicating if the request is coming
  716. from kernel mode (TRUE) or user mode (FALSE).
  717. Socket - Supplies a pointer to the socket to use for the connection.
  718. Address - Supplies a pointer to the address to connect to.
  719. RemotePath - Supplies a pointer to the string containing the path to
  720. connect to.
  721. RemotePathSize - Supplies the size fo the remote path string in bytes,
  722. including the null terminator.
  723. Return Value:
  724. Status code.
  725. --*/
  726. {
  727. PFILE_OBJECT FileObject;
  728. PSOCKET NewSocket;
  729. PIO_HANDLE NewSocketHandle;
  730. PUNIX_SOCKET NewUnixSocket;
  731. ULONG OpenFlags;
  732. PATH_POINT PathPoint;
  733. ULONG ReturnedEvents;
  734. BOOL ServerLockHeld;
  735. PSOCKET ServerSocket;
  736. PUNIX_SOCKET ServerUnixSocket;
  737. KSTATUS Status;
  738. PUNIX_SOCKET UnixSocket;
  739. PSTR WalkedPath;
  740. ULONG WalkedPathSize;
  741. NewSocketHandle = NULL;
  742. IO_INITIALIZE_PATH_POINT(&PathPoint);
  743. ServerLockHeld = FALSE;
  744. ServerUnixSocket = NULL;
  745. UnixSocket = (PUNIX_SOCKET)Socket;
  746. KeAcquireQueuedLock(UnixSocket->Lock);
  747. if (Address->Domain != NetDomainLocal) {
  748. Status = STATUS_UNEXPECTED_TYPE;
  749. goto UnixSocketConnectEnd;
  750. }
  751. if ((Socket->Type != NetSocketStream) &&
  752. (Socket->Type != NetSocketSequencedPacket) &&
  753. (Socket->Type != NetSocketDatagram)) {
  754. Status = STATUS_INVALID_PARAMETER;
  755. goto UnixSocketConnectEnd;
  756. }
  757. if (RemotePathSize == 0) {
  758. Status = STATUS_INVALID_PARAMETER;
  759. goto UnixSocketConnectEnd;
  760. }
  761. if (UnixSocket->State == UnixSocketStateConnected) {
  762. Status = STATUS_CONNECTION_EXISTS;
  763. goto UnixSocketConnectEnd;
  764. }
  765. if ((UnixSocket->State != UnixSocketStateInitialized) &&
  766. (UnixSocket->State != UnixSocketStateBound)) {
  767. Status = STATUS_INVALID_PARAMETER;
  768. goto UnixSocketConnectEnd;
  769. }
  770. //
  771. // Attempt to open a handle to the socket.
  772. //
  773. ASSERT((PVOID)RemotePath >= KERNEL_VA_START);
  774. WalkedPath = RemotePath;
  775. WalkedPathSize = RemotePathSize;
  776. Status = IopPathWalk(FromKernelMode,
  777. NULL,
  778. &WalkedPath,
  779. &WalkedPathSize,
  780. 0,
  781. IoObjectInvalid,
  782. NULL,
  783. FILE_PERMISSION_NONE,
  784. &PathPoint);
  785. if (!KSUCCESS(Status)) {
  786. goto UnixSocketConnectEnd;
  787. }
  788. Status = IopCheckPermissions(FromKernelMode,
  789. &PathPoint,
  790. IO_ACCESS_READ | IO_ACCESS_WRITE);
  791. if (!KSUCCESS(Status)) {
  792. goto UnixSocketConnectEnd;
  793. }
  794. //
  795. // Get the socket from the file object.
  796. //
  797. FileObject = PathPoint.PathEntry->FileObject;
  798. if (FileObject->Properties.Type != IoObjectSocket) {
  799. Status = STATUS_NOT_A_SOCKET;
  800. goto UnixSocketConnectEnd;
  801. }
  802. ServerSocket = FileObject->SpecialIo;
  803. ASSERT(ServerSocket->Domain == NetDomainLocal);
  804. ServerUnixSocket = (PUNIX_SOCKET)ServerSocket;
  805. //
  806. // Fail if the types disagree.
  807. //
  808. if (ServerSocket->Type != Socket->Type) {
  809. Status = STATUS_INVALID_ADDRESS;
  810. goto UnixSocketConnectEnd;
  811. }
  812. //
  813. // For datagram sockets, just set it as the remote and go on.
  814. //
  815. if (Socket->Type == NetSocketDatagram) {
  816. UnixSocket->Remote = ServerUnixSocket;
  817. //
  818. // For connection-based sockets, really connect the two.
  819. //
  820. } else {
  821. //
  822. // Stream sockets are not allowed to be both the server and the client.
  823. // Fail if it's the same socket. The socket's state should not be
  824. // listening, but special case it here by comparing the sockets to
  825. // prevent the attempt to reacquire the lock.
  826. //
  827. if (ServerSocket == Socket) {
  828. ASSERT(ServerUnixSocket->State != UnixSocketStateListening);
  829. Status = STATUS_CONNECTION_CLOSED;
  830. goto UnixSocketConnectEnd;
  831. }
  832. //
  833. // Loop until the lock is held and there's space for a new connection.
  834. //
  835. OpenFlags = IoGetIoHandleOpenFlags(Socket->IoHandle);
  836. while (TRUE) {
  837. KeAcquireQueuedLock(ServerUnixSocket->Lock);
  838. ServerLockHeld = TRUE;
  839. if (ServerUnixSocket->State != UnixSocketStateListening) {
  840. Status = STATUS_CONNECTION_CLOSED;
  841. goto UnixSocketConnectEnd;
  842. }
  843. if (ServerUnixSocket->CurrentBacklog >=
  844. ServerUnixSocket->MaxBacklog) {
  845. ASSERT((ServerSocket->IoState->Events & POLL_EVENT_OUT) == 0);
  846. KeReleaseQueuedLock(ServerUnixSocket->Lock);
  847. ServerLockHeld = FALSE;
  848. //
  849. // If it was opened non-blocking, then return immediately.
  850. //
  851. if ((OpenFlags & OPEN_FLAG_NON_BLOCKING) != 0) {
  852. Status = STATUS_OPERATION_WOULD_BLOCK;
  853. goto UnixSocketConnectEnd;
  854. }
  855. Status = IoWaitForIoObjectState(ServerSocket->IoState,
  856. POLL_EVENT_OUT,
  857. TRUE,
  858. WAIT_TIME_INDEFINITE,
  859. &ReturnedEvents);
  860. if (!KSUCCESS(Status)) {
  861. goto UnixSocketConnectEnd;
  862. }
  863. //
  864. // The lock is held and there's space.
  865. //
  866. } else {
  867. break;
  868. }
  869. }
  870. //
  871. // The server's lock is held. Create a new socket on the server side to
  872. // represent this connection. Creating the server's socket in connect
  873. // allows the connection to be fully established when this routine
  874. // returns, even if the accept call hasn't happened yet. This is in
  875. // line with behavior of other systems.
  876. //
  877. Status = IoSocketCreate(Socket->Domain,
  878. Socket->Type,
  879. Socket->Protocol,
  880. 0,
  881. &NewSocketHandle);
  882. if (!KSUCCESS(Status)) {
  883. goto UnixSocketConnectEnd;
  884. }
  885. Status = IoGetSocketFromHandle(NewSocketHandle, &NewSocket);
  886. if (!KSUCCESS(Status)) {
  887. goto UnixSocketConnectEnd;
  888. }
  889. ASSERT(NewSocket->Domain == NetDomainLocal);
  890. NewUnixSocket = (PUNIX_SOCKET)NewSocket;
  891. //
  892. // Copy the path.
  893. //
  894. if (ServerUnixSocket->Name != NULL) {
  895. NewUnixSocket->Name = MmAllocatePagedPool(
  896. ServerUnixSocket->NameSize,
  897. UNIX_SOCKET_ALLOCATION_TAG);
  898. if (NewUnixSocket->Name == NULL) {
  899. Status = STATUS_INSUFFICIENT_RESOURCES;
  900. goto UnixSocketConnectEnd;
  901. }
  902. NewUnixSocket->NameSize = ServerUnixSocket->NameSize;
  903. RtlCopyMemory(NewUnixSocket->Name,
  904. ServerUnixSocket->Name,
  905. NewUnixSocket->NameSize);
  906. }
  907. ASSERT(ServerUnixSocket->Credentials.ProcessId != -1);
  908. RtlCopyMemory(&(NewUnixSocket->Credentials),
  909. &(ServerUnixSocket->Credentials),
  910. sizeof(UNIX_SOCKET_CREDENTIALS));
  911. //
  912. // Wire the two sockets together in a connection.
  913. //
  914. ASSERT(ServerUnixSocket->CurrentBacklog < ServerUnixSocket->MaxBacklog);
  915. IoSetIoObjectState(NewUnixSocket->KernelSocket.IoState,
  916. POLL_EVENT_IN | POLL_EVENT_OUT,
  917. TRUE);
  918. UnixSocket->Remote = NewUnixSocket;
  919. IoSocketAddReference(&(NewUnixSocket->KernelSocket));
  920. NewUnixSocket->Remote = UnixSocket;
  921. IoSocketAddReference(&(UnixSocket->KernelSocket));
  922. UnixSocket->State = UnixSocketStateConnected;
  923. NewUnixSocket->State = UnixSocketStateConnected;
  924. INSERT_BEFORE(&(NewUnixSocket->ConnectionListEntry),
  925. &(ServerUnixSocket->ConnectionListEntry));
  926. if (ServerUnixSocket->CurrentBacklog == 0) {
  927. IoSetIoObjectState(ServerSocket->IoState, POLL_EVENT_IN, TRUE);
  928. }
  929. ServerUnixSocket->CurrentBacklog += 1;
  930. KeReleaseQueuedLock(ServerUnixSocket->Lock);
  931. ServerLockHeld = FALSE;
  932. }
  933. IopUnixSocketInitializeCredentials(UnixSocket);
  934. Status = STATUS_SUCCESS;
  935. UnixSocketConnectEnd:
  936. KeReleaseQueuedLock(UnixSocket->Lock);
  937. if (PathPoint.PathEntry != NULL) {
  938. IO_PATH_POINT_RELEASE_REFERENCE(&PathPoint);
  939. }
  940. if (ServerLockHeld != FALSE) {
  941. KeReleaseQueuedLock(ServerUnixSocket->Lock);
  942. }
  943. return Status;
  944. }
  945. KSTATUS
  946. IopUnixSocketSendData (
  947. BOOL FromKernelMode,
  948. PSOCKET Socket,
  949. PSOCKET_IO_PARAMETERS Parameters,
  950. PIO_BUFFER IoBuffer
  951. )
  952. /*++
  953. Routine Description:
  954. This routine sends the given data buffer through the local socket.
  955. Arguments:
  956. FromKernelMode - Supplies a boolean indicating if the request is coming
  957. from kernel mode or user mode. This value affects the root path node
  958. to traverse for local domain sockets.
  959. Socket - Supplies a pointer to the socket to send the data to.
  960. Parameters - Supplies a pointer to the I/O parameters.
  961. IoBuffer - Supplies a pointer to the I/O buffer containing the data to
  962. send.
  963. Return Value:
  964. Status code.
  965. --*/
  966. {
  967. UINTN BytesCompleted;
  968. PNETWORK_ADDRESS Destination;
  969. NETWORK_ADDRESS DestinationLocal;
  970. PFILE_OBJECT FileObject;
  971. ULONG OpenFlags;
  972. PUNIX_SOCKET_PACKET Packet;
  973. UINTN PacketSize;
  974. PATH_POINT PathPoint;
  975. PKPROCESS Process;
  976. PSTR RemoteCopy;
  977. PSTR RemotePath;
  978. PSOCKET RemoteSocket;
  979. PUNIX_SOCKET RemoteUnixSocket;
  980. ULONG ReturnedEvents;
  981. UINTN Size;
  982. KSTATUS Status;
  983. PKTHREAD Thread;
  984. PUNIX_SOCKET UnixSocket;
  985. BOOL UnixSocketLockHeld;
  986. PSTR WalkedPath;
  987. UINTN WalkedPathSize;
  988. BytesCompleted = 0;
  989. Packet = NULL;
  990. IO_INITIALIZE_PATH_POINT(&PathPoint);
  991. RemoteCopy = NULL;
  992. UnixSocket = (PUNIX_SOCKET)Socket;
  993. KeAcquireQueuedLock(UnixSocket->Lock);
  994. UnixSocketLockHeld = TRUE;
  995. //
  996. // Make sure the socket is properly connected (or as connected as it needs
  997. // to be).
  998. //
  999. Status = IopUnixSocketEnsureConnected(UnixSocket, TRUE);
  1000. if (!KSUCCESS(Status)) {
  1001. goto UnixSocketSendDataEnd;
  1002. }
  1003. //
  1004. // Get or open the remote socket being sent to.
  1005. //
  1006. RemoteUnixSocket = UnixSocket->Remote;
  1007. Destination = Parameters->NetworkAddress;
  1008. if ((Destination != NULL) && (FromKernelMode == FALSE)) {
  1009. Status = MmCopyFromUserMode(&DestinationLocal,
  1010. Destination,
  1011. sizeof(NETWORK_ADDRESS));
  1012. Destination = &DestinationLocal;
  1013. if (!KSUCCESS(Status)) {
  1014. goto UnixSocketSendDataEnd;
  1015. }
  1016. }
  1017. if ((Destination != NULL) &&
  1018. (Destination->Domain != NetDomainInvalid)) {
  1019. if (UnixSocket->KernelSocket.Type != NetSocketDatagram) {
  1020. Status = STATUS_NOT_SUPPORTED;
  1021. goto UnixSocketSendDataEnd;
  1022. }
  1023. if (Destination->Domain != NetDomainLocal) {
  1024. Status = STATUS_UNEXPECTED_TYPE;
  1025. goto UnixSocketSendDataEnd;
  1026. }
  1027. if (Parameters->RemotePathSize == 0) {
  1028. Status = STATUS_INVALID_PARAMETER;
  1029. goto UnixSocketSendDataEnd;
  1030. }
  1031. RemotePath = Parameters->RemotePath;
  1032. if (FromKernelMode == FALSE) {
  1033. Status = MmCreateCopyOfUserModeString(RemotePath,
  1034. Parameters->RemotePathSize,
  1035. UNIX_SOCKET_ALLOCATION_TAG,
  1036. &RemoteCopy);
  1037. RemotePath = RemoteCopy;
  1038. if (!KSUCCESS(Status)) {
  1039. goto UnixSocketSendDataEnd;
  1040. }
  1041. }
  1042. ASSERT((PVOID)RemotePath >= KERNEL_VA_START);
  1043. WalkedPath = RemotePath;
  1044. WalkedPathSize = Parameters->RemotePathSize;
  1045. Status = IopPathWalk(FromKernelMode,
  1046. NULL,
  1047. &WalkedPath,
  1048. &WalkedPathSize,
  1049. 0,
  1050. IoObjectInvalid,
  1051. NULL,
  1052. FILE_PERMISSION_NONE,
  1053. &PathPoint);
  1054. if (!KSUCCESS(Status)) {
  1055. goto UnixSocketSendDataEnd;
  1056. }
  1057. Status = IopCheckPermissions(FromKernelMode,
  1058. &PathPoint,
  1059. IO_ACCESS_READ | IO_ACCESS_WRITE);
  1060. if (!KSUCCESS(Status)) {
  1061. goto UnixSocketSendDataEnd;
  1062. }
  1063. //
  1064. // Get the socket from the file object.
  1065. //
  1066. FileObject = PathPoint.PathEntry->FileObject;
  1067. if (FileObject->Properties.Type != IoObjectSocket) {
  1068. return STATUS_NOT_A_SOCKET;
  1069. }
  1070. ASSERT((UINTN)(FileObject->Properties.DeviceId) ==
  1071. OBJECT_MANAGER_DEVICE_ID);
  1072. RemoteSocket = (PSOCKET)(UINTN)(FileObject->Properties.FileId);
  1073. ASSERT(RemoteSocket->Domain == NetDomainLocal);
  1074. RemoteUnixSocket = (PUNIX_SOCKET)RemoteSocket;
  1075. }
  1076. if (RemoteUnixSocket == NULL) {
  1077. Status = STATUS_NOT_CONNECTED;
  1078. goto UnixSocketSendDataEnd;
  1079. }
  1080. OpenFlags = IoGetIoHandleOpenFlags(Socket->IoHandle);
  1081. //
  1082. // Loop while there's data to send.
  1083. //
  1084. Size = Parameters->Size;
  1085. while (Size != 0) {
  1086. if (UnixSocketLockHeld == FALSE) {
  1087. KeAcquireQueuedLock(UnixSocket->Lock);
  1088. UnixSocketLockHeld = TRUE;
  1089. }
  1090. //
  1091. // Make sure a close didn't sneak in while the lock was not held.
  1092. //
  1093. Status = IopUnixSocketEnsureConnected(UnixSocket, TRUE);
  1094. if (!KSUCCESS(Status)) {
  1095. goto UnixSocketSendDataEnd;
  1096. }
  1097. //
  1098. // For types where the message boundaries matter, the size must fit in
  1099. // a single packet.
  1100. //
  1101. if ((Socket->Type == NetSocketDatagram) ||
  1102. (Socket->Type == NetSocketSequencedPacket)) {
  1103. if (Size > UnixSocket->SendListMax) {
  1104. Status = STATUS_MESSAGE_TOO_LONG;
  1105. goto UnixSocketSendDataEnd;
  1106. }
  1107. }
  1108. if (UnixSocket->SendListSize >= UnixSocket->SendListMax) {
  1109. PacketSize = 0;
  1110. } else {
  1111. PacketSize = UnixSocket->SendListMax - UnixSocket->SendListSize;
  1112. }
  1113. if (PacketSize > Size) {
  1114. PacketSize = Size;
  1115. }
  1116. //
  1117. // If the whole packet needs to be sent in one go, block to wait for
  1118. // more space to free up, and try again.
  1119. //
  1120. if ((Socket->Type == NetSocketDatagram) ||
  1121. (Socket->Type == NetSocketSequencedPacket)) {
  1122. if (Size > PacketSize) {
  1123. PacketSize = 0;
  1124. }
  1125. //
  1126. // Streams can send multiple packets at a time.
  1127. //
  1128. } else {
  1129. ASSERT(Socket->Type == NetSocketStream);
  1130. }
  1131. //
  1132. // Create the packet.
  1133. //
  1134. Packet = NULL;
  1135. if (PacketSize != 0) {
  1136. Packet = NULL;
  1137. Status = IopUnixSocketCreatePacket(UnixSocket,
  1138. IoBuffer,
  1139. BytesCompleted,
  1140. PacketSize,
  1141. &Packet);
  1142. if (!KSUCCESS(Status)) {
  1143. goto UnixSocketSendDataEnd;
  1144. }
  1145. //
  1146. // Charge the socket for the data while the lock is still held.
  1147. //
  1148. UnixSocket->SendListSize += PacketSize;
  1149. if (UnixSocket->SendListSize >= UnixSocket->SendListMax) {
  1150. IoSetIoObjectState(Socket->IoState, POLL_EVENT_OUT, FALSE);
  1151. }
  1152. if ((Parameters->ControlData != NULL) &&
  1153. (Parameters->ControlDataSize != 0)) {
  1154. Status = IopUnixSocketSendControlData(
  1155. FromKernelMode,
  1156. UnixSocket,
  1157. Packet,
  1158. Parameters->ControlData,
  1159. Parameters->ControlDataSize);
  1160. if (!KSUCCESS(Status)) {
  1161. goto UnixSocketSendDataEnd;
  1162. }
  1163. }
  1164. //
  1165. // Send the credentials if either side has that option set.
  1166. //
  1167. if ((Packet->Credentials.ProcessId == -1) &&
  1168. (((UnixSocket->Flags | RemoteUnixSocket->Flags) &
  1169. UNIX_SOCKET_FLAG_SEND_CREDENTIALS) != 0)) {
  1170. Thread = KeGetCurrentThread();
  1171. Process = Thread->OwningProcess;
  1172. Packet->Credentials.ProcessId = Process->Identifiers.ProcessId;
  1173. Packet->Credentials.UserId = Thread->Identity.RealUserId;
  1174. Packet->Credentials.GroupId = Thread->Identity.RealGroupId;
  1175. }
  1176. //
  1177. // The packet doesn't fit, so block until data is flushed out.
  1178. //
  1179. } else {
  1180. IoSetIoObjectState(Socket->IoState, POLL_EVENT_OUT, FALSE);
  1181. }
  1182. KeReleaseQueuedLock(UnixSocket->Lock);
  1183. UnixSocketLockHeld = FALSE;
  1184. //
  1185. // If no packet was created, wait for some space to open up.
  1186. //
  1187. if (Packet == NULL) {
  1188. if ((OpenFlags & OPEN_FLAG_NON_BLOCKING) != 0) {
  1189. Status = STATUS_OPERATION_WOULD_BLOCK;
  1190. goto UnixSocketSendDataEnd;
  1191. }
  1192. Status = IoWaitForIoObjectState(Socket->IoState,
  1193. POLL_EVENT_OUT,
  1194. TRUE,
  1195. Parameters->TimeoutInMilliseconds,
  1196. &ReturnedEvents);
  1197. if (!KSUCCESS(Status)) {
  1198. goto UnixSocketSendDataEnd;
  1199. }
  1200. //
  1201. // Try again to send some data.
  1202. //
  1203. continue;
  1204. }
  1205. //
  1206. // Both locks should not be held at once because it could create lock
  1207. // ordering issues.
  1208. //
  1209. ASSERT(UnixSocketLockHeld == FALSE);
  1210. KeAcquireQueuedLock(RemoteUnixSocket->Lock);
  1211. if (RemoteUnixSocket->KernelSocket.Type != Socket->Type) {
  1212. KeReleaseQueuedLock(RemoteUnixSocket->Lock);
  1213. Status = STATUS_UNEXPECTED_TYPE;
  1214. goto UnixSocketSendDataEnd;
  1215. }
  1216. //
  1217. // Make sure the server is connected.
  1218. //
  1219. Status = IopUnixSocketEnsureConnected(RemoteUnixSocket, FALSE);
  1220. if (!KSUCCESS(Status)) {
  1221. Status = STATUS_BROKEN_PIPE;
  1222. KeReleaseQueuedLock(RemoteUnixSocket->Lock);
  1223. goto UnixSocketSendDataEnd;
  1224. }
  1225. INSERT_BEFORE(&(Packet->ListEntry), &(RemoteUnixSocket->ReceiveList));
  1226. //
  1227. // If this is the only item on the list, signal the remote socket.
  1228. //
  1229. if (Packet->ListEntry.Previous == &(RemoteUnixSocket->ReceiveList)) {
  1230. IoSetIoObjectState(RemoteUnixSocket->KernelSocket.IoState,
  1231. POLL_EVENT_IN,
  1232. TRUE);
  1233. }
  1234. KeReleaseQueuedLock(RemoteUnixSocket->Lock);
  1235. Packet = NULL;
  1236. BytesCompleted += PacketSize;
  1237. Size -= PacketSize;
  1238. }
  1239. UnixSocketSendDataEnd:
  1240. if (RemoteCopy != NULL) {
  1241. MmFreePagedPool(RemoteCopy);
  1242. }
  1243. if (!KSUCCESS(Status)) {
  1244. //
  1245. // Roll back the charge to the socket if the packet is still around.
  1246. //
  1247. if (Packet != NULL) {
  1248. if (UnixSocketLockHeld == FALSE) {
  1249. KeAcquireQueuedLock(UnixSocket->Lock);
  1250. UnixSocketLockHeld = TRUE;
  1251. }
  1252. ASSERT(UnixSocket->SendListSize >= Packet->Length);
  1253. UnixSocket->SendListSize -= Packet->Length;
  1254. if (UnixSocket->SendListSize < UnixSocket->SendListMax) {
  1255. IoSetIoObjectState(Socket->IoState, POLL_EVENT_OUT, TRUE);
  1256. }
  1257. IopUnixSocketDestroyPacket(Packet);
  1258. }
  1259. }
  1260. if (UnixSocketLockHeld != FALSE) {
  1261. KeReleaseQueuedLock(UnixSocket->Lock);
  1262. }
  1263. if (PathPoint.PathEntry != NULL) {
  1264. IO_PATH_POINT_RELEASE_REFERENCE(&PathPoint);
  1265. }
  1266. Parameters->Size = BytesCompleted;
  1267. return Status;
  1268. }
  1269. KSTATUS
  1270. IopUnixSocketReceiveData (
  1271. BOOL FromKernelMode,
  1272. PSOCKET Socket,
  1273. PSOCKET_IO_PARAMETERS Parameters,
  1274. PIO_BUFFER IoBuffer
  1275. )
  1276. /*++
  1277. Routine Description:
  1278. This routine is called by the user to receive data from the socket.
  1279. Arguments:
  1280. FromKernelMode - Supplies a boolean indicating if the request is coming
  1281. from kernel mode or user mode. This value affects the root path node
  1282. to traverse for local domain sockets.
  1283. Socket - Supplies a pointer to the socket to receive data from.
  1284. Parameters - Supplies a pointer to the socket I/O parameters.
  1285. IoBuffer - Supplies a pointer to the I/O buffer where the received data
  1286. will be returned.
  1287. Return Value:
  1288. Status code.
  1289. --*/
  1290. {
  1291. UINTN ByteCount;
  1292. UINTN BytesReceived;
  1293. PUNIX_SOCKET FirstSender;
  1294. ULONG OpenFlags;
  1295. PUNIX_SOCKET_PACKET Packet;
  1296. PUNIX_SOCKET Remote;
  1297. NETWORK_ADDRESS RemoteAddressLocal;
  1298. ULONG ReturnedEvents;
  1299. UINTN SenderCopySize;
  1300. UINTN Size;
  1301. KSTATUS Status;
  1302. PUNIX_SOCKET UnixSocket;
  1303. BOOL UnixSocketLockHeld;
  1304. BytesReceived = 0;
  1305. FirstSender = NULL;
  1306. Size = Parameters->Size;
  1307. UnixSocket = (PUNIX_SOCKET)Socket;
  1308. UnixSocketLockHeld = FALSE;
  1309. ASSERT(Socket->Domain == NetDomainLocal);
  1310. //
  1311. // Loop reading stuff.
  1312. //
  1313. OpenFlags = IoGetIoHandleOpenFlags(Socket->IoHandle);
  1314. while (Size != 0) {
  1315. if (UnixSocketLockHeld == FALSE) {
  1316. KeAcquireQueuedLock(UnixSocket->Lock);
  1317. UnixSocketLockHeld = TRUE;
  1318. }
  1319. Status = IopUnixSocketEnsureConnected(UnixSocket, FALSE);
  1320. if (!KSUCCESS(Status)) {
  1321. goto UnixSocketReceiveDataEnd;
  1322. }
  1323. //
  1324. // If the list is empty, wait and try again.
  1325. //
  1326. if (LIST_EMPTY(&(UnixSocket->ReceiveList)) != FALSE) {
  1327. IoSetIoObjectState(Socket->IoState, POLL_EVENT_IN, FALSE);
  1328. //
  1329. // If something was retrieved already, just use that.
  1330. //
  1331. if (BytesReceived != 0) {
  1332. break;
  1333. }
  1334. //
  1335. // If this is a connection oriented socket and the remote is shut
  1336. // down for writing, end now.
  1337. //
  1338. if ((Socket->Type == NetSocketStream) ||
  1339. (Socket->Type == NetSocketSequencedPacket)) {
  1340. Remote = UnixSocket->Remote;
  1341. if ((Remote != NULL) &&
  1342. (Remote->State != UnixSocketStateConnected) &&
  1343. (Remote->State != UnixSocketStateShutdownRead)) {
  1344. Status = STATUS_END_OF_FILE;
  1345. goto UnixSocketReceiveDataEnd;
  1346. }
  1347. }
  1348. if ((OpenFlags & OPEN_FLAG_NON_BLOCKING) != 0) {
  1349. Status = STATUS_OPERATION_WOULD_BLOCK;
  1350. goto UnixSocketReceiveDataEnd;
  1351. }
  1352. KeReleaseQueuedLock(UnixSocket->Lock);
  1353. UnixSocketLockHeld = FALSE;
  1354. Status = IoWaitForIoObjectState(Socket->IoState,
  1355. POLL_EVENT_IN,
  1356. TRUE,
  1357. Parameters->TimeoutInMilliseconds,
  1358. &ReturnedEvents);
  1359. if (!KSUCCESS(Status)) {
  1360. goto UnixSocketReceiveDataEnd;
  1361. }
  1362. continue;
  1363. //
  1364. // Grab stuff off the list.
  1365. //
  1366. } else {
  1367. Packet = LIST_VALUE(UnixSocket->ReceiveList.Next,
  1368. UNIX_SOCKET_PACKET,
  1369. ListEntry);
  1370. //
  1371. // Don't cross boundaries of different senders or packets with
  1372. // control data.
  1373. //
  1374. if (FirstSender != NULL) {
  1375. if ((Packet->Sender != FirstSender) ||
  1376. (Packet->Credentials.ProcessId != -1) ||
  1377. (Packet->Credentials.UserId != -1) ||
  1378. (Packet->Credentials.GroupId != -1) ||
  1379. (Packet->HandleCount != 0)) {
  1380. break;
  1381. }
  1382. }
  1383. FirstSender = Packet->Sender;
  1384. ByteCount = Packet->Length - Packet->Offset;
  1385. if (ByteCount > Size) {
  1386. ByteCount = Size;
  1387. }
  1388. Status = MmCopyIoBufferData(IoBuffer,
  1389. Packet->Data + Packet->Offset,
  1390. BytesReceived,
  1391. ByteCount,
  1392. TRUE);
  1393. if (!KSUCCESS(Status)) {
  1394. goto UnixSocketReceiveDataEnd;
  1395. }
  1396. Packet->Offset += ByteCount;
  1397. BytesReceived += ByteCount;
  1398. Size -= ByteCount;
  1399. //
  1400. // Copy the ancillary data as well.
  1401. //
  1402. Status = IopUnixSocketReceiveControlData(FromKernelMode,
  1403. UnixSocket,
  1404. Packet,
  1405. Parameters);
  1406. if (!KSUCCESS(Status)) {
  1407. goto UnixSocketReceiveDataEnd;
  1408. }
  1409. //
  1410. // Return the remote path if requested.
  1411. //
  1412. if ((Parameters->RemotePath != NULL) &&
  1413. (Parameters->RemotePathSize != 0)) {
  1414. SenderCopySize = Packet->Sender->NameSize;
  1415. if (SenderCopySize > Parameters->RemotePathSize) {
  1416. SenderCopySize = Parameters->RemotePathSize;
  1417. }
  1418. Parameters->RemotePathSize = Packet->Sender->NameSize;
  1419. if (SenderCopySize != 0) {
  1420. if (FromKernelMode != FALSE) {
  1421. RtlCopyMemory(Parameters->RemotePath,
  1422. Packet->Sender->Name,
  1423. SenderCopySize);
  1424. } else {
  1425. Status = MmCopyToUserMode(Parameters->RemotePath,
  1426. Packet->Sender->Name,
  1427. SenderCopySize);
  1428. if (!KSUCCESS(Status)) {
  1429. goto UnixSocketReceiveDataEnd;
  1430. }
  1431. }
  1432. }
  1433. }
  1434. //
  1435. // Copy the network address portion of the sender address as well.
  1436. //
  1437. if (Parameters->NetworkAddress != NULL) {
  1438. if (FromKernelMode != FALSE) {
  1439. Parameters->NetworkAddress->Domain = NetDomainLocal;
  1440. } else {
  1441. RtlZeroMemory(&RemoteAddressLocal, sizeof(NETWORK_ADDRESS));
  1442. RemoteAddressLocal.Domain = NetDomainLocal;
  1443. Status = MmCopyToUserMode(Parameters->NetworkAddress,
  1444. &RemoteAddressLocal,
  1445. sizeof(NETWORK_ADDRESS));
  1446. if (!KSUCCESS(Status)) {
  1447. goto UnixSocketReceiveDataEnd;
  1448. }
  1449. }
  1450. }
  1451. //
  1452. // If the packet was completely consumed or this is datagram mode,
  1453. // destroy the packet.
  1454. //
  1455. if ((Packet->Offset >= Packet->Length) ||
  1456. (Socket->Type == NetSocketDatagram)) {
  1457. LIST_REMOVE(&(Packet->ListEntry));
  1458. if (LIST_EMPTY(&(UnixSocket->ReceiveList)) != FALSE) {
  1459. IoSetIoObjectState(Socket->IoState, POLL_EVENT_IN, FALSE);
  1460. }
  1461. //
  1462. // Release the sender if needed. Release the lock first so that
  1463. // both locks are not held at once, which could cause lock
  1464. // ordering problems.
  1465. //
  1466. KeReleaseQueuedLock(UnixSocket->Lock);
  1467. UnixSocketLockHeld = FALSE;
  1468. KeAcquireQueuedLock(Packet->Sender->Lock);
  1469. ASSERT(Packet->Sender->SendListSize >= Packet->Length);
  1470. IoSetIoObjectState(Packet->Sender->KernelSocket.IoState,
  1471. POLL_EVENT_OUT,
  1472. TRUE);
  1473. Packet->Sender->SendListSize -= Packet->Length;
  1474. KeReleaseQueuedLock(Packet->Sender->Lock);
  1475. //
  1476. // Destroy the sender's packet.
  1477. //
  1478. IopUnixSocketDestroyPacket(Packet);
  1479. }
  1480. //
  1481. // For datagram or sequenced packet sockets, only return one packet
  1482. // at a time.
  1483. //
  1484. if ((Socket->Type == NetSocketDatagram) ||
  1485. (Socket->Type == NetSocketSequencedPacket)) {
  1486. break;
  1487. }
  1488. }
  1489. }
  1490. Status = STATUS_SUCCESS;
  1491. UnixSocketReceiveDataEnd:
  1492. if (UnixSocketLockHeld != FALSE) {
  1493. KeReleaseQueuedLock(UnixSocket->Lock);
  1494. }
  1495. if ((Status == STATUS_END_OF_FILE) && (BytesReceived != 0)) {
  1496. Status = STATUS_SUCCESS;
  1497. }
  1498. Parameters->Size = BytesReceived;
  1499. return Status;
  1500. }
  1501. KSTATUS
  1502. IopUnixSocketGetSetSocketInformation (
  1503. PSOCKET Socket,
  1504. SOCKET_INFORMATION_TYPE InformationType,
  1505. UINTN Option,
  1506. PVOID Data,
  1507. PUINTN DataSize,
  1508. BOOL Set
  1509. )
  1510. /*++
  1511. Routine Description:
  1512. This routine gets or sets properties of the given socket.
  1513. Arguments:
  1514. Socket - Supplies a pointer to the socket to get or set information for.
  1515. InformationType - Supplies the socket information type category to which
  1516. specified option belongs.
  1517. Option - Supplies the option to get or set, which is specific to the
  1518. information type. The type of this value is generally
  1519. SOCKET_<information_type>_OPTION.
  1520. Data - Supplies a pointer to the data buffer where the data is either
  1521. returned for a get operation or given for a set operation.
  1522. DataSize - Supplies a pointer that on input constains the size of the data
  1523. buffer. On output, this contains the required size of the data buffer.
  1524. Set - Supplies a boolean indicating if this is a get operation (FALSE) or
  1525. a set operation (TRUE).
  1526. Return Value:
  1527. STATUS_SUCCESS on success.
  1528. STATUS_INVALID_PARAMETER if the information type is incorrect.
  1529. STATUS_BUFFER_TOO_SMALL if the data buffer is too small to receive the
  1530. requested option.
  1531. STATUS_NOT_SUPPORTED_BY_PROTOCOL if the socket option is not supported by
  1532. the socket.
  1533. --*/
  1534. {
  1535. NETWORK_ADDRESS Address;
  1536. SOCKET_BASIC_OPTION BasicOption;
  1537. UINTN CopySize;
  1538. ULONG PassCredentials;
  1539. UINTN RemainingSize;
  1540. UINTN RequiredSize;
  1541. UINTN SendListMax;
  1542. PVOID Source;
  1543. KSTATUS Status;
  1544. PUNIX_SOCKET UnixSocket;
  1545. UnixSocket = (PUNIX_SOCKET)Socket;
  1546. ASSERT(Socket->Domain == NetDomainLocal);
  1547. Source = NULL;
  1548. RequiredSize = 0;
  1549. Status = STATUS_SUCCESS;
  1550. switch (InformationType) {
  1551. case SocketInformationBasic:
  1552. BasicOption = (SOCKET_BASIC_OPTION)Option;
  1553. switch (BasicOption) {
  1554. case SocketBasicOptionType:
  1555. if (Set != FALSE) {
  1556. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1557. break;
  1558. }
  1559. Source = &(Socket->Type);
  1560. RequiredSize = sizeof(NET_SOCKET_TYPE);
  1561. break;
  1562. case SocketBasicOptionDomain:
  1563. if (Set != FALSE) {
  1564. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1565. break;
  1566. }
  1567. Source = &(Socket->Domain);
  1568. RequiredSize = sizeof(NET_DOMAIN_TYPE);
  1569. break;
  1570. //
  1571. // Switch to the remote socket and fall through.
  1572. //
  1573. case SocketBasicOptionRemoteAddress:
  1574. UnixSocket = UnixSocket->Remote;
  1575. case SocketBasicOptionLocalAddress:
  1576. if (Set != FALSE) {
  1577. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1578. break;
  1579. }
  1580. if (UnixSocket == NULL) {
  1581. Status = STATUS_NOT_CONNECTED;
  1582. break;
  1583. }
  1584. RtlZeroMemory(&Address, sizeof(NETWORK_ADDRESS));
  1585. Address.Domain = NetDomainLocal;
  1586. KeAcquireQueuedLock(UnixSocket->Lock);
  1587. RequiredSize = sizeof(NETWORK_ADDRESS) + UnixSocket->NameSize;
  1588. if (*DataSize > RequiredSize) {
  1589. *DataSize = RequiredSize;
  1590. }
  1591. RemainingSize = *DataSize;
  1592. CopySize = RemainingSize;
  1593. if (CopySize > sizeof(NETWORK_ADDRESS)) {
  1594. CopySize = sizeof(NETWORK_ADDRESS);
  1595. }
  1596. //
  1597. // The lock must be held while the name is copied, so this cannot
  1598. // be done below.
  1599. //
  1600. RtlCopyMemory(Data, &Address, CopySize);
  1601. RemainingSize -= CopySize;
  1602. if ((RemainingSize != 0) && (UnixSocket->NameSize != 0)) {
  1603. ASSERT(RemainingSize <= UnixSocket->NameSize);
  1604. RtlCopyMemory(Data + CopySize, UnixSocket->Name, RemainingSize);
  1605. }
  1606. KeReleaseQueuedLock(UnixSocket->Lock);
  1607. break;
  1608. case SocketBasicOptionSendBufferSize:
  1609. if ((Set != FALSE) && (*DataSize < sizeof(ULONG))) {
  1610. *DataSize = sizeof(ULONG);
  1611. Status = STATUS_BUFFER_TOO_SMALL;
  1612. break;
  1613. }
  1614. RequiredSize = sizeof(ULONG);
  1615. if (Set != FALSE) {
  1616. SendListMax = *((PULONG)Data);
  1617. if (SendListMax > SOCKET_OPTION_MAX_ULONG) {
  1618. SendListMax = SOCKET_OPTION_MAX_ULONG;
  1619. }
  1620. //
  1621. // TODO: Are there limits to Unix socket buffer sizes?
  1622. //
  1623. KeAcquireQueuedLock(UnixSocket->Lock);
  1624. UnixSocket->SendListMax = SendListMax;
  1625. KeReleaseQueuedLock(UnixSocket->Lock);
  1626. } else {
  1627. Source = &SendListMax;
  1628. SendListMax = UnixSocket->SendListMax;
  1629. }
  1630. break;
  1631. case SocketBasicOptionPassCredentials:
  1632. if ((Set != FALSE) && (*DataSize < sizeof(ULONG))) {
  1633. *DataSize = sizeof(ULONG);
  1634. Status = STATUS_BUFFER_TOO_SMALL;
  1635. break;
  1636. }
  1637. RequiredSize = sizeof(ULONG);
  1638. KeAcquireQueuedLock(UnixSocket->Lock);
  1639. if (Set != FALSE) {
  1640. UnixSocket->Flags &= ~UNIX_SOCKET_FLAG_SEND_CREDENTIALS;
  1641. if (*((PULONG)Data) != FALSE) {
  1642. UnixSocket->Flags |= UNIX_SOCKET_FLAG_SEND_CREDENTIALS;
  1643. }
  1644. } else {
  1645. Source = &PassCredentials;
  1646. PassCredentials = FALSE;
  1647. if ((UnixSocket->Flags &
  1648. UNIX_SOCKET_FLAG_SEND_CREDENTIALS) != 0) {
  1649. PassCredentials = TRUE;
  1650. }
  1651. }
  1652. KeReleaseQueuedLock(UnixSocket->Lock);
  1653. break;
  1654. case SocketBasicOptionPeerCredentials:
  1655. if (Set != FALSE) {
  1656. Status = STATUS_NOT_SUPPORTED_BY_PROTOCOL;
  1657. break;
  1658. }
  1659. Source = &(UnixSocket->Remote->Credentials);
  1660. RequiredSize = sizeof(UNIX_SOCKET_CREDENTIALS);
  1661. break;
  1662. default:
  1663. Status = STATUS_INVALID_PARAMETER;
  1664. break;
  1665. }
  1666. break;
  1667. default:
  1668. Status = STATUS_INVALID_PARAMETER;
  1669. break;
  1670. }
  1671. //
  1672. // Complete the common information processing if this call succeeded.
  1673. //
  1674. if (KSUCCESS(Status)) {
  1675. //
  1676. // Truncate all copies for get requests down to the required size and
  1677. // only return the required size on set requests.
  1678. //
  1679. if (*DataSize > RequiredSize) {
  1680. *DataSize = RequiredSize;
  1681. }
  1682. //
  1683. // For get requests, copy the gathered information to the supplied data
  1684. // buffer.
  1685. //
  1686. if (Set == FALSE) {
  1687. if (Source != NULL) {
  1688. RtlCopyMemory(Data, Source, *DataSize);
  1689. }
  1690. //
  1691. // If the copy truncated the data, report that the given buffer was
  1692. // too small. The caller can choose to ignore this if the truncated
  1693. // data is enough.
  1694. //
  1695. if (*DataSize < RequiredSize) {
  1696. *DataSize = RequiredSize;
  1697. Status = STATUS_BUFFER_TOO_SMALL;
  1698. }
  1699. }
  1700. }
  1701. return Status;
  1702. }
  1703. KSTATUS
  1704. IopUnixSocketShutdown (
  1705. PSOCKET Socket,
  1706. ULONG ShutdownType
  1707. )
  1708. /*++
  1709. Routine Description:
  1710. This routine shuts down communication with a given socket.
  1711. Arguments:
  1712. Socket - Supplies a pointer to the socket.
  1713. ShutdownType - Supplies the shutdown type to perform. See the
  1714. SOCKET_SHUTDOWN_* definitions.
  1715. Return Value:
  1716. Status code.
  1717. --*/
  1718. {
  1719. PUNIX_SOCKET RemoteToRelease;
  1720. PUNIX_SOCKET RemoteToSignal;
  1721. KSTATUS Status;
  1722. PUNIX_SOCKET UnixSocket;
  1723. RemoteToRelease = NULL;
  1724. RemoteToSignal = NULL;
  1725. UnixSocket = (PUNIX_SOCKET)Socket;
  1726. ASSERT(Socket->Domain == NetDomainLocal);
  1727. KeAcquireQueuedLock(UnixSocket->Lock);
  1728. if (UnixSocket->State == UnixSocketStateInitialized) {
  1729. UnixSocket->State = UnixSocketStateShutdown;
  1730. } else if ((UnixSocket->State >= UnixSocketStateBound) &&
  1731. (UnixSocket->State < UnixSocketStateShutdown)) {
  1732. if ((ShutdownType & SOCKET_SHUTDOWN_READ) != 0) {
  1733. //
  1734. // A listening socket can only shut down read, so treat it as a
  1735. // full shutdown.
  1736. //
  1737. if (UnixSocket->State == UnixSocketStateListening) {
  1738. UnixSocket->State = UnixSocketStateShutdown;
  1739. //
  1740. // It might already be shut down for writing.
  1741. //
  1742. } else if (UnixSocket->State == UnixSocketStateShutdownWrite) {
  1743. UnixSocket->State = UnixSocketStateShutdown;
  1744. } else if (UnixSocket->State != UnixSocketStateShutdown) {
  1745. UnixSocket->State = UnixSocketStateShutdownRead;
  1746. }
  1747. IopUnixSocketFlushData(UnixSocket);
  1748. }
  1749. if ((ShutdownType & SOCKET_SHUTDOWN_WRITE) != 0) {
  1750. //
  1751. // Listening sockets can still accept new connections while
  1752. // shutdown for write. Everything else closes.
  1753. //
  1754. if (UnixSocket->State == UnixSocketStateShutdownRead) {
  1755. UnixSocket->State = UnixSocketStateShutdown;
  1756. } else if (UnixSocket->State != UnixSocketStateListening) {
  1757. if (UnixSocket->State != UnixSocketStateShutdown) {
  1758. UnixSocket->State = UnixSocketStateShutdownWrite;
  1759. }
  1760. }
  1761. //
  1762. // If there's a remote connection for a connection-oriented socket,
  1763. // signal it as no more data will be sent.
  1764. //
  1765. if ((Socket->Type == NetSocketStream) ||
  1766. (Socket->Type == NetSocketSequencedPacket)) {
  1767. RemoteToSignal = UnixSocket->Remote;
  1768. }
  1769. }
  1770. //
  1771. // Release the reference on the remote if the socket is completely
  1772. // disconnected.
  1773. //
  1774. if (UnixSocket->State == UnixSocketStateShutdown) {
  1775. RemoteToRelease = UnixSocket->Remote;
  1776. UnixSocket->Remote = NULL;
  1777. }
  1778. }
  1779. KeReleaseQueuedLock(UnixSocket->Lock);
  1780. //
  1781. // Signal the remote outside holding this socket lock to avoid lock
  1782. // ordering problems.
  1783. //
  1784. if (RemoteToSignal != NULL) {
  1785. KeAcquireQueuedLock(RemoteToSignal->Lock);
  1786. IoSetIoObjectState(RemoteToSignal->KernelSocket.IoState,
  1787. POLL_EVENT_IN,
  1788. TRUE);
  1789. KeReleaseQueuedLock(RemoteToSignal->Lock);
  1790. }
  1791. if (RemoteToRelease != NULL) {
  1792. IoSocketReleaseReference(&(RemoteToRelease->KernelSocket));
  1793. }
  1794. Status = STATUS_SUCCESS;
  1795. return Status;
  1796. }
  1797. KSTATUS
  1798. IopUnixSocketClose (
  1799. PSOCKET Socket
  1800. )
  1801. /*++
  1802. Routine Description:
  1803. This routine closes down a local socket.
  1804. Arguments:
  1805. Socket - Supplies a pointer to the socket.
  1806. Return Value:
  1807. Status code.
  1808. --*/
  1809. {
  1810. PUNIX_SOCKET Connection;
  1811. ULONG ShutdownFlags;
  1812. KSTATUS Status;
  1813. PUNIX_SOCKET UnixSocket;
  1814. UnixSocket = (PUNIX_SOCKET)Socket;
  1815. ASSERT(Socket->Domain == NetDomainLocal);
  1816. //
  1817. // Shut the socket down.
  1818. //
  1819. ShutdownFlags = SOCKET_SHUTDOWN_READ | SOCKET_SHUTDOWN_WRITE;
  1820. Status = IopUnixSocketShutdown(Socket, ShutdownFlags);
  1821. if (!KSUCCESS(Status)) {
  1822. return Status;
  1823. }
  1824. KeAcquireQueuedLock(UnixSocket->Lock);
  1825. if (UnixSocket->State == UnixSocketStateClosed) {
  1826. KeReleaseQueuedLock(UnixSocket->Lock);
  1827. return STATUS_SUCCESS;
  1828. }
  1829. //
  1830. // Destroy any incoming connections.
  1831. //
  1832. while (UnixSocket->CurrentBacklog != 0) {
  1833. ASSERT(LIST_EMPTY(&(UnixSocket->ConnectionListEntry)) == FALSE);
  1834. Connection = LIST_VALUE(UnixSocket->ConnectionListEntry.Next,
  1835. UNIX_SOCKET,
  1836. ConnectionListEntry);
  1837. LIST_REMOVE(&(Connection->ConnectionListEntry));
  1838. UnixSocket->CurrentBacklog -= 1;
  1839. IoClose(UnixSocket->KernelSocket.IoHandle);
  1840. }
  1841. //
  1842. // Release the reference on the path entry.
  1843. //
  1844. if (UnixSocket->PathPoint.PathEntry != NULL) {
  1845. IO_PATH_POINT_RELEASE_REFERENCE(&(UnixSocket->PathPoint));
  1846. UnixSocket->PathPoint.PathEntry = NULL;
  1847. }
  1848. ASSERT(UnixSocket->State == UnixSocketStateShutdown);
  1849. UnixSocket->State = UnixSocketStateClosed;
  1850. KeReleaseQueuedLock(UnixSocket->Lock);
  1851. IoSocketReleaseReference(&(UnixSocket->KernelSocket));
  1852. return STATUS_SUCCESS;
  1853. }
  1854. //
  1855. // --------------------------------------------------------- Internal Functions
  1856. //
  1857. KSTATUS
  1858. IopUnixSocketEnsureConnected (
  1859. PUNIX_SOCKET Socket,
  1860. BOOL Write
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. This routine ensures a socket is connected and okay to send data. This
  1865. routine assumes the socket lock is already held.
  1866. Arguments:
  1867. Socket - Supplies a pointer to the socket to check.
  1868. Write - Supplies a boolean indicating if the caller is going to do a write
  1869. operation on the socket (TRUE) or a read operation (FALSE).
  1870. Return Value:
  1871. Status code.
  1872. --*/
  1873. {
  1874. KSTATUS Status;
  1875. Status = STATUS_SUCCESS;
  1876. if (Write != FALSE) {
  1877. if (Socket->State == UnixSocketStateShutdownRead) {
  1878. return STATUS_SUCCESS;
  1879. } else if ((Socket->State == UnixSocketStateShutdownWrite) ||
  1880. (Socket->State == UnixSocketStateShutdown)) {
  1881. return STATUS_BROKEN_PIPE;
  1882. }
  1883. } else {
  1884. if (Socket->State == UnixSocketStateShutdownWrite) {
  1885. return STATUS_SUCCESS;
  1886. } else if ((Socket->State == UnixSocketStateShutdownRead) ||
  1887. (Socket->State == UnixSocketStateShutdown)) {
  1888. return STATUS_END_OF_FILE;
  1889. }
  1890. }
  1891. if (Socket->State != UnixSocketStateConnected) {
  1892. if (Socket->KernelSocket.Type == NetSocketDatagram) {
  1893. if ((Socket->State != UnixSocketStateInitialized) &&
  1894. (Socket->State != UnixSocketStateBound)) {
  1895. Status = STATUS_BROKEN_PIPE;
  1896. }
  1897. } else {
  1898. Status = STATUS_NOT_CONNECTED;
  1899. }
  1900. }
  1901. return Status;
  1902. }
  1903. VOID
  1904. IopUnixSocketFlushData (
  1905. PUNIX_SOCKET Socket
  1906. )
  1907. /*++
  1908. Routine Description:
  1909. This routine flushes all incoming data on the given socket. This routine
  1910. assumes the socket lock is already held.
  1911. Arguments:
  1912. Socket - Supplies a pointer to the socket to flush.
  1913. Return Value:
  1914. Status code.
  1915. --*/
  1916. {
  1917. PUNIX_SOCKET_PACKET Packet;
  1918. while (LIST_EMPTY(&(Socket->ReceiveList)) == FALSE) {
  1919. Packet = LIST_VALUE(Socket->ReceiveList.Next,
  1920. UNIX_SOCKET_PACKET,
  1921. ListEntry);
  1922. LIST_REMOVE(&(Packet->ListEntry));
  1923. KeAcquireQueuedLock(Packet->Sender->Lock);
  1924. ASSERT(Packet->Sender->SendListSize >= Packet->Length);
  1925. IoSetIoObjectState(Packet->Sender->KernelSocket.IoState,
  1926. POLL_EVENT_OUT,
  1927. TRUE);
  1928. Packet->Sender->SendListSize -= Packet->Length;
  1929. KeReleaseQueuedLock(Packet->Sender->Lock);
  1930. IopUnixSocketDestroyPacket(Packet);
  1931. }
  1932. return;
  1933. }
  1934. KSTATUS
  1935. IopUnixSocketCreatePacket (
  1936. PUNIX_SOCKET Sender,
  1937. PIO_BUFFER IoBuffer,
  1938. UINTN Offset,
  1939. UINTN DataSize,
  1940. PUNIX_SOCKET_PACKET *NewPacket
  1941. )
  1942. /*++
  1943. Routine Description:
  1944. This routine creates a socket packet structure, and takes a reference on
  1945. the sender on success.
  1946. Arguments:
  1947. Sender - Supplies a pointer to the socket sending the data.
  1948. IoBuffer - Supplies a pointer to the I/O buffer to base the data on. A
  1949. copy of this data will be made.
  1950. Offset - Supplies the offset from the start of the I/O buffer to copy from.
  1951. DataSize - Supplies the number of bytes to send.
  1952. NewPacket - Supplies a pointer where a pointer to a newly allocated packet
  1953. will be returned on success.
  1954. Return Value:
  1955. Status code.
  1956. --*/
  1957. {
  1958. UINTN AllocationSize;
  1959. PUNIX_SOCKET_PACKET Packet;
  1960. KSTATUS Status;
  1961. AllocationSize = sizeof(UNIX_SOCKET_PACKET) + DataSize;
  1962. Packet = MmAllocatePagedPool(AllocationSize, UNIX_SOCKET_ALLOCATION_TAG);
  1963. if (Packet == NULL) {
  1964. return STATUS_INSUFFICIENT_RESOURCES;
  1965. }
  1966. Packet->Sender = Sender;
  1967. Packet->Data = (PVOID)(Packet + 1);
  1968. Packet->Length = DataSize;
  1969. Packet->Offset = 0;
  1970. Packet->Credentials.ProcessId = -1;
  1971. Packet->Credentials.UserId = -1;
  1972. Packet->Credentials.GroupId = -1;
  1973. Packet->Handles = NULL;
  1974. Packet->HandleCount = 0;
  1975. if (DataSize != 0) {
  1976. Status = MmCopyIoBufferData(IoBuffer,
  1977. Packet->Data,
  1978. Offset,
  1979. DataSize,
  1980. FALSE);
  1981. if (!KSUCCESS(Status)) {
  1982. MmFreePagedPool(Packet);
  1983. return Status;
  1984. }
  1985. }
  1986. IoSocketAddReference(&(Sender->KernelSocket));
  1987. *NewPacket = Packet;
  1988. return STATUS_SUCCESS;;
  1989. }
  1990. VOID
  1991. IopUnixSocketDestroyPacket (
  1992. PUNIX_SOCKET_PACKET Packet
  1993. )
  1994. /*++
  1995. Routine Description:
  1996. This routine destroys a socket packet structure.
  1997. Arguments:
  1998. Packet - Supplies a pointer to the packet to destroy.
  1999. Return Value:
  2000. None.
  2001. --*/
  2002. {
  2003. UINTN Index;
  2004. PIO_HANDLE *IoHandleArray;
  2005. //
  2006. // Release any handles and free the array if present.
  2007. //
  2008. IoHandleArray = Packet->Handles;
  2009. if (IoHandleArray != NULL) {
  2010. for (Index = 0; Index < Packet->HandleCount; Index += 1) {
  2011. IoIoHandleReleaseReference(IoHandleArray[Index]);
  2012. }
  2013. MmFreePagedPool(IoHandleArray);
  2014. }
  2015. IoSocketReleaseReference(&(Packet->Sender->KernelSocket));
  2016. MmFreePagedPool(Packet);
  2017. return;
  2018. }
  2019. KSTATUS
  2020. IopUnixSocketSendControlData (
  2021. BOOL FromKernelMode,
  2022. PUNIX_SOCKET Sender,
  2023. PUNIX_SOCKET_PACKET Packet,
  2024. PVOID ControlData,
  2025. UINTN ControlDataSize
  2026. )
  2027. /*++
  2028. Routine Description:
  2029. This routine parses and attaches ancillary data to a packet.
  2030. Arguments:
  2031. FromKernelMode - Supplies a boolean indicating if the send is originating
  2032. from user mode (FALSE) or kernel mode (TRUE). If user mode, then the
  2033. control data pointer is expected to be a user mode pointer.
  2034. Sender - Supplies a pointer to the socket doing the sending.
  2035. Packet - Supplies a pointer to the packet that will be sent.
  2036. ControlData - Supplies a pointer to the control data.
  2037. ControlDataSize - Supplies the size of the control data.
  2038. Return Value:
  2039. Status code.
  2040. --*/
  2041. {
  2042. UINTN AllocationSize;
  2043. PSOCKET_CONTROL_MESSAGE Control;
  2044. PVOID ControlDataCopy;
  2045. PUNIX_SOCKET_CREDENTIALS Credentials;
  2046. PHANDLE DescriptorArray;
  2047. UINTN DescriptorCount;
  2048. UINTN DescriptorIndex;
  2049. PIO_HANDLE *IoHandleArray;
  2050. UINTN IoHandleCount;
  2051. PKPROCESS Process;
  2052. KSTATUS Status;
  2053. PKTHREAD Thread;
  2054. UINTN TotalDescriptorCount;
  2055. ControlDataCopy = NULL;
  2056. IoHandleArray = NULL;
  2057. IoHandleCount = 0;
  2058. ASSERT(FromKernelMode == FALSE);
  2059. if (ControlDataSize > UNIX_SOCKET_MAX_CONTROL_DATA) {
  2060. Status = STATUS_INVALID_PARAMETER;
  2061. goto UnixSocketSendControlDataEnd;
  2062. }
  2063. Process = PsGetCurrentProcess();
  2064. //
  2065. // Make a copy of the control data to avoid a million tiny accesses to user
  2066. // mode memory.
  2067. //
  2068. ControlDataCopy = MmAllocatePagedPool(ControlDataSize,
  2069. UNIX_SOCKET_ALLOCATION_TAG);
  2070. if (ControlDataCopy == NULL) {
  2071. Status = STATUS_INSUFFICIENT_RESOURCES;
  2072. goto UnixSocketSendControlDataEnd;
  2073. }
  2074. Status = MmCopyFromUserMode(ControlDataCopy, ControlData, ControlDataSize);
  2075. if (!KSUCCESS(Status)) {
  2076. goto UnixSocketSendControlDataEnd;
  2077. }
  2078. //
  2079. // Loop once to count the number of file descriptors.
  2080. //
  2081. TotalDescriptorCount = 0;
  2082. Control = SOCKET_CONTROL_FIRST(ControlDataCopy, ControlDataSize);
  2083. while (Control != NULL) {
  2084. if (Control->Protocol != SOCKET_LEVEL_SOCKET) {
  2085. Status = STATUS_NOT_SUPPORTED;
  2086. goto UnixSocketSendControlDataEnd;
  2087. }
  2088. if (Control->Type == SOCKET_CONTROL_RIGHTS) {
  2089. //
  2090. // TODO: HANDLE won't work in 64-bit, as PVOID will go to 8
  2091. // bytes but the C library int will stay at 4. Create a new
  2092. // DESCRIPTOR type that is always 32-bits, and use that as the Ob
  2093. // handle table type.
  2094. //
  2095. ASSERT(sizeof(HANDLE) == sizeof(int));
  2096. DescriptorCount = (Control->Length - SOCKET_CONTROL_LENGTH(0)) /
  2097. sizeof(HANDLE);
  2098. TotalDescriptorCount += DescriptorCount;
  2099. } else if (Control->Type != SOCKET_CONTROL_CREDENTIALS) {
  2100. Status = STATUS_NOT_SUPPORTED;
  2101. goto UnixSocketSendControlDataEnd;
  2102. }
  2103. SOCKET_CONTROL_NEXT(ControlDataCopy, ControlDataSize, Control);
  2104. }
  2105. //
  2106. // Allocate the handle array if needed.
  2107. //
  2108. if (TotalDescriptorCount > 0) {
  2109. if (TotalDescriptorCount > UNIX_SOCKET_MAX_CONTROL_HANDLES) {
  2110. Status = STATUS_INVALID_PARAMETER;
  2111. goto UnixSocketSendControlDataEnd;
  2112. }
  2113. AllocationSize = sizeof(PIO_HANDLE) * TotalDescriptorCount;
  2114. IoHandleArray = MmAllocatePagedPool(AllocationSize,
  2115. UNIX_SOCKET_ALLOCATION_TAG);
  2116. if (IoHandleArray == NULL) {
  2117. Status = STATUS_INSUFFICIENT_RESOURCES;
  2118. goto UnixSocketSendControlDataEnd;
  2119. }
  2120. RtlZeroMemory(IoHandleArray, AllocationSize);
  2121. }
  2122. //
  2123. // Go through the control messages again and populate the data.
  2124. //
  2125. Control = SOCKET_CONTROL_FIRST(ControlDataCopy, ControlDataSize);
  2126. while (Control != NULL) {
  2127. ASSERT(Control->Protocol == SOCKET_LEVEL_SOCKET);
  2128. //
  2129. // For passing descriptors, loop through all descriptors getting their
  2130. // associated I/O handles. The routine that gets the handles adds a
  2131. // reference on them, which is left there as the I/O handle sits in the
  2132. // array.
  2133. //
  2134. if (Control->Type == SOCKET_CONTROL_RIGHTS) {
  2135. DescriptorArray = SOCKET_CONTROL_DATA(Control);
  2136. ASSERT(sizeof(HANDLE) == sizeof(int));
  2137. DescriptorCount = (Control->Length - SOCKET_CONTROL_LENGTH(0)) /
  2138. sizeof(HANDLE);
  2139. for (DescriptorIndex = 0;
  2140. DescriptorIndex < DescriptorCount;
  2141. DescriptorIndex += 1) {
  2142. IoHandleArray[IoHandleCount] = ObGetHandleValue(
  2143. Process->HandleTable,
  2144. DescriptorArray[DescriptorIndex],
  2145. NULL);
  2146. if (IoHandleArray[IoHandleCount] == NULL) {
  2147. Status = STATUS_INVALID_HANDLE;
  2148. goto UnixSocketSendControlDataEnd;
  2149. }
  2150. IoHandleCount += 1;
  2151. }
  2152. } else {
  2153. ASSERT(Control->Type == SOCKET_CONTROL_CREDENTIALS);
  2154. Credentials = SOCKET_CONTROL_DATA(Control);
  2155. if ((Control->Length - SOCKET_CONTROL_LENGTH(0)) <
  2156. sizeof(UNIX_SOCKET_CREDENTIALS)) {
  2157. Status = STATUS_DATA_LENGTH_MISMATCH;
  2158. goto UnixSocketSendControlDataEnd;
  2159. }
  2160. Thread = KeGetCurrentThread();
  2161. //
  2162. // Validate the credentials, unless the user has the proper
  2163. // permissions to send forgeries.
  2164. //
  2165. Status = PsCheckPermission(PERMISSION_SYSTEM_ADMINISTRATOR);
  2166. if ((!KSUCCESS(Status)) &&
  2167. (Credentials->ProcessId != Process->Identifiers.ProcessId)) {
  2168. goto UnixSocketSendControlDataEnd;
  2169. }
  2170. Status = PsCheckPermission(PERMISSION_SET_USER_ID);
  2171. if ((!KSUCCESS(Status)) &&
  2172. (Credentials->UserId != Thread->Identity.RealUserId) &&
  2173. (Credentials->UserId != Thread->Identity.EffectiveUserId) &&
  2174. (Credentials->UserId != Thread->Identity.SavedUserId)) {
  2175. goto UnixSocketSendControlDataEnd;
  2176. }
  2177. Status = PsCheckPermission(PERMISSION_SET_GROUP_ID);
  2178. if ((!KSUCCESS(Status)) &&
  2179. (Credentials->GroupId != Thread->Identity.RealGroupId) &&
  2180. (Credentials->GroupId != Thread->Identity.EffectiveGroupId) &&
  2181. (Credentials->GroupId != Thread->Identity.SavedGroupId)) {
  2182. goto UnixSocketSendControlDataEnd;
  2183. }
  2184. //
  2185. // The sent credentials passed, add them in the packet.
  2186. //
  2187. Packet->Credentials.ProcessId = Credentials->ProcessId;
  2188. Packet->Credentials.UserId = Credentials->UserId;
  2189. Packet->Credentials.GroupId = Credentials->GroupId;
  2190. }
  2191. SOCKET_CONTROL_NEXT(ControlDataCopy, ControlDataSize, Control);
  2192. }
  2193. ASSERT(IoHandleCount == TotalDescriptorCount);
  2194. Packet->Handles = IoHandleArray;
  2195. Packet->HandleCount = IoHandleCount;
  2196. IoHandleArray = NULL;
  2197. Status = STATUS_SUCCESS;
  2198. UnixSocketSendControlDataEnd:
  2199. if (ControlDataCopy != NULL) {
  2200. MmFreePagedPool(ControlDataCopy);
  2201. }
  2202. if (IoHandleArray != NULL) {
  2203. for (DescriptorIndex = 0;
  2204. DescriptorIndex < IoHandleCount;
  2205. DescriptorIndex += 1) {
  2206. IoIoHandleReleaseReference(IoHandleArray[DescriptorIndex]);
  2207. }
  2208. MmFreePagedPool(IoHandleArray);
  2209. }
  2210. return Status;
  2211. }
  2212. KSTATUS
  2213. IopUnixSocketReceiveControlData (
  2214. BOOL FromKernelMode,
  2215. PUNIX_SOCKET Socket,
  2216. PUNIX_SOCKET_PACKET Packet,
  2217. PSOCKET_IO_PARAMETERS Parameters
  2218. )
  2219. /*++
  2220. Routine Description:
  2221. This routine receives ancillary data.
  2222. Arguments:
  2223. FromKernelMode - Supplies a boolean indicating if the receive is
  2224. originating from user mode (FALSE) or kernel mode (TRUE). If user mode,
  2225. then the control data pointer is expected to be a user mode pointer.
  2226. Socket - Supplies a pointer to the receiving socket.
  2227. Packet - Supplies a pointer to the packet that is being received.
  2228. Parameters - Supplies a pointer to the I/O parameters.
  2229. Return Value:
  2230. Status code. Truncation or not receiving the ancillary data is not a
  2231. failure.
  2232. --*/
  2233. {
  2234. PSOCKET_CONTROL_MESSAGE Control;
  2235. PVOID ControlData;
  2236. UINTN ControlSize;
  2237. PHANDLE DescriptorArray;
  2238. UINTN Index;
  2239. PKPROCESS Process;
  2240. KSTATUS Status;
  2241. //
  2242. // Compute the size of the control data needed.
  2243. //
  2244. ControlSize = 0;
  2245. if ((Packet->Credentials.ProcessId != -1) ||
  2246. (Packet->Credentials.UserId != -1) ||
  2247. (Packet->Credentials.GroupId != -1)) {
  2248. ControlSize += SOCKET_CONTROL_SPACE(sizeof(UNIX_SOCKET_CREDENTIALS));
  2249. }
  2250. if (Packet->HandleCount != 0) {
  2251. ASSERT(sizeof(HANDLE) == sizeof(int));
  2252. ControlSize += SOCKET_CONTROL_SPACE(
  2253. sizeof(HANDLE) * Packet->HandleCount);
  2254. }
  2255. if (ControlSize == 0) {
  2256. Parameters->ControlDataSize = 0;
  2257. return STATUS_SUCCESS;
  2258. }
  2259. //
  2260. // There is ancillary data to be received. If the caller didn't provide
  2261. // a buffer, then do nothing. Perhaps this is a stream socket and they're
  2262. // only partially receiving the buffer, in which case they get another shot
  2263. // when they receive the rest.
  2264. //
  2265. if ((Parameters->ControlData == NULL) ||
  2266. (Parameters->ControlDataSize < ControlSize)) {
  2267. Parameters->SocketIoFlags |= SOCKET_IO_CONTROL_TRUNCATED;
  2268. return STATUS_SUCCESS;
  2269. }
  2270. //
  2271. // Construct the complete control buffer in kernel mode.
  2272. //
  2273. ControlData = MmAllocatePagedPool(ControlSize, UNIX_SOCKET_ALLOCATION_TAG);
  2274. if (ControlData == NULL) {
  2275. Status = STATUS_INSUFFICIENT_RESOURCES;
  2276. goto UnixSocketReceiveControlDataEnd;
  2277. }
  2278. //
  2279. // Zero the buffer to avoid leaking uninitialized kernel pool to user mode.
  2280. //
  2281. RtlZeroMemory(ControlData, ControlSize);
  2282. Control = SOCKET_CONTROL_FIRST(ControlData, ControlSize);
  2283. if (((Socket->Flags & UNIX_SOCKET_FLAG_SEND_CREDENTIALS) != 0) &&
  2284. ((Packet->Credentials.ProcessId != -1) ||
  2285. (Packet->Credentials.UserId != -1) ||
  2286. (Packet->Credentials.GroupId != -1))) {
  2287. Control->Length = SOCKET_CONTROL_LENGTH(
  2288. sizeof(UNIX_SOCKET_CREDENTIALS));
  2289. Control->Protocol = SOCKET_LEVEL_SOCKET;
  2290. Control->Type = SOCKET_CONTROL_CREDENTIALS;
  2291. RtlCopyMemory(SOCKET_CONTROL_DATA(Control),
  2292. &(Packet->Credentials),
  2293. sizeof(UNIX_SOCKET_CREDENTIALS));
  2294. Packet->Credentials.ProcessId = -1;
  2295. Packet->Credentials.UserId = -1;
  2296. Packet->Credentials.GroupId = -1;
  2297. SOCKET_CONTROL_NEXT(ControlData, ControlSize, Control);
  2298. }
  2299. if (Packet->HandleCount != 0) {
  2300. //
  2301. // The kernel process doesn't have a handle table, so this would get
  2302. // weird.
  2303. //
  2304. Process = PsGetCurrentProcess();
  2305. ASSERT(FromKernelMode == FALSE);
  2306. ASSERT(Process != PsGetKernelProcess());
  2307. ASSERT(sizeof(HANDLE) == sizeof(int));
  2308. Control->Length = SOCKET_CONTROL_LENGTH(
  2309. sizeof(HANDLE) * Packet->HandleCount);
  2310. Control->Protocol = SOCKET_LEVEL_SOCKET;
  2311. Control->Type = SOCKET_CONTROL_RIGHTS;
  2312. DescriptorArray = SOCKET_CONTROL_DATA(Control);
  2313. //
  2314. // Create the handles in the receiving process. If failure occurs,
  2315. // the process may end up with handles it doesn't know about. These
  2316. // handles will get cleaned up when the process exits or does something
  2317. // drastic like closes everything.
  2318. //
  2319. Status = STATUS_SUCCESS;
  2320. for (Index = 0; Index < Packet->HandleCount; Index += 1) {
  2321. Status = ObCreateHandle(Process->HandleTable,
  2322. Packet->Handles[Index],
  2323. 0,
  2324. &(DescriptorArray[Index]));
  2325. if (!KSUCCESS(Status)) {
  2326. //
  2327. // If creating a handle failed, release the reference on the
  2328. // rest of the handles, and stop.
  2329. //
  2330. while (Index < Packet->HandleCount) {
  2331. IoIoHandleReleaseReference(Packet->Handles[Index]);
  2332. Index += 1;
  2333. }
  2334. break;
  2335. }
  2336. }
  2337. //
  2338. // Destroy the handle array, as all the references on the handles were
  2339. // either transferred to the handle table or explicitly released in
  2340. // the failure case.
  2341. //
  2342. MmFreePagedPool(Packet->Handles);
  2343. Packet->Handles = NULL;
  2344. Packet->HandleCount = 0;
  2345. if (!KSUCCESS(Status)) {
  2346. goto UnixSocketReceiveControlDataEnd;
  2347. }
  2348. }
  2349. //
  2350. // Try to copy this ancillary data buffer to user mode.
  2351. //
  2352. Status = MmCopyToUserMode(Parameters->ControlData,
  2353. ControlData,
  2354. ControlSize);
  2355. Parameters->ControlDataSize = ControlSize;
  2356. if (!KSUCCESS(Status)) {
  2357. goto UnixSocketReceiveControlDataEnd;
  2358. }
  2359. Status = STATUS_SUCCESS;
  2360. UnixSocketReceiveControlDataEnd:
  2361. if (ControlData != NULL) {
  2362. MmFreePagedPool(ControlData);
  2363. }
  2364. return Status;
  2365. }
  2366. VOID
  2367. IopUnixSocketInitializeCredentials (
  2368. PUNIX_SOCKET Socket
  2369. )
  2370. /*++
  2371. Routine Description:
  2372. This routine initializes the credentials in the given socket.
  2373. Arguments:
  2374. Socket - Supplies a pointer to the socket to initialize.
  2375. Return Value:
  2376. None.
  2377. --*/
  2378. {
  2379. PKPROCESS Process;
  2380. PKTHREAD Thread;
  2381. Thread = KeGetCurrentThread();
  2382. Process = PsGetCurrentProcess();
  2383. Socket->Credentials.ProcessId = Process->Identifiers.ProcessId;
  2384. Socket->Credentials.UserId = Thread->Identity.RealUserId;
  2385. Socket->Credentials.GroupId = Thread->Identity.RealGroupId;
  2386. return;
  2387. }