diff options
author | Thiago Macieira <thiago@kde.org> | 2009-07-16 16:05:16 +0200 |
---|---|---|
committer | Thiago Macieira <thiago@kde.org> | 2009-07-16 16:05:16 +0200 |
commit | 37019e9d271390fa8c62c1aae62d30bb9068adaa (patch) | |
tree | 536d5838b73939a6a885f4ef61de1c18814b9529 /bus | |
parent | 56f7ce147e82c7eb529ccba634013e97d53b23c0 (diff) | |
parent | 9f06daccce3f4e75cfac7c97bfb1743affb55cb2 (diff) |
Merge branch 'fd-passing'
Conflicts:
dbus/dbus-connection.c
dbus/dbus-message-util.c
dbus/dbus-sysdeps-unix.c
Diffstat (limited to 'bus')
-rw-r--r-- | bus/bus.c | 10 | ||||
-rw-r--r-- | bus/bus.h | 3 | ||||
-rw-r--r-- | bus/config-parser.c | 27 | ||||
-rw-r--r-- | bus/dbus-daemon.1.in | 5 | ||||
-rw-r--r-- | bus/desktop-file.c | 2 | ||||
-rw-r--r-- | bus/dir-watch-inotify.c | 1 | ||||
-rw-r--r-- | bus/dispatch.c | 170 | ||||
-rw-r--r-- | bus/main.c | 3 | ||||
-rw-r--r-- | bus/session.conf.in | 3 | ||||
-rw-r--r-- | bus/test-main.c | 10 | ||||
-rw-r--r-- | bus/test.h | 4 |
11 files changed, 230 insertions, 8 deletions
@@ -190,6 +190,12 @@ new_connection_callback (DBusServer *server, dbus_connection_set_max_message_size (new_connection, context->limits.max_message_size); + + dbus_connection_set_max_received_unix_fds (new_connection, + context->limits.max_incoming_unix_fds); + + dbus_connection_set_max_message_unix_fds (new_connection, + context->limits.max_message_unix_fds); dbus_connection_set_allow_anonymous (new_connection, context->allow_anonymous); @@ -1471,8 +1477,8 @@ bus_context_check_security_policy (BusContext *context, /* See if limits on size have been exceeded */ if (proposed_recipient && - dbus_connection_get_outgoing_size (proposed_recipient) > - context->limits.max_outgoing_bytes) + ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) || + (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds))) { dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "The destination service \"%s\" has a full message queue", @@ -47,8 +47,11 @@ typedef struct BusMatchRule BusMatchRule; typedef struct { long max_incoming_bytes; /**< How many incoming message bytes for a single connection */ + long max_incoming_unix_fds; /**< How many incoming message unix fds for a single connection */ long max_outgoing_bytes; /**< How many outgoing bytes can be queued for a single connection */ + long max_outgoing_unix_fds; /**< How many outgoing unix fds can be queued for a single connection */ long max_message_size; /**< Max size of a single message in bytes */ + long max_message_unix_fds; /**< Max number of unix fds of a single message*/ int activation_timeout; /**< How long to wait for an activation to time out */ int auth_timeout; /**< How long to wait for an authentication to time out */ int max_completed_connections; /**< Max number of authorized connections */ diff --git a/bus/config-parser.c b/bus/config-parser.c index 007b4e5d..a4a01914 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -404,6 +404,15 @@ bus_config_parser_new (const DBusString *basedir, parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 127; parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 127; parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32; + + /* We set relatively conservative values here since due to the + way SCM_RIGHTS works we need to preallocate an array for the + maximum number of file descriptors we can receive. Picking a + high value here thus translates directly to more memory + allocation. */ + parser->limits.max_incoming_unix_fds = 1024*4; + parser->limits.max_outgoing_unix_fds = 1024*4; + parser->limits.max_message_unix_fds = 1024; /* Making this long means the user has to wait longer for an error * message if something screws up, but making it too short means @@ -1828,16 +1837,31 @@ set_limit (BusConfigParser *parser, must_be_positive = TRUE; parser->limits.max_incoming_bytes = value; } + else if (strcmp (name, "max_incoming_unix_fds") == 0) + { + must_be_positive = TRUE; + parser->limits.max_incoming_unix_fds = value; + } else if (strcmp (name, "max_outgoing_bytes") == 0) { must_be_positive = TRUE; parser->limits.max_outgoing_bytes = value; } + else if (strcmp (name, "max_outgoing_unix_fds") == 0) + { + must_be_positive = TRUE; + parser->limits.max_outgoing_unix_fds = value; + } else if (strcmp (name, "max_message_size") == 0) { must_be_positive = TRUE; parser->limits.max_message_size = value; } + else if (strcmp (name, "max_message_unix_fds") == 0) + { + must_be_positive = TRUE; + parser->limits.max_message_unix_fds = value; + } else if (strcmp (name, "service_start_timeout") == 0) { must_be_positive = TRUE; @@ -2979,8 +3003,11 @@ limits_equal (const BusLimits *a, { return (a->max_incoming_bytes == b->max_incoming_bytes + || a->max_incoming_unix_fds == b->max_incoming_unix_fds || a->max_outgoing_bytes == b->max_outgoing_bytes + || a->max_outgoing_unix_fds == b->max_outgoing_unix_fds || a->max_message_size == b->max_message_size + || a->max_message_unix_fds == b->max_message_unix_fds || a->activation_timeout == b->activation_timeout || a->auth_timeout == b->auth_timeout || a->max_completed_connections == b->max_completed_connections diff --git a/bus/dbus-daemon.1.in b/bus/dbus-daemon.1.in index 4b55ac29..8d518136 100644 --- a/bus/dbus-daemon.1.in +++ b/bus/dbus-daemon.1.in @@ -365,10 +365,15 @@ Available limit names are: .nf "max_incoming_bytes" : total size in bytes of messages incoming from a single connection + "max_incoming_unix_fds" : total number of unix fds of messages + incoming from a single connection "max_outgoing_bytes" : total size in bytes of messages queued up for a single connection + "max_outgoing_unix_fds" : total number of unix fds of messages + queued up for a single connection "max_message_size" : max size of a single message in bytes + "max_message_unix_fds" : max unix fds of a single message "service_start_timeout" : milliseconds (thousandths) until a started service has to connect "auth_timeout" : milliseconds (thousandths) a diff --git a/bus/desktop-file.c b/bus/desktop-file.c index 754a83c3..9f88d6e7 100644 --- a/bus/desktop-file.c +++ b/bus/desktop-file.c @@ -330,7 +330,7 @@ new_line (BusDesktopFileParser *parser) line = §ion->lines[section->n_lines++]; - memset (line, 0, sizeof (BusDesktopFileLine)); + _DBUS_ZERO(*line); return line; } diff --git a/bus/dir-watch-inotify.c b/bus/dir-watch-inotify.c index f03e1bd7..ee580d74 100644 --- a/bus/dir-watch-inotify.c +++ b/bus/dir-watch-inotify.c @@ -24,7 +24,6 @@ #include <config.h> -#define _GNU_SOURCE #include <stdlib.h> #include <unistd.h> #include <fcntl.h> diff --git a/bus/dispatch.c b/bus/dispatch.c index ae6971de..a69a929c 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -35,6 +35,11 @@ #include <dbus/dbus-internals.h> #include <string.h> +#ifdef HAVE_UNIX_FD_PASSING +#include <dbus/dbus-sysdeps-unix.h> +#include <unistd.h> +#endif + static dbus_bool_t send_one_message (DBusConnection *connection, BusContext *context, @@ -51,6 +56,10 @@ send_one_message (DBusConnection *connection, message, NULL)) return TRUE; /* silently don't send it */ + + if (dbus_message_contains_unix_fds(message) && + !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) + return TRUE; /* silently don't send it */ if (!bus_transaction_send (transaction, connection, @@ -295,6 +304,16 @@ bus_dispatch (DBusConnection *connection, addressed_recipient, message, &error)) goto out; + + if (dbus_message_contains_unix_fds(message) && + !dbus_connection_can_send_type(addressed_recipient, DBUS_TYPE_UNIX_FD)) + { + dbus_set_error(&error, + DBUS_ERROR_NOT_SUPPORTED, + "Tried to send message with Unix file descriptors" + "to a client that doesn't support that."); + goto out; + } /* Dispatch the message */ if (!bus_transaction_send (transaction, addressed_recipient, message)) @@ -4716,4 +4735,155 @@ bus_dispatch_sha1_test (const DBusString *test_data_dir) return TRUE; } +#ifdef HAVE_UNIX_FD_PASSING + +dbus_bool_t +bus_unix_fds_passing_test(const DBusString *test_data_dir) +{ + BusContext *context; + DBusConnection *foo, *bar; + DBusError error; + DBusMessage *m; + dbus_bool_t b; + int one[2], two[2], x, y, z; + char r; + + dbus_error_init (&error); + + context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf"); + if (context == NULL) + _dbus_assert_not_reached ("could not alloc context"); + + foo = dbus_connection_open_private ("debug-pipe:name=test-server", &error); + if (foo == NULL) + _dbus_assert_not_reached ("could not alloc connection"); + + if (!bus_setup_debug_client (foo)) + _dbus_assert_not_reached ("could not set up connection"); + + spin_connection_until_authenticated (context, foo); + + if (!check_hello_message (context, foo)) + _dbus_assert_not_reached ("hello message failed"); + + if (!check_add_match_all (context, foo)) + _dbus_assert_not_reached ("AddMatch message failed"); + + bar = dbus_connection_open_private ("debug-pipe:name=test-server", &error); + if (bar == NULL) + _dbus_assert_not_reached ("could not alloc connection"); + + if (!bus_setup_debug_client (bar)) + _dbus_assert_not_reached ("could not set up connection"); + + spin_connection_until_authenticated (context, bar); + + if (!check_hello_message (context, bar)) + _dbus_assert_not_reached ("hello message failed"); + + if (!check_add_match_all (context, bar)) + _dbus_assert_not_reached ("AddMatch message failed"); + + if (!(m = dbus_message_new_signal("/", "a.b.c", "d"))) + _dbus_assert_not_reached ("could not alloc message"); + + if (!(_dbus_full_duplex_pipe(one, one+1, TRUE, &error))) + _dbus_assert_not_reached("Failed to allocate pipe #1"); + + if (!(_dbus_full_duplex_pipe(two, two+1, TRUE, &error))) + _dbus_assert_not_reached("Failed to allocate pipe #2"); + + if (!dbus_message_append_args(m, + DBUS_TYPE_UNIX_FD, one, + DBUS_TYPE_UNIX_FD, two, + DBUS_TYPE_UNIX_FD, two, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached("Failed to attach fds."); + + if (!_dbus_close(one[0], &error)) + _dbus_assert_not_reached("Failed to close pipe #1 "); + if (!_dbus_close(two[0], &error)) + _dbus_assert_not_reached("Failed to close pipe #2 "); + + if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD))) + _dbus_assert_not_reached("Connection cannot do fd passing"); + + if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD))) + _dbus_assert_not_reached("Connection cannot do fd passing"); + + if (!dbus_connection_send (foo, m, NULL)) + _dbus_assert_not_reached("Failed to send fds"); + + dbus_message_unref(m); + + bus_test_run_clients_loop (SEND_PENDING (foo)); + + bus_test_run_everything (context); + + block_connection_until_message_from_bus (context, foo, "unix fd reception on foo"); + + if (!(m = pop_message_waiting_for_memory (foo))) + _dbus_assert_not_reached("Failed to receive msg"); + + if (!dbus_message_is_signal(m, "a.b.c", "d")) + _dbus_assert_not_reached("bogus message received"); + + dbus_message_unref(m); + + block_connection_until_message_from_bus (context, bar, "unix fd reception on bar"); + + if (!(m = pop_message_waiting_for_memory (bar))) + _dbus_assert_not_reached("Failed to receive msg"); + + if (!dbus_message_is_signal(m, "a.b.c", "d")) + _dbus_assert_not_reached("bogus message received"); + + if (!dbus_message_get_args(m, + &error, + DBUS_TYPE_UNIX_FD, &x, + DBUS_TYPE_UNIX_FD, &y, + DBUS_TYPE_UNIX_FD, &z, + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached("Failed to parse fds."); + + dbus_message_unref(m); + + if (write(x, "X", 1) != 1) + _dbus_assert_not_reached("Failed to write to pipe #1"); + if (write(y, "Y", 1) != 1) + _dbus_assert_not_reached("Failed to write to pipe #2"); + if (write(z, "Z", 1) != 1) + _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd"); + + if (!_dbus_close(x, &error)) + _dbus_assert_not_reached("Failed to close pipe #1/other side "); + if (!_dbus_close(y, &error)) + _dbus_assert_not_reached("Failed to close pipe #2/other side "); + if (!_dbus_close(z, &error)) + _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd "); + + if (read(one[1], &r, 1) != 1 || r != 'X') + _dbus_assert_not_reached("Failed to read value from pipe."); + if (read(two[1], &r, 1) != 1 || r != 'Y') + _dbus_assert_not_reached("Failed to read value from pipe."); + if (read(two[1], &r, 1) != 1 || r != 'Z') + _dbus_assert_not_reached("Failed to read value from pipe."); + + if (!_dbus_close(one[1], &error)) + _dbus_assert_not_reached("Failed to close pipe #1 "); + if (!_dbus_close(two[1], &error)) + _dbus_assert_not_reached("Failed to close pipe #2 "); + + _dbus_verbose ("Disconnecting foo\n"); + kill_client_connection_unchecked (foo); + + _dbus_verbose ("Disconnecting bar\n"); + kill_client_connection_unchecked (bar); + + bus_context_unref (context); + + return TRUE; +} +#endif + #endif /* DBUS_BUILD_TESTS */ @@ -208,9 +208,6 @@ setup_reload_pipe (DBusLoop *loop) exit (1); } - _dbus_fd_set_close_on_exec (reload_pipe[0]); - _dbus_fd_set_close_on_exec (reload_pipe[1]); - watch = _dbus_watch_new (reload_pipe[RELOAD_READ_END], DBUS_WATCH_READABLE, TRUE, handle_reload_watch, NULL, NULL); diff --git a/bus/session.conf.in b/bus/session.conf.in index e7229ad5..85395c52 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -45,8 +45,11 @@ <!-- the memory limits are 1G instead of say 4G because they can't exceed 32-bit signed int max --> <limit name="max_incoming_bytes">1000000000</limit> + <limit name="max_incoming_unix_fds">250000000</limit> <limit name="max_outgoing_bytes">1000000000</limit> + <limit name="max_outgoing_unix_fds">250000000</limit> <limit name="max_message_size">1000000000</limit> + <limit name="max_message_unix_fds">4096</limit> <limit name="service_start_timeout">120000</limit> <limit name="auth_timeout">240000</limit> <limit name="max_completed_connections">100000</limit> diff --git a/bus/test-main.c b/bus/test-main.c index f19d0d55..000bdd5a 100644 --- a/bus/test-main.c +++ b/bus/test-main.c @@ -27,6 +27,7 @@ #include <dbus/dbus-string.h> #include <dbus/dbus-sysdeps.h> #include <dbus/dbus-internals.h> +#include <dbus/dbus-message-private.h> #include "selinux.h" #ifdef DBUS_BUILD_TESTS @@ -69,6 +70,7 @@ test_post_hook (void) if (_dbus_getenv ("DBUS_TEST_SELINUX")) bus_selinux_shutdown (); check_memleaks (progname); + _dbus_check_fdleaks(); } int @@ -138,6 +140,14 @@ main (int argc, char **argv) die ("service reload"); test_post_hook (); +#ifdef HAVE_UNIX_FD_PASSING + test_pre_hook (); + printf ("%s: Running unix fd passing test\n", argv[0]); + if (!bus_unix_fds_passing_test (&test_data_dir)) + die ("unix fd passing"); + test_post_hook (); +#endif + printf ("%s: Success\n", argv[0]); @@ -51,7 +51,9 @@ void bus_test_run_everything (BusContext *context); BusContext* bus_context_new_test (const DBusString *test_data_dir, const char *filename); - +#ifdef HAVE_UNIX_FD_PASSING +dbus_bool_t bus_unix_fds_passing_test (const DBusString *test_data_dir); +#endif #endif |