RFC: adding fd-passing to win32

Hailun Tan dearambermini at gmail.com
Tue Aug 9 23:29:09 UTC 2022


Unsubscribed for the god sake.

On Fri, 5 Aug 2022 at 5:36 pm, Marc-André Lureau <marcandre.lureau at gmail.com>
wrote:

> Hi
>
> On Thu, Aug 4, 2022 at 11:36 PM Simon McVittie <smcv at collabora.com> wrote:
>
>> On Wed, 03 Aug 2022 at 14:54:21 +0400, Marc-André Lureau wrote:
>> > The array elements have
>> > the handle type & value or details for SOCKET. The body 'H' arguments
>> index the
>> > array, similar to 'h' FDs values.
>>
>> Is there a reason why the wire protocol can't use the same 'h' type as
>> on Unix? In the wire protocol, the 'h' type is just a special sort of
>> integer, with the conventional semantics being that it is an index into an
>> array of out-of-band file descriptors. Can the Windows equivalent be
>> making
>> it an index into an array of HANDLEs?
>>
>
> As you probably know, HANDLEs are not FD. And Windows has the 2 types, and
> functions to map to/from the 2 (_get_osfhandle/_open_osfhandle).
>
> With the addition of AF_UNIX socket support, Windows developers have shown
> interest in adding more features over time (
> https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupportedunavailable),
> including SCM_RIGHTS/fdpass.
>
> If some day, Windows has SCM_RIGHTS, we should enable that code too. For
> those reasons, I think we should add a new type. If 'H' is not a good
> character, please advise.
>
>
>> This would work very well for GDBus, which literally represents the 'h'
>> type as an integer index into the GUnixFdList, but might be a bit weird
>> in libdbus, which transparently replaces the integer index with the actual
>> file descriptor (which of course will usually be numerically unequal to
>> either the index, or the fd in the sender) while iterating a received
>> message's arguments, or transparently replaces a fd with an index into
>> the array of fds to be sent while building a new message to be sent.
>> HANDLEs are not the same size as int, so the ABI for dealing with handles
>> would be different on Unix and Windows.
>>
>
> I handled that in my dev branch. I introduced a new type to wrap HANDLE or
> SOCKET (or future handle kinds as needed):
>
> /*
>  * Handles which are not yet supported:
>  * - Change notification: FindCloseChangeNotification
>  * - Event log: CloseEventLog
>  * - Find file: FindClose
>  * - Update resource: EndUpdateResource
>  */
>
> typedef struct DBusWinHandle DBusWinHandle;
>
> struct DBusWinHandle {
>   int type;
>   union {
>     SOCKET socket;
>     HANDLE handle;
>   } u;
> };
>
>
>
>> I can see why the authors of fd-passing in libdbus did it this way,
>> but with hindsight, GDBus' approach is probably better.
>>
>
> may be :) in my glib/gio wip branch, I re-use the fdlist (mapping HANDLEs
> to FD). The problem with that approach is that the client looses the HANDLE
> type information, which may be hard to get back (there are "bad" &
> undocumented windows API to do that). I plan to change that, to introduce a
> HANDLE list & API instead.
>
>
>
>> If the Windows HANDLEs or SOCKETs have to be sent in-band as ordinary
>> bytes in the message stream, rather than out-of-band as a special
>> kernel-mediated capability (which seems odd to me, but I'm not a
>> Windows expert), then they should probably be in a new header field of
>>
>
> yes, you have to use DuplicateHandle/wsaduplicatesocket and send the
> handle details to the target, via ipc.
>
>
>> an appropriate type (perhaps 'at' if a bare 64-bit integer is enough,
>> or 'a(t...)' if you need a 64-bit integer plus metadata, or something
>> along those lines).
>>
>> Something like this (in GVariant-ish pseudocode):
>>
>> header = (
>>     byte endianness,
>>     byte message type,
>>     byte flags,
>>     byte major_version,
>>     uint32 body_length,
>>     uint32 serial,
>>     @a(yv) {
>>         PATH: <'/foo'>,
>>         INTERFACE: <'com.example.ArbitraryCodeExecution'>,
>>         MEMBER: <'ExecCommand'>,
>>         ...,
>>         WINDOWS_HANDLES: @a(t...) [                  # a new header field
>>             (0x12345678, 'this one is stdin', ...),
>>             (0x87654321, 'this one is stdout', ...),
>>             (0x12121212, 'this one is stderr', ...),
>>         ],
>>     }
>> )
>>
>> # 0-7 bytes of padding here, to reach next 8-byte boundary
>>
>> body = (
>>     bytestring b'dir c:\',
>>     handle 0,  # stdin is the 0'th item in WINDOWS_HANDLES, i.e.
>> 0x12345678
>>     handle 1,  # stdout is the 1st item
>>     handle 2,  # stderr is the 2nd item
>> )   # for a total of body_length bytes
>>
>> so that where Unix would have the number of out-of-band fds in the
>> existing UNIX_FDS header field, Windows would instead have the in-band
>> HANDLEs in the WINDOWS_HANDLES header field.
>>
>
>
> Yes, that's an idea I discussed with Thiago:
> > 2) if the 'handle array' is itself embedded in the header fields, the
> header content will need to be updated for each receiver when broadcasting.
> > The second option might not be so bad after all, but my original design
> kept the original message (header+body) untouched.
>
>
>
>> > It seems the D-Bus protocol was designed so that the message size can be
>> > computed from the header alone, with header + body + fields array size.
>> The
>> > reference implementation relies on that
>> (_dbus_header_have_message_untrusted
>> > for ex).
>>
>> Yes, the framing layer of the wire protocol is intended to make it
>> possible
>> to know how long the whole message is going to be by reading its first 16
>> bytes. This should remain true.
>>
>
> Ok
>
> --
> Marc-André Lureau
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/dbus/attachments/20220810/e646ac7d/attachment-0001.htm>


More information about the dbus mailing list