Skip to content

FileDescriptors don't actually get sent #81

@rm5248

Description

@rm5248

This is marked as fixed in #42, however after some testing I have found that sending FileDescriptors does not actually work correctly.

I have some sample code here that demonstrates the issue. What I am trying to do is to create a pipe in a client application and send it to a different application in order to write to it. I create the pipe via JNA, and then attempt to convert it to a java.io.FileDescriptor in order to be sent. When I do that, dbus-monitor has the following output:

method call time=1573231344.276953 sender=:1.1897 -> destination=test.filedescriptor serial=3 path=/; interface=fd_rx.FDInterface; member=setFileDescriptor
   file descriptor
method return time=1573231344.298849 sender=:1.1895 -> destination=:1.1897 serial=5 reply_serial=3

On the receiving side, the file descriptor is parsed and is believed to be valid, however when we attempt to write to it we get an IOException:

[2019-11-08 11:42:24] DEBUG fd_rx.FDRX - Got the file descriptor.  Valid? true
[2019-11-08 11:42:24] ERROR fd_rx.FDRX - IOException: 
java.io.IOException: Bad file descriptor
	at java.io.FileOutputStream.write(Native Method) ~[?:1.8.0_171]
	at java.io.FileOutputStream.write(FileOutputStream.java:290) ~[?:1.8.0_171]
	at java.io.DataOutputStream.writeChars(DataOutputStream.java:297) ~[?:1.8.0_171]
	at fd_rx.FDRX.setFileDescriptor(FDRX.java:31) [classes/:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_171]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_171]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_171]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_171]
	at org.freedesktop.dbus.connections.AbstractConnection$2.run(AbstractConnection.java:766) [dbus-java-3.2.0.jar:3.2.0]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_171]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_171]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]

I've also created a C++ application that uses dbus-cxx that acts the same as the Java application where it tries to send a FileDescriptor to the other process. This fails with an error, and the following shows up in dbus-monitor:

method call time=1573231622.504991 sender=:1.1900 -> destination=test.filedescriptor serial=2 path=/; interface=fd_rx.FDInterface; member=setFiledescriptor
   file descriptor
         inode: 42492471
         type: fifo
error time=1573231622.505026 sender=org.freedesktop.DBus -> destination=:1.1900 error_name=org.freedesktop.DBus.Error.NotSupported reply_serial=2
   string "Tried to send message with Unix file descriptorsto a client that doesn't support that."

It seems that the root of this problem is when a java.io.FileDescriptor is sent, an integer is simply marshaled onto the message, which is not the correct way to send a filedescriptor over a socket.

According to the DBus spec, the client must send a "NEGOTIATE_UNIX_FD Command" to allow FD passing. From my reading of the specification as well, it seems that after the NEGOTIATE_UNIX_FD has been sent, when you are actually sending the FD this needs to be set in the message header, and the FDs are sent as some kind of array(the spec indicates that they are sent out-of-band). The value of the FD set in the message is the index into this array.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions