[prev in list] [next in list] [prev in thread] [next in thread] 

List:       freedesktop-dbus
Subject:    Re: RFC: adding fd-passing to win32
From:       Hailun Tan <dearambermini () gmail ! com>
Date:       2022-08-09 23:29:09
Message-ID: CAEjDU6r1=XXASFGGEkNE+abCQsJJ-Qfbsq2QczTZYtGwE7qtQw () mail ! gmail ! com
[Download RAW message or body]

Unsubscribed for the god sake.

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

> Hi
>
> On Thu, Aug 4, 2022 at 11:36 PM Simon McVittie <smcv@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
>

[Attachment #3 (text/html)]

<div dir="ltr"><div dir="auto">Unsubscribed for the god sake.</div><div><br><div \
class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 5 Aug 2022 at 5:36 pm, \
Marc-André Lureau &lt;<a href="mailto:marcandre.lureau@gmail.com" \
target="_blank">marcandre.lureau@gmail.com</a>&gt; wrote:<br></div><blockquote \
class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"><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 &lt;<a href="mailto:smcv@collabora.com" \
target="_blank">smcv@collabora.com</a>&gt; 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> &gt; The array elements have<br>
&gt; the handle type &amp; value or details for SOCKET. The body &#39;H&#39; \
arguments index the<br> &gt; array, similar to &#39;h&#39; FDs values.<br>
<br>
Is there a reason why the wire protocol can&#39;t use the same &#39;h&#39; type \
as<br> on Unix? In the wire protocol, the &#39;h&#39; 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></blockquote><div><br></div><div>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).<br></div><div><br></div><div>With the \
addition of AF_UNIX socket support, Windows developers have shown interest in adding \
more features over time (<a \
href="https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupportedunavailable" \
target="_blank">https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupportedunavailable</a>), \
including SCM_RIGHTS/fdpass.<br></div><div>  </div><div>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 &#39;H&#39; is not a good character, please \
advise.<br></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>
This would work very well for GDBus, which literally represents the &#39;h&#39;<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&#39;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></blockquote><div><br></div><div>I handled \
that in my dev branch. I introduced a new type to wrap HANDLE or SOCKET (or future \
handle kinds as needed):<br></div><div><br></div><div>/*<br>  * Handles which are not \
yet supported:<br>  * - Change notification: FindCloseChangeNotification<br>  * - \
Event log: CloseEventLog<br>  * - Find file: FindClose<br>  * - Update resource: \
EndUpdateResource<br>  */<br><br>typedef struct DBusWinHandle \
DBusWinHandle;<br><br>struct DBusWinHandle {<br>   int type;<br>   union {<br>      \
SOCKET socket;<br>      HANDLE handle;<br>   } \
u;<br>};</div><div><br></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>
I can see why the authors of fd-passing in libdbus did it this way,<br>
but with hindsight, GDBus&#39; approach is probably \
better.<br></blockquote><div><br></div><div>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 \
&quot;bad&quot; &amp; undocumented windows API to do that). I plan to change that, to \
introduce a HANDLE list &amp; API \
instead.<br></div><div><br></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>
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&#39;m not a<br>
Windows expert), then they should probably be in a new header field \
of<br></blockquote><div><br></div><div>yes, you have to use \
DuplicateHandle/wsaduplicatesocket and send the handle details to the target, via \
ipc.<br></div></div></div><div dir="ltr"><div class="gmail_quote"><div>  \
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px \
solid rgb(204,204,204);padding-left:1ex"> an appropriate type (perhaps &#39;at&#39; \
if a bare 64-bit integer is enough,<br> or &#39;a(t...)&#39; 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: &lt;&#39;/foo&#39;&gt;,<br>
            INTERFACE: &lt;&#39;com.example.ArbitraryCodeExecution&#39;&gt;,<br>
            MEMBER: &lt;&#39;ExecCommand&#39;&gt;,<br>
            ...,<br>
            WINDOWS_HANDLES: @a(t...) [                           # a new header \
field<br>  (0x12345678, &#39;this one is stdin&#39;, ...),<br>
                  (0x87654321, &#39;this one is stdout&#39;, ...),<br>
                  (0x12121212, &#39;this one is stderr&#39;, ...),<br>
            ],<br>
      }<br>
)<br>
<br>
# 0-7 bytes of padding here, to reach next 8-byte boundary<br>
<br>
body = (<br>
      bytestring b&#39;dir c:\&#39;,<br>
      handle 0,   # stdin is the 0&#39;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></blockquote><div><br></div><div><br></div></div></div><div dir="ltr"><div \
class="gmail_quote"><div>Yes, that&#39;s an idea I discussed with \
Thiago:</div><div>&gt; 2) if the &#39;handle array&#39; is itself  embedded in the \
header fields, the header content will need to be  updated for each receiver when \
broadcasting.<br><div>&gt; The second option might not be so bad after all, but my \
original design kept the original message (header+body) untouched.</div></div><div>  \
</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>
&gt; It seems the D-Bus protocol was designed so that the message size can be<br>
&gt; computed from the header alone, with header + body + fields array size. The<br>
&gt; reference implementation relies on that (_dbus_header_have_message_untrusted<br>
&gt; 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></blockquote><div><br></div><div>Ok \
<br></div></div></div><div dir="ltr"><br>-- <br><div dir="ltr">Marc-André \
Lureau<br></div></div> </blockquote></div></div>
</div>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic