Unix FD Passing
mzqohf at 0pointer.de
Fri Apr 24 09:55:16 PDT 2009
Please have a look here:
That's my dbus git repo that includes the unix fd passing stuff I have
been working on recently. The code there is mostly ready for merging,
two things are missing however: I need to update the spec to match my
protocol extensions and I need to make it possible to control fd
passing via the bus policy xml language. Sending unix fds over the bus
is currently unrestricted with these patches, which might be
problematic because it would be too easy to break apps by sending them
1000 fds and taking away all there available fds by doing so.
A few comments:
This adds just one new call to the API:
dbus_connection_can_send_type(). The purpose for this is that apps can
call this to check whether fd passing is supported by passing the type
code DBUS_TYPE_UNIX_FD. For all other (valid) types this will always
return TRUE. The reason this is called can_send_type() instead of
can_send_unix_fd() is that if more types are added later (float32...)
we don't need to have to add more function calls to the API but just
have a single call for all new types.
If you try to send a msg that contains fds over a transport that
cannot take them the current code will only return an error if the
function you use for it has support for reporting arbitrary errors. If
it has not the msg is silently thrown away. If you use functions like
that you are supposed to call _can_send_type() first. Of course this
can easily be changed to return errors asynchronously as has been
suggested on the list.
The bus will not forward signals with unix fds to clients that cannot
handle them. This is corrrect behaviour I believe. After all, a client
cannot be interested in messages it cannot understand. If it was
interested in those messages it would be supporting the unix fd
passing extensions in the first place.
This also includes simple negotiation for unix fd passing: the auth
protocol is extended a bit. Two new commands have been introduced. If
a clients can do and wants to do fd passing it will send
NEGOTIATE-UNIX-FD after the authentication was sucessful, before
sending BEGIN. The server then responds with ERROR if it cannot or
doesn't want to do fd passing. Otherwise it will respond with
AGREE-UNIX-FD and both sides enable their fd passing code.
The wire protocol extensions for unix fd passing are minimal. There is
one new header field that contains the number of fds that accompany
the message. The fds of course have to be sent out-of-band, i.e. via
SCM_RIGHTS. In the packets themselves for each fd we store one uint32
that is the index into the array of fds that belong to a message. This
encoding should make it possible to support fd passing on all types of
local fd passing APIs. AFAICS all current unixes support SCM_RIGHTS,
however I am not sure they all actually implement the same semantics:
i.e. how the data blocks are actually matched up with the fds that are
passed. To deal with that I made only the most basic assumptions:
i.e. that fds are not silently dropped, that they arrive on the other
side in the same order they were sent. Also they should not arrive
after the last byte of the actual payload packet was received, but it
is ok if they are received before the first byte of it is received. If
later on other local transports should be introduced it should easily
be possible add a bypass via classic unix fds that is used exclusively
for the fd passing.
There are some other changes in the repo too: a few commits regarding
FD_CLOEXEC: newer linux kernels have support for SOCK_CLOEXEC which
allows sockets to be created with O_CLOEXEC set right-away. This
closes a race condition where some other thread might fork/exec while
dbus allocated an fd and hasn't yet set FD_CLOEXEC. Given how
fundamental D-Bus is it is certainly good idea to fix this race.
Also, I made a few changes so that we make use of Linux' MSG_NOSIGNAL
flag when sending data over the sockets. This frees us from having to
play games with SIGPIPE.
I'd be happy about comments. When I'll have fixed the two missing
parts as pointed out above I will post this series to the ML as
git-format-patch formatted mails, if that's OK. Nonetheless i'd be
happy about comments even before I'll do that.
One more thing: git is only half as much fun if sources use
inconsistent white space rules. Some files in dbus include tabs for
indenting. And about every file has trailing whitespace on the
lines. This makes rebasing and preparing patches needlessly
painful. Would you accept a patch that cleans this up by replacing all
tabs by spaces and by dropping all trailing whitespaces? That would be
a huge patch and of course breaks all outstanding patches from
folks. And it would only make sense to merge if from then on a
stronger whitespace regime is upheld.
Lennart Poettering Red Hat, Inc.
lennart [at] poettering [dot] net ICQ# 11060553
http://0pointer.net/lennart/ GnuPG 0x1A015CC4
More information about the dbus