alexlarsson/xdg-app

xdg-app-proxy.c:got_buffer_from_side() ignores data following BEGIN authentization

danvratil opened this issue · 1 comments

Whenever I try to run anything in a sandbox that talks to dbus, I get following error:

** (process:19374): WARNING **: Invalid message header format
Could not connect to D-Bus server: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

The bug seems to be that when a new client connects, the DBus "Hello" message is sent right after the initial handshake, i.e. right after BEGIN\r\n and since the size of the buffer used in side_in_cb() for authentication is 64 bytes, the beginning of the Hello message gets appended to the authentication buffer, like this:

BEGIN\r\nl\1\0\1\0\0\0\0\1\0\0\0n\0\0\0\1\1o\0\25\0\0\0/org/freedesktop/DBus\0\0\0\6\1s\0\24\0\0\0o

(notice that the message itself is incomplete, because it does not fit into the buffer that was handed to read_buffer()).

However the code in got_buffer_from_side() only looks for the BEGIN\r\n part at this phase and then throws the rest of the buffer away. When the rest of the message arrives, the buffer that side_in_cb() tries to parse (by handing it to g_dbus_message_bytes_needed) contains:

rg.freedesktop.D

At this point g_dbus_message_bytes_needed() returns -1, because this is not a valid DBus blob and the entire thing breaks (I guess 16 bytes is the buffer for message header, so the message is payload is truncated here).

So to sum it up - we somehow need to take whatever is in the initial buffer after BEGIN\r\n and put it to a queue until the rest of the message arrives (the question remains how to figure out that the message is complete now).

This is strace output from running "qdbus" utility inside the sandbox:

[dvratil@Thor ~ {default}]
$ xdg-app run -d --command="bash" org.kde.kate --norc
bash-4.3$ strace -s 10000 qdbus
execve("/usr/bin/qdbus", ["qdbus"], [/* 86 vars */]) = 0
...
(skipped the boring parts)
...
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0) = 6
connect(6, {sa_family=AF_LOCAL, sun_path="/run/user/1000/bus"}, 20) = 0
fcntl(6, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
geteuid()                               = 1000
getsockname(6, {sa_family=AF_LOCAL, NULL}, [2]) = 0
poll([{fd=6, events=POLLOUT}], 1, 0)    = 1 ([{fd=6, revents=POLLOUT}])
sendto(6, "\0", 1, MSG_NOSIGNAL, NULL, 0) = 1
sendto(6, "AUTH EXTERNAL 31303030\r\n", 24, MSG_NOSIGNAL, NULL, 0) = 24
poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}])
read(6, "OK 5c9f95b50338d84075ace48d55599f24\r\n", 2048) = 37
poll([{fd=6, events=POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}])
sendto(6, "NEGOTIATE_UNIX_FD\r\n", 19, MSG_NOSIGNAL, NULL, 0) = 19
poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}])
read(6, "AGREE_UNIX_FD\r\n", 2048)      = 15
poll([{fd=6, events=POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}])
sendto(6, "BEGIN\r\n", 7, MSG_NOSIGNAL, NULL, 0) = 7
poll([{fd=6, events=POLLIN|POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}])
sendmsg(6, {msg_name(0)=NULL, msg_iov(2)=[{"l\1\0\1\0\0\0\0\1\0\0\0n\0\0\0\1\1o\0\25\0\0\0/org/freedesktop/DBus\0\0\0\6\1s\0\24\0\0\0org.freedesktop.DBus\0\0\0\0\2\1s\0\24\0\0\0org.freedesktop.DBus\0\0\0\0\3\1s\0\5\0\0\0Hello\0\0\0", 128}, {"", 0}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 128
poll([{fd=6, events=POLLIN}], 1, 25000
** (process:23898): WARNING **: Invalid message header read
) = 1 ([{fd=6, revents=POLLIN|POLLERR|POLLHUP}])
close(6)                                = 0
....
(cleanup)
....
+++ exited with 1 +++

This is strace output from xdg-dbus-proxy process when I ran "qdbus" within the sandbox:

$ strace -s 10000 -p `pidof xdg-dbus-proxy`
Process 23815 attached
restart_syscall(<... resuming interrupted call ...>) = 1
read(4, 0x7ffc3a78d560, 16)             = -1 EAGAIN (Resource temporarily unavailable)
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
accept(3, 0, NULL)                      = 5
fcntl(5, F_GETFD)                       = 0
fcntl(5, F_SETFD, FD_CLOEXEC)           = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
getsockopt(5, SOL_SOCKET, SO_TYPE, [1], [4]) = 0
getsockname(5, {sa_family=AF_LOCAL, sun_path="/run/user/1000/bus-proxy/session-bus-proxy-7W4OYX"}, [52]) = 0
getpeername(5, {sa_family=AF_LOCAL, NULL}, [2]) = 0
getsockopt(5, SOL_SOCKET, SO_KEEPALIVE, [0], [4]) = 0
fcntl(5, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f3f1aa97000
mprotect(0x7f3f1aa97000, 4096, PROT_NONE) = 0
clone(child_stack=0x7f3f1b296ef0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f3f1b2979d0, tls=0x7f3f1b297700, child_tidptr=0x7f3f1b2979d0) = 23822
futex(0x7f3f1cc87488, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0xfd70c0, FUTEX_WAKE_PRIVATE, 1)  = 1
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=9, events=0}], 3, 4294967295) = 1 ([{fd=4, revents=POLLIN}])
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=9, events=0}], 3, 4294967295) = 1 ([{fd=4, revents=POLLIN}])
read(4, "\2\0\0\0\0\0\0\0", 16)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=9, events=0}], 3, 4294967295) = 1 ([{fd=4, revents=POLLIN}])
read(4, "\2\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLIN}])
read(4, "\2\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=5, events=POLLIN}], 1, 4294967295) = 1 ([{fd=5, revents=POLLIN}])
recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"\0", 1}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 1
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN|POLLOUT}, {fd=9, events=0}], 5, 4294967295) = 3 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLIN}, {fd=6, revents=POLLOUT}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=5, events=POLLIN}], 1, 4294967295) = 1 ([{fd=5, revents=POLLIN}])
recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"AUTH EXTERNAL 31303030\r\n", 64}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 24
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
geteuid()                               = 1000
getegid()                               = 1000
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7f3f1cc874a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
sendmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"\0", 1}], msg_controllen=32, [{cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS, {pid=23815, uid=1000, gid=1000}}], msg_flags=0}, MSG_NOSIGNAL) = 1
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN|POLLOUT}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=6, revents=POLLOUT}])
read(4, "\4\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
sendmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"AUTH EXTERNAL 31303030\r\n", 24}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 24
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=6, revents=POLLIN}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}])
recvmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"OK 5c9f95b50338d84075ace48d55599f24\r\n", 64}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 37
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLOUT}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLOUT}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
sendmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"OK 5c9f95b50338d84075ace48d55599f24\r\n", 37}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 37
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLIN}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=5, events=POLLIN}], 1, 4294967295) = 1 ([{fd=5, revents=POLLIN}])
recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"NEGOTIATE_UNIX_FD\r\n", 64}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 19
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN|POLLOUT}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=6, revents=POLLOUT}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
sendmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"NEGOTIATE_UNIX_FD\r\n", 19}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 19
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=6, revents=POLLIN}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=6, events=POLLIN}], 1, 4294967295) = 1 ([{fd=6, revents=POLLIN}])
recvmsg(6, {msg_name(0)=NULL, msg_iov(1)=[{"AGREE_UNIX_FD\r\n", 64}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 15
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN|POLLOUT}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLOUT}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
sendmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"AGREE_UNIX_FD\r\n", 15}], msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 15
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=9, events=0}], 5, 4294967295) = 2 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLIN}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=5, events=POLLIN}], 1, 4294967295) = 1 ([{fd=5, revents=POLLIN}])
recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"BEGIN\r\nl\1\0\1\0\0\0\0\1\0\0\0n\0\0\0\1\1o\0\25\0\0\0/org/freedesktop/DBus\0\0\0\6\1s\0\24\0\0\0o", 64}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 64
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=6, events=POLLIN|POLLOUT}, {fd=9, events=0}], 5, 4294967295) = 3 ([{fd=4, revents=POLLIN}, {fd=5, revents=POLLIN}, {fd=6, revents=POLLOUT}])
read(4, "\3\0\0\0\0\0\0\0", 16)         = 8
write(4, "\1\0\0\0\0\0\0\0", 8)         = 8
poll([{fd=5, events=POLLIN}], 1, 4294967295) = 1 ([{fd=5, revents=POLLIN}])
recvmsg(5, {msg_name(0)=NULL, msg_iov(1)=[{"rg.freedesktop.D", 16}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 16
open("/usr/lib64/charset.alias", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 7
fstat(7, {st_mode=S_IFREG|0644, st_size=26254, ...}) = 0
mmap(NULL, 26254, PROT_READ, MAP_SHARED, 7, 0) = 0x7f3f1d46a000
close(7)                                = 0
futex(0x7f3f1c5288d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
write(2, "\n** (process:23815): WARNING **: Invalid message header read\n", 61) = 61
close(5)                                = 0

This should be fixed in latest master.