summaryrefslogtreecommitdiffstats
path: root/bus
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2009-07-16 16:05:16 +0200
committerThiago Macieira <thiago@kde.org>2009-07-16 16:05:16 +0200
commit37019e9d271390fa8c62c1aae62d30bb9068adaa (patch)
tree536d5838b73939a6a885f4ef61de1c18814b9529 /bus
parent56f7ce147e82c7eb529ccba634013e97d53b23c0 (diff)
parent9f06daccce3f4e75cfac7c97bfb1743affb55cb2 (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.c10
-rw-r--r--bus/bus.h3
-rw-r--r--bus/config-parser.c27
-rw-r--r--bus/dbus-daemon.1.in5
-rw-r--r--bus/desktop-file.c2
-rw-r--r--bus/dir-watch-inotify.c1
-rw-r--r--bus/dispatch.c170
-rw-r--r--bus/main.c3
-rw-r--r--bus/session.conf.in3
-rw-r--r--bus/test-main.c10
-rw-r--r--bus/test.h4
11 files changed, 230 insertions, 8 deletions
diff --git a/bus/bus.c b/bus/bus.c
index fe90fc44..f6ff1803 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -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",
diff --git a/bus/bus.h b/bus/bus.h
index 62649fd9..94c64c7e 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -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 = &section->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 */
diff --git a/bus/main.c b/bus/main.c
index 7f9e98f3..59651957 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -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]);
diff --git a/bus/test.h b/bus/test.h
index 72d68b09..090768ca 100644
--- a/bus/test.h
+++ b/bus/test.h
@@ -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