<div dir="ltr"><div dir="ltr">Hi<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Aug 4, 2022 at 11:36 PM Simon McVittie <<a href="mailto:smcv@collabora.com">smcv@collabora.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Wed, 03 Aug 2022 at 14:54:21 +0400, Marc-André Lureau wrote:<br>
> The array elements have<br>
> the handle type & value or details for SOCKET. The body 'H' arguments index the<br>
> array, similar to 'h' FDs values.<br>
<br>
Is there a reason why the wire protocol can't use the same 'h' type as<br>
on Unix? In the wire protocol, the 'h' type is just a special sort of<br>
integer, with the conventional semantics being that it is an index into an<br>
array of out-of-band file descriptors. Can the Windows equivalent be making<br>
it an index into an array of HANDLEs?<br>
<br>
This would work very well for GDBus, which literally represents the 'h'<br>
type as an integer index into the GUnixFdList, but might be a bit weird<br>
in libdbus, which transparently replaces the integer index with the actual<br>
file descriptor (which of course will usually be numerically unequal to<br>
either the index, or the fd in the sender) while iterating a received<br>
message's arguments, or transparently replaces a fd with an index into<br>
the array of fds to be sent while building a new message to be sent.<br>
HANDLEs are not the same size as int, so the ABI for dealing with handles<br>
would be different on Unix and Windows.<br>
<br>
I can see why the authors of fd-passing in libdbus did it this way,<br>
but with hindsight, GDBus' approach is probably better.<br>
<br>
If the Windows HANDLEs or SOCKETs have to be sent in-band as ordinary<br>
bytes in the message stream, rather than out-of-band as a special<br>
kernel-mediated capability (which seems odd to me, but I'm not a<br>
Windows expert), then they should probably be in a new header field of<br>
an appropriate type (perhaps 'at' if a bare 64-bit integer is enough,<br>
or 'a(t...)' if you need a 64-bit integer plus metadata, or something<br>
along those lines).<br>
<br>
Something like this (in GVariant-ish pseudocode):<br>
<br>
header = (<br>
    byte endianness,<br>
    byte message type,<br>
    byte flags,<br>
    byte major_version,<br>
    uint32 body_length,<br>
    uint32 serial,<br>
    @a(yv) {<br>
        PATH: <'/foo'>,<br>
        INTERFACE: <'com.example.ArbitraryCodeExecution'>,<br>
        MEMBER: <'ExecCommand'>,<br>
        ...,<br>
        WINDOWS_HANDLES: @a(t...) [                  # a new header field<br>
            (0x12345678, 'this one is stdin', ...),<br>
            (0x87654321, 'this one is stdout', ...),<br>
            (0x12121212, 'this one is stderr', ...),<br>
        ],<br>
    }<br>
)<br></blockquote><div><br></div><div>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.</div><div><br></div><div>I am reluctant to modify the header for each target, making broadcast or other optimizations difficult.</div><div><br></div><div>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.</div><div><br></div><div>Maybe we could have an extra fixed "uint32 handle_array_length"? (in the first 20 bytes)</div><div><br></div><div>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.<br></div><div><br></div><div>Thanks for the help & advices !</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
# 0-7 bytes of padding here, to reach next 8-byte boundary<br>
<br>
body = (<br>
    bytestring b'dir c:\',<br>
    handle 0,  # stdin is the 0'th item in WINDOWS_HANDLES, i.e. 0x12345678<br>
    handle 1,  # stdout is the 1st item<br>
    handle 2,  # stderr is the 2nd item<br>
)   # for a total of body_length bytes<br>
<br>
so that where Unix would have the number of out-of-band fds in the<br>
existing UNIX_FDS header field, Windows would instead have the in-band<br>
HANDLEs in the WINDOWS_HANDLES header field.<br>
<br>
> It seems the D-Bus protocol was designed so that the message size can be<br>
> computed from the header alone, with header + body + fields array size. The<br>
> reference implementation relies on that (_dbus_header_have_message_untrusted<br>
> for ex).<br>
<br>
Yes, the framing layer of the wire protocol is intended to make it possible<br>
to know how long the whole message is going to be by reading its first 16<br>
bytes. This should remain true.<br>
<br>
    smcv<br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr" class="gmail_signature">Marc-André Lureau<br></div></div>