RFC: adding fd-passing to win32

Marc-André Lureau marcandre.lureau at gmail.com
Wed Aug 10 09:59:33 UTC 2022


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?
>
> 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 can see why the authors of fd-passing in libdbus did it this way,
> but with hindsight, GDBus' approach is probably better.
>
> 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
> 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', ...),
>         ],
>     }
> )
>

Regardless of whether we map 'h' FDs internally to HANDLE/SOCKETs or expose
a new Windows-specific 'H' type, I am still torn about the location of that
handle array.

I am reluctant to modify the header for each target, making broadcast or
other optimizations difficult.

We could have an extra header field with the size of that array that comes
after the body, but parsing header fields isn't usually done until the
message is fully received.

Maybe we could have an extra fixed "uint32 handle_array_length"? (in the
first 20 bytes)

The only reasonable alternative I can think of is to create a new message
type, that comes next with the message that requires it. This would have
the advantage of making introspection a bit easier too, and maybe help with
policies.

Thanks for the help & advices !


> # 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.
>
> > 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.
>
>     smcv
>


-- 
Marc-André Lureau
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/dbus/attachments/20220810/19c29817/attachment.htm>


More information about the dbus mailing list