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