Re: [systemd-devel] [PATCH] [RFC] [WIP] [kdbus] Attempt to recursively pass fd

2014-09-16 Thread David Herrmann
Hi

On Mon, Sep 15, 2014 at 11:53 PM, Daniel Mack dan...@zonque.org wrote:
 We might eventually allow this once we have a generic GC implementation
 for file descriptors (currently, there's only one, and that one only
 works for unix domain sockets). For now, we'll also need something that
 disallows passing kdbus handles over UDS.

The patch looks good. But I doubt we can fix this via a GC
implementation. I mean, there is no natural way to limit the recursion
level. If we recursively open an FD and queue the previous one into
it, we end up eating all kernel memory, but *all* FDs are still
retrievable! If we stop at like 10k FDs, you can still recursively
read all the queued FDs again, one per FD.

What I'm saying is, if we allow queuing kdbus FDs on kdbus, we need a
fixed recursion level or we have to account the user for the
underlying file even if they close it.

The fixed recursion level for unix sockets is not reliable, though. If
you look at the kernel patch, you see they only reset the recursion
level if the queue is emptied, not if the offending messaged is read.
That is, if you queue a message with recursion-level 4, then one
without any FD, but only the first message is read (that is, the real
recursion level is 0 now), you cannot queue this FD anywhere else. The
effective recursion level is still 4, as is only reset if that
non-offending message is read, too.
They had to do this, as computing the real recursion level is not
doable in O(1), but O(n) (n is queue-length) and they cannot break
backwards-compatibility.

So I think your kdbus patch is the way to go. And if we every want to
allow passing kdbus over kdbus, I'd vote for a recursion level 1.
That is, we only allow passing kdbus messages with an empty queue.

Thanks
David
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] [PATCH] [RFC] [WIP] [kdbus] Attempt to recursively pass fd

2014-09-15 Thread Daniel Mack
Hi Alban,

Sorry for the long delay on this.

On 08/14/2014 01:21 PM, Alban Crequy wrote:
 Before Linux commit 25888e (from 2.6.37-rc4, Nov 2010), fd-passing on Unix
 sockets could recursively be stacked, allowing a process to exhaust the open
 files limit (/proc/sys/fs/file-max) on the system without restriction from
 ulimit -n.
 
 This DoS on Unix sockets was fixed by commit:
 
 commit 25888e30319f8896fc656fc68643e6a078263060
 Author: Eric Dumazet eric.duma...@gmail.com
 Date:   Thu Nov 25 04:11:39 2010 +

 af_unix: limit recursion level
 
 But that commit introduced a bug in dbus:
 https://bugs.freedesktop.org/show_bug.cgi?id=80163
 
 kdbus does not use fd-passing on Unix sockets so it is not affected by this.
 
 However, it allows fd-passing similarly. This patch shows it is possible to
 recursively pass file descriptors in kdbus and stack them without keeping them
 attached to the initial process. I could stack passed fds 256 times, probably
 because of the limit KDBUS_USER_MAX_CONN:

I finally found some time to look into this, and added a patch that
disallows passing kdbus handles over kdbus handles. Such an attempt now
returns -ELOOP.

We might eventually allow this once we have a generic GC implementation
for file descriptors (currently, there's only one, and that one only
works for unix domain sockets). For now, we'll also need something that
disallows passing kdbus handles over UDS.

I also added a test to the suite to check for this behaviour. I borrowed
some code from you test case for this. Care to check wheter that seems
alright to you?

Many thanks for the heads-up!


Daniel
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


[systemd-devel] [PATCH] [RFC] [WIP] [kdbus] Attempt to recursively pass fd

2014-08-14 Thread Alban Crequy
Before Linux commit 25888e (from 2.6.37-rc4, Nov 2010), fd-passing on Unix
sockets could recursively be stacked, allowing a process to exhaust the open
files limit (/proc/sys/fs/file-max) on the system without restriction from
ulimit -n.

This DoS on Unix sockets was fixed by commit:

 commit 25888e30319f8896fc656fc68643e6a078263060
 Author: Eric Dumazet eric.duma...@gmail.com
 Date:   Thu Nov 25 04:11:39 2010 +

 af_unix: limit recursion level

But that commit introduced a bug in dbus:
https://bugs.freedesktop.org/show_bug.cgi?id=80163

kdbus does not use fd-passing on Unix sockets so it is not affected by this.

However, it allows fd-passing similarly. This patch shows it is possible to
recursively pass file descriptors in kdbus and stack them without keeping them
attached to the initial process. I could stack passed fds 256 times, probably
because of the limit KDBUS_USER_MAX_CONN:

defaults.h:#define KDBUS_USER_MAX_CONN  256

But this limit could probably be overrided by using fds from different
endpoints.

I am also afraid that fds from Unix sockets and fds from kdbus could be stacked
together, defeating the limit implemented in unix_attach_fds() by commit 25888e
because the check uses unix_get_socket(), making the assumption that only Unix
sockets could carry file descriptors:
http://lxr.free-electrons.com/source/net/unix/af_unix.c#L1380
http://lxr.free-electrons.com/source/net/unix/garbage.c#L99
---
 test/test-kdbus.c | 72 +++
 1 file changed, 72 insertions(+)

diff --git a/test/test-kdbus.c b/test/test-kdbus.c
index f0bf705..3c79877 100644
--- a/test/test-kdbus.c
+++ b/test/test-kdbus.c
@@ -12,6 +12,8 @@
 #include limits.h
 #include sys/mman.h
 #include sys/ioctl.h
+#include sys/types.h
+#include sys/socket.h
 #include getopt.h
 #include stdbool.h
 
@@ -1004,6 +1006,75 @@ static int check_msg_basic(struct kdbus_check_env *env)
return CHECK_OK;
 }
 
+static int send_fds(struct conn *conn, uint64_t dst_id, int fds[2])
+{
+   struct kdbus_msg *msg;
+   struct kdbus_item *item;
+   uint64_t size;
+   int ret;
+
+   size = sizeof(struct kdbus_msg);
+   size += KDBUS_ITEM_SIZE(sizeof(int[2]));
+
+   msg = malloc(size);
+   ASSERT_RETURN (msg != NULL);
+
+   memset(msg, 0, size);
+   msg-size = size;
+   msg-src_id = conn-id;
+   msg-dst_id = dst_id;
+   msg-payload_type = KDBUS_PAYLOAD_DBUS;
+
+   item = msg-items;
+
+   item-type = KDBUS_ITEM_FDS;
+   item-size = KDBUS_ITEM_HEADER_SIZE + sizeof(int[2]);
+   item-fds[0] = fds[0];
+   item-fds[1] = fds[1];
+   item = KDBUS_ITEM_NEXT(item);
+
+   ret = ioctl(conn-fd, KDBUS_CMD_MSG_SEND, msg);
+   if (ret) {
+   fprintf(stderr, error sending message: %d err %d (%m)\n, ret, 
errno);
+   return EXIT_FAILURE;
+   }
+
+   free(msg);
+
+   return 0;
+}
+
+static int check_fds_passing(struct kdbus_check_env *env)
+{
+   struct conn *conn_src, *conn_dst;
+   int fds[2];
+   int ret;
+   int i;
+
+   /* create two connections */
+   conn_src = kdbus_hello(env-buspath, 0, NULL, 0);
+   ASSERT_RETURN(conn_src != NULL);
+
+   for (i = 0; i = 0; i++) {
+   conn_dst = kdbus_hello(env-buspath, 0, NULL, 0);
+   ASSERT_RETURN(conn_dst != NULL);
+
+   fds[0] = conn_src-fd;
+   fds[1] = conn_dst-fd;
+
+   ret = send_fds (conn_src, conn_dst-id, fds);
+   printf(check_fds_passing: iter: %d fds %d-%d ret %d err %d 
(%m)\n, i, fds[0], fds[1], ret, errno);
+   ASSERT_RETURN(ret == 0);
+
+   close(conn_src-fd);
+   free(conn_src);
+
+   conn_src = conn_dst;
+   }
+
+   return CHECK_OK;
+}
+
 static int check_msg_free(struct kdbus_check_env *env)
 {
int ret;
@@ -,6 +1182,7 @@ static const struct kdbus_check checks[] = {
{ name queue, check_name_queue,   
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
{ message basic,  check_msg_basic,
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
{ message free,   check_msg_free, 
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
+   { fds passing,check_fds_passing,  
CHECK_CREATE_BUS},
{ connection info,check_conn_info,
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
{ match id add,   check_match_id_add, 
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
{ match id remove,check_match_id_remove,  
CHECK_CREATE_BUS | CHECK_CREATE_CONN},
-- 
1.8.5.3

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel