mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-27 02:10:11 +01:00
Merge branch 'fd-passing'
Conflicts: dbus/dbus-connection.c dbus/dbus-message-util.c dbus/dbus-sysdeps-unix.c
This commit is contained in:
commit
37019e9d27
55 changed files with 2376 additions and 355 deletions
|
|
@ -13,6 +13,12 @@ FILE=dbus-1.pc.in
|
|||
|
||||
DIE=0
|
||||
|
||||
if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
|
||||
echo "Activating pre-commit hook."
|
||||
cp -av .git/hooks/pre-commit.sample .git/hooks/pre-commit
|
||||
chmod -c +x .git/hooks/pre-commit
|
||||
fi
|
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have autoconf installed to compile $PROJECT."
|
||||
|
|
|
|||
10
bus/bus.c
10
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",
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ new_line (BusDesktopFileParser *parser)
|
|||
|
||||
line = §ion->lines[section->n_lines++];
|
||||
|
||||
memset (line, 0, sizeof (BusDesktopFileLine));
|
||||
_DBUS_ZERO(*line);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
|
|
|||
170
bus/dispatch.c
170
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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
68
configure.in
68
configure.in
|
|
@ -57,6 +57,7 @@ AC_SUBST(DBUS_VERSION)
|
|||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CXX
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_ISC_POSIX
|
||||
AC_HEADER_STDC
|
||||
AC_C_INLINE
|
||||
|
|
@ -349,41 +350,23 @@ if test "x$dbus_cv_va_val_copy" = "xno"; then
|
|||
fi
|
||||
|
||||
|
||||
#### Atomic integers (checks by Sebastian Wilhelmi for GLib)
|
||||
AC_MSG_CHECKING([whether to use inline assembler routines for atomic integers])
|
||||
have_atomic_inc_cond=0
|
||||
if test x"$GCC" = xyes; then
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
case $host_cpu in
|
||||
i386)
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
i?86)
|
||||
case $host_os in
|
||||
darwin*)
|
||||
AC_MSG_RESULT([darwin])
|
||||
# check at compile-time, so that it is possible to build universal
|
||||
# (with multiple architectures at once on the compile line)
|
||||
have_atomic_inc_cond="(defined(__i386__) || defined(__x86_64__))"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([i486])
|
||||
have_atomic_inc_cond=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
AC_MSG_RESULT([no])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
#### Atomic integers
|
||||
|
||||
AC_CACHE_CHECK([whether $CC knows __sync_sub_and_fetch()],
|
||||
dbus_cv_sync_sub_and_fetch,
|
||||
[AC_LINK_IFELSE(
|
||||
AC_LANG_PROGRAM([], [[int a = 4; int b = __sync_sub_and_fetch(&a, 4);]]),
|
||||
[dbus_cv_sync_sub_and_fetch=yes],
|
||||
[dbus_cv_sync_sub_and_fetch=no])
|
||||
])
|
||||
|
||||
if test "x$dbus_cv_sync_sub_and_fetch" = "xyes" ; then
|
||||
have_sync=1
|
||||
else
|
||||
have_sync=0
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([DBUS_USE_ATOMIC_INT_486_COND], [$have_atomic_inc_cond],
|
||||
[Always defined; expands to 1 if we should use atomic integer implementation for 486, else 0])
|
||||
AC_DEFINE_UNQUOTED(DBUS_HAVE_ATOMIC_INT_COND, [$have_atomic_inc_cond],
|
||||
[Always defined; expands to 1 if we have an atomic integer implementation, else 0])
|
||||
|
||||
AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension])
|
||||
|
||||
#### Various functions
|
||||
AC_SEARCH_LIBS(socket,[socket network])
|
||||
|
|
@ -456,6 +439,8 @@ AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
|
|||
|
||||
AC_CHECK_HEADERS(errno.h)
|
||||
|
||||
AC_CHECK_HEADERS(byteswap.h)
|
||||
|
||||
AC_CHECK_HEADERS(unistd.h)
|
||||
|
||||
# Add -D_POSIX_PTHREAD_SEMANTICS if on Solaris
|
||||
|
|
@ -536,6 +521,9 @@ AC_CHECK_HEADERS(sys/uio.h, [AC_CHECK_FUNCS(writev)])
|
|||
dnl needed on darwin for NAME_MAX
|
||||
AC_CHECK_HEADERS(sys/syslimits.h)
|
||||
|
||||
dnl Make it easy to check if we have MSG_NOSIGNAL without actually having to include sys/socket.h
|
||||
AC_CHECK_DECLS([MSG_NOSIGNAL], [], [], [[ #include <sys/socket.h> ]])
|
||||
|
||||
dnl check for flavours of varargs macros (test from GLib)
|
||||
AC_MSG_CHECKING(for ISO C99 varargs macros in C)
|
||||
AC_TRY_COMPILE([],[
|
||||
|
|
@ -579,6 +567,8 @@ fi
|
|||
|
||||
AC_CHECK_FUNCS(getpeerucred getpeereid)
|
||||
|
||||
AC_CHECK_FUNCS(pipe2 accept4)
|
||||
|
||||
#### Abstract sockets
|
||||
|
||||
if test x$enable_abstract_sockets = xauto; then
|
||||
|
|
@ -881,6 +871,16 @@ else
|
|||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
# Check for SCM_RIGHTS
|
||||
AC_MSG_CHECKING([for SCM_RIGHTS])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
static int x = SCM_RIGHTS;
|
||||
]], [[]])],
|
||||
[ AC_MSG_RESULT([supported])
|
||||
AC_DEFINE([HAVE_UNIX_FD_PASSING], [1], [Supports sending UNIX file descriptors]) ],
|
||||
[ AC_MSG_RESULT([not supported]) ])
|
||||
|
||||
#### Set up final flags
|
||||
DBUS_CLIENT_CFLAGS=
|
||||
|
|
|
|||
184
dbus/dbus-auth.c
184
dbus/dbus-auth.c
|
|
@ -122,7 +122,9 @@ typedef enum {
|
|||
DBUS_AUTH_COMMAND_REJECTED,
|
||||
DBUS_AUTH_COMMAND_OK,
|
||||
DBUS_AUTH_COMMAND_ERROR,
|
||||
DBUS_AUTH_COMMAND_UNKNOWN
|
||||
DBUS_AUTH_COMMAND_UNKNOWN,
|
||||
DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD,
|
||||
DBUS_AUTH_COMMAND_AGREE_UNIX_FD
|
||||
} DBusAuthCommand;
|
||||
|
||||
/**
|
||||
|
|
@ -184,6 +186,9 @@ struct DBusAuth
|
|||
unsigned int already_got_mechanisms : 1; /**< Client already got mech list */
|
||||
unsigned int already_asked_for_initial_response : 1; /**< Already sent a blank challenge to get an initial response */
|
||||
unsigned int buffer_outstanding : 1; /**< Buffer is "checked out" for reading data into */
|
||||
|
||||
unsigned int unix_fd_possible : 1; /**< This side could do unix fd passing */
|
||||
unsigned int unix_fd_negotiated : 1; /**< Unix fd was successfully negotiated */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -223,9 +228,10 @@ static dbus_bool_t send_rejected (DBusAuth *auth);
|
|||
static dbus_bool_t send_error (DBusAuth *auth,
|
||||
const char *message);
|
||||
static dbus_bool_t send_ok (DBusAuth *auth);
|
||||
static dbus_bool_t send_begin (DBusAuth *auth,
|
||||
const DBusString *args_from_ok);
|
||||
static dbus_bool_t send_begin (DBusAuth *auth);
|
||||
static dbus_bool_t send_cancel (DBusAuth *auth);
|
||||
static dbus_bool_t send_negotiate_unix_fd (DBusAuth *auth);
|
||||
static dbus_bool_t send_agree_unix_fd (DBusAuth *auth);
|
||||
|
||||
/**
|
||||
* Client states
|
||||
|
|
@ -264,6 +270,9 @@ static dbus_bool_t handle_client_state_waiting_for_ok (DBusAuth *aut
|
|||
static dbus_bool_t handle_client_state_waiting_for_reject (DBusAuth *auth,
|
||||
DBusAuthCommand command,
|
||||
const DBusString *args);
|
||||
static dbus_bool_t handle_client_state_waiting_for_agree_unix_fd (DBusAuth *auth,
|
||||
DBusAuthCommand command,
|
||||
const DBusString *args);
|
||||
|
||||
static const DBusAuthStateData client_state_need_send_auth = {
|
||||
"NeedSendAuth", NULL
|
||||
|
|
@ -277,7 +286,10 @@ static const DBusAuthStateData client_state_waiting_for_ok = {
|
|||
static const DBusAuthStateData client_state_waiting_for_reject = {
|
||||
"WaitingForReject", handle_client_state_waiting_for_reject
|
||||
};
|
||||
|
||||
static const DBusAuthStateData client_state_waiting_for_agree_unix_fd = {
|
||||
"WaitingForAgreeUnixFD", handle_client_state_waiting_for_agree_unix_fd
|
||||
};
|
||||
|
||||
/**
|
||||
* Common terminal states. Terminal states have handler == NULL.
|
||||
*/
|
||||
|
|
@ -1522,9 +1534,21 @@ send_ok (DBusAuth *auth)
|
|||
}
|
||||
|
||||
static dbus_bool_t
|
||||
send_begin (DBusAuth *auth,
|
||||
const DBusString *args_from_ok)
|
||||
send_begin (DBusAuth *auth)
|
||||
{
|
||||
|
||||
if (!_dbus_string_append (&auth->outgoing,
|
||||
"BEGIN\r\n"))
|
||||
return FALSE;
|
||||
|
||||
goto_state (auth, &common_state_authenticated);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
process_ok(DBusAuth *auth,
|
||||
const DBusString *args_from_ok) {
|
||||
|
||||
int end_of_hex;
|
||||
|
||||
/* "args_from_ok" should be the GUID, whitespace already pulled off the front */
|
||||
|
|
@ -1549,20 +1573,19 @@ send_begin (DBusAuth *auth,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if (_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0) &&
|
||||
_dbus_string_append (&auth->outgoing, "BEGIN\r\n"))
|
||||
{
|
||||
_dbus_verbose ("Got GUID '%s' from the server\n",
|
||||
_dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
|
||||
|
||||
goto_state (auth, &common_state_authenticated);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_dbus_string_copy (args_from_ok, 0, &DBUS_AUTH_CLIENT (auth)->guid_from_server, 0)) {
|
||||
_dbus_string_set_length (& DBUS_AUTH_CLIENT (auth)->guid_from_server, 0);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
_dbus_verbose ("Got GUID '%s' from the server\n",
|
||||
_dbus_string_get_const_data (& DBUS_AUTH_CLIENT (auth)->guid_from_server));
|
||||
|
||||
if (auth->unix_fd_possible)
|
||||
return send_negotiate_unix_fd(auth);
|
||||
|
||||
_dbus_verbose("Not negotiating unix fd passing, since not possible\n");
|
||||
return send_begin (auth);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -1621,6 +1644,33 @@ process_data (DBusAuth *auth,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
send_negotiate_unix_fd (DBusAuth *auth)
|
||||
{
|
||||
if (!_dbus_string_append (&auth->outgoing,
|
||||
"NEGOTIATE_UNIX_FD\r\n"))
|
||||
return FALSE;
|
||||
|
||||
goto_state (auth, &client_state_waiting_for_agree_unix_fd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
send_agree_unix_fd (DBusAuth *auth)
|
||||
{
|
||||
_dbus_assert(auth->unix_fd_possible);
|
||||
|
||||
auth->unix_fd_negotiated = TRUE;
|
||||
_dbus_verbose("Agreed to UNIX FD passing\n");
|
||||
|
||||
if (!_dbus_string_append (&auth->outgoing,
|
||||
"AGREE_UNIX_FD\r\n"))
|
||||
return FALSE;
|
||||
|
||||
goto_state (auth, &server_state_waiting_for_begin);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
handle_auth (DBusAuth *auth, const DBusString *args)
|
||||
{
|
||||
|
|
@ -1712,9 +1762,13 @@ handle_server_state_waiting_for_auth (DBusAuth *auth,
|
|||
case DBUS_AUTH_COMMAND_ERROR:
|
||||
return send_rejected (auth);
|
||||
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
return send_error (auth, "Need to authenticate first");
|
||||
|
||||
case DBUS_AUTH_COMMAND_REJECTED:
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
}
|
||||
|
|
@ -1741,9 +1795,13 @@ handle_server_state_waiting_for_data (DBusAuth *auth,
|
|||
goto_state (auth, &common_state_need_disconnect);
|
||||
return TRUE;
|
||||
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
return send_error (auth, "Need to authenticate first");
|
||||
|
||||
case DBUS_AUTH_COMMAND_REJECTED:
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
}
|
||||
|
|
@ -1766,9 +1824,16 @@ handle_server_state_waiting_for_begin (DBusAuth *auth,
|
|||
goto_state (auth, &common_state_authenticated);
|
||||
return TRUE;
|
||||
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
if (auth->unix_fd_possible)
|
||||
return send_agree_unix_fd(auth);
|
||||
else
|
||||
return send_error(auth, "Unix FD passing not supported, not authenticated or otherwise not possible");
|
||||
|
||||
case DBUS_AUTH_COMMAND_REJECTED:
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
|
||||
|
|
@ -1933,7 +1998,7 @@ handle_client_state_waiting_for_data (DBusAuth *auth,
|
|||
return process_rejected (auth, args);
|
||||
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
return send_begin (auth, args);
|
||||
return process_ok(auth, args);
|
||||
|
||||
case DBUS_AUTH_COMMAND_ERROR:
|
||||
return send_cancel (auth);
|
||||
|
|
@ -1942,6 +2007,8 @@ handle_client_state_waiting_for_data (DBusAuth *auth,
|
|||
case DBUS_AUTH_COMMAND_CANCEL:
|
||||
case DBUS_AUTH_COMMAND_BEGIN:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
}
|
||||
|
|
@ -1958,7 +2025,7 @@ handle_client_state_waiting_for_ok (DBusAuth *auth,
|
|||
return process_rejected (auth, args);
|
||||
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
return send_begin (auth, args);
|
||||
return process_ok(auth, args);
|
||||
|
||||
case DBUS_AUTH_COMMAND_DATA:
|
||||
case DBUS_AUTH_COMMAND_ERROR:
|
||||
|
|
@ -1968,6 +2035,8 @@ handle_client_state_waiting_for_ok (DBusAuth *auth,
|
|||
case DBUS_AUTH_COMMAND_CANCEL:
|
||||
case DBUS_AUTH_COMMAND_BEGIN:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
}
|
||||
|
|
@ -1990,12 +2059,46 @@ handle_client_state_waiting_for_reject (DBusAuth *auth,
|
|||
case DBUS_AUTH_COMMAND_OK:
|
||||
case DBUS_AUTH_COMMAND_ERROR:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
default:
|
||||
goto_state (auth, &common_state_need_disconnect);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth,
|
||||
DBusAuthCommand command,
|
||||
const DBusString *args)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case DBUS_AUTH_COMMAND_AGREE_UNIX_FD:
|
||||
_dbus_assert(auth->unix_fd_possible);
|
||||
auth->unix_fd_negotiated = TRUE;
|
||||
_dbus_verbose("Sucessfully negotiated UNIX FD passing\n");
|
||||
return send_begin (auth);
|
||||
|
||||
case DBUS_AUTH_COMMAND_ERROR:
|
||||
_dbus_assert(auth->unix_fd_possible);
|
||||
auth->unix_fd_negotiated = FALSE;
|
||||
_dbus_verbose("Failed to negotiate UNIX FD passing\n");
|
||||
return send_begin (auth);
|
||||
|
||||
case DBUS_AUTH_COMMAND_OK:
|
||||
case DBUS_AUTH_COMMAND_DATA:
|
||||
case DBUS_AUTH_COMMAND_REJECTED:
|
||||
case DBUS_AUTH_COMMAND_AUTH:
|
||||
case DBUS_AUTH_COMMAND_CANCEL:
|
||||
case DBUS_AUTH_COMMAND_BEGIN:
|
||||
case DBUS_AUTH_COMMAND_UNKNOWN:
|
||||
case DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD:
|
||||
default:
|
||||
return send_error (auth, "Unknown command");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping from command name to enum
|
||||
*/
|
||||
|
|
@ -2005,13 +2108,15 @@ typedef struct {
|
|||
} DBusAuthCommandName;
|
||||
|
||||
static const DBusAuthCommandName auth_command_names[] = {
|
||||
{ "AUTH", DBUS_AUTH_COMMAND_AUTH },
|
||||
{ "CANCEL", DBUS_AUTH_COMMAND_CANCEL },
|
||||
{ "DATA", DBUS_AUTH_COMMAND_DATA },
|
||||
{ "BEGIN", DBUS_AUTH_COMMAND_BEGIN },
|
||||
{ "REJECTED", DBUS_AUTH_COMMAND_REJECTED },
|
||||
{ "OK", DBUS_AUTH_COMMAND_OK },
|
||||
{ "ERROR", DBUS_AUTH_COMMAND_ERROR }
|
||||
{ "AUTH", DBUS_AUTH_COMMAND_AUTH },
|
||||
{ "CANCEL", DBUS_AUTH_COMMAND_CANCEL },
|
||||
{ "DATA", DBUS_AUTH_COMMAND_DATA },
|
||||
{ "BEGIN", DBUS_AUTH_COMMAND_BEGIN },
|
||||
{ "REJECTED", DBUS_AUTH_COMMAND_REJECTED },
|
||||
{ "OK", DBUS_AUTH_COMMAND_OK },
|
||||
{ "ERROR", DBUS_AUTH_COMMAND_ERROR },
|
||||
{ "NEGOTIATE_UNIX_FD", DBUS_AUTH_COMMAND_NEGOTIATE_UNIX_FD },
|
||||
{ "AGREE_UNIX_FD", DBUS_AUTH_COMMAND_AGREE_UNIX_FD }
|
||||
};
|
||||
|
||||
static DBusAuthCommand
|
||||
|
|
@ -2685,6 +2790,31 @@ _dbus_auth_set_context (DBusAuth *auth,
|
|||
&auth->context, 0, _dbus_string_get_length (context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether unix fd passing is potentially on the transport and
|
||||
* hence shall be negotiated.
|
||||
*
|
||||
* @param auth the auth conversation
|
||||
* @param b TRUE when unix fd passing shall be negotiated, otherwise FALSE
|
||||
*/
|
||||
void
|
||||
_dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b)
|
||||
{
|
||||
auth->unix_fd_possible = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether unix fd passing was sucessfully negotiated.
|
||||
*
|
||||
* @param auth the auth conversion
|
||||
* @returns #TRUE when unix fd passing was negotiated.
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_auth_get_unix_fd_negotiated(DBusAuth *auth)
|
||||
{
|
||||
return auth->unix_fd_negotiated;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* tests in dbus-auth-util.c */
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ dbus_bool_t _dbus_auth_set_context (DBusAuth *auth,
|
|||
const DBusString *context);
|
||||
const char* _dbus_auth_get_guid_from_server(DBusAuth *auth);
|
||||
|
||||
void _dbus_auth_set_unix_fd_possible(DBusAuth *auth, dbus_bool_t b);
|
||||
dbus_bool_t _dbus_auth_get_unix_fd_negotiated(DBusAuth *auth);
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "dbus-list.h"
|
||||
#include "dbus-hash.h"
|
||||
#include "dbus-message-internal.h"
|
||||
#include "dbus-message-private.h"
|
||||
#include "dbus-threads.h"
|
||||
#include "dbus-protocol.h"
|
||||
#include "dbus-dataslot.h"
|
||||
|
|
@ -41,6 +42,7 @@
|
|||
#include "dbus-object-tree.h"
|
||||
#include "dbus-threads-internal.h"
|
||||
#include "dbus-bus.h"
|
||||
#include "dbus-marshal-basic.h"
|
||||
|
||||
#ifdef DBUS_DISABLE_CHECKS
|
||||
#define TOOK_LOCK_CHECK(connection)
|
||||
|
|
@ -223,7 +225,11 @@ struct DBusPreallocatedSend
|
|||
DBusList *counter_link; /**< Preallocated link in the resource counter */
|
||||
};
|
||||
|
||||
#ifdef HAVE_DECL_MSG_NOSIGNAL
|
||||
static dbus_bool_t _dbus_modify_sigpipe = FALSE;
|
||||
#else
|
||||
static dbus_bool_t _dbus_modify_sigpipe = TRUE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implementation details of DBusConnection. All fields are private.
|
||||
|
|
@ -621,8 +627,8 @@ _dbus_connection_message_sent (DBusConnection *connection,
|
|||
connection, connection->n_outgoing);
|
||||
|
||||
/* Save this link in the link cache also */
|
||||
_dbus_message_remove_size_counter (message, connection->outgoing_counter,
|
||||
&link);
|
||||
_dbus_message_remove_counter (message, connection->outgoing_counter,
|
||||
&link);
|
||||
_dbus_list_prepend_link (&connection->link_cache, link);
|
||||
|
||||
dbus_message_unref (message);
|
||||
|
|
@ -1929,8 +1935,8 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con
|
|||
_dbus_list_prepend_link (&connection->outgoing_messages,
|
||||
preallocated->queue_link);
|
||||
|
||||
_dbus_message_add_size_counter_link (message,
|
||||
preallocated->counter_link);
|
||||
_dbus_message_add_counter_link (message,
|
||||
preallocated->counter_link);
|
||||
|
||||
dbus_free (preallocated);
|
||||
preallocated = NULL;
|
||||
|
|
@ -2575,9 +2581,9 @@ free_outgoing_message (void *element,
|
|||
DBusMessage *message = element;
|
||||
DBusConnection *connection = data;
|
||||
|
||||
_dbus_message_remove_size_counter (message,
|
||||
connection->outgoing_counter,
|
||||
NULL);
|
||||
_dbus_message_remove_counter (message,
|
||||
connection->outgoing_counter,
|
||||
NULL);
|
||||
dbus_message_unref (message);
|
||||
}
|
||||
|
||||
|
|
@ -2970,14 +2976,58 @@ dbus_connection_get_server_id (DBusConnection *connection)
|
|||
char *id;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, NULL);
|
||||
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a certain type can be send via the connection. This
|
||||
* will always return TRUE for all types, with the exception of
|
||||
* DBUS_TYPE_UNIX_FD. The function will return TRUE for
|
||||
* DBUS_TYPE_UNIX_FD only on systems that know Unix file descriptors
|
||||
* and can send them via the chosen transport and when the remote side
|
||||
* supports this.
|
||||
*
|
||||
* This function can be used to do runtime checking for types that
|
||||
* might be unknown to the specific D-Bus client implementation
|
||||
* version, i.e. it will return FALSE for all types this
|
||||
* implementation does not know.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param type the type to check
|
||||
* @returns TRUE if the type may be send via the connection
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_connection_can_send_type(DBusConnection *connection,
|
||||
int type)
|
||||
{
|
||||
_dbus_return_val_if_fail (connection != NULL, FALSE);
|
||||
|
||||
if (!_dbus_type_is_valid(type))
|
||||
return FALSE;
|
||||
|
||||
if (type != DBUS_TYPE_UNIX_FD)
|
||||
return TRUE;
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
{
|
||||
dbus_bool_t b;
|
||||
|
||||
CONNECTION_LOCK(connection);
|
||||
b = _dbus_transport_can_pass_unix_fd(connection->transport);
|
||||
CONNECTION_UNLOCK(connection);
|
||||
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether _exit() should be called when the connection receives a
|
||||
* disconnect signal. The call to _exit() comes after any handlers for
|
||||
|
|
@ -3078,8 +3128,23 @@ dbus_connection_send_preallocated (DBusConnection *connection,
|
|||
_dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
|
||||
(dbus_message_get_interface (message) != NULL &&
|
||||
dbus_message_get_member (message) != NULL));
|
||||
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
|
||||
message->n_unix_fds > 0)
|
||||
{
|
||||
/* Refuse to send fds on a connection that cannot handle
|
||||
them. Unfortunately we cannot return a proper error here, so
|
||||
the best we can is just return. */
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
_dbus_connection_send_preallocated_and_unlock (connection,
|
||||
preallocated,
|
||||
message, client_serial);
|
||||
|
|
@ -3143,6 +3208,20 @@ dbus_connection_send (DBusConnection *connection,
|
|||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
|
||||
message->n_unix_fds > 0)
|
||||
{
|
||||
/* Refuse to send fds on a connection that cannot handle
|
||||
them. Unfortunately we cannot return a proper error here, so
|
||||
the best we can is just return. */
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return _dbus_connection_send_and_unlock (connection,
|
||||
message,
|
||||
serial);
|
||||
|
|
@ -3197,12 +3276,16 @@ reply_handler_timeout (void *data)
|
|||
* you want a very short or very long timeout. If INT_MAX is passed for
|
||||
* the timeout, no timeout will be set and the call will block forever.
|
||||
*
|
||||
* @warning if the connection is disconnected, the #DBusPendingCall
|
||||
* will be set to #NULL, so be careful with this.
|
||||
*
|
||||
* @warning if the connection is disconnected or you try to send Unix
|
||||
* file descriptors on a connection that does not support them, the
|
||||
* #DBusPendingCall will be set to #NULL, so be careful with this.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param message the message to send
|
||||
* @param pending_return return location for a #DBusPendingCall object, or #NULL if connection is disconnected
|
||||
* @param pending_return return location for a #DBusPendingCall
|
||||
* object, or #NULL if connection is disconnected or when you try to
|
||||
* send Unix file descriptors on a connection that does not support
|
||||
* them.
|
||||
* @param timeout_milliseconds timeout in milliseconds, -1 for default or INT_MAX for no timeout
|
||||
* @returns #FALSE if no memory, #TRUE otherwise.
|
||||
*
|
||||
|
|
@ -3226,6 +3309,21 @@ dbus_connection_send_with_reply (DBusConnection *connection,
|
|||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
|
||||
message->n_unix_fds > 0)
|
||||
{
|
||||
/* Refuse to send fds on a connection that cannot handle
|
||||
them. Unfortunately we cannot return a proper error here, so
|
||||
the best we can do is return TRUE but leave *pending_return
|
||||
as NULL. */
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!_dbus_connection_get_is_connected_unlocked (connection))
|
||||
{
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
|
@ -3334,12 +3432,26 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
|
|||
{
|
||||
DBusMessage *reply;
|
||||
DBusPendingCall *pending;
|
||||
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, NULL);
|
||||
_dbus_return_val_if_fail (message != NULL, NULL);
|
||||
_dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
|
||||
_dbus_return_val_if_error_is_set (error, NULL);
|
||||
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
|
||||
message->n_unix_fds > 0)
|
||||
{
|
||||
CONNECTION_UNLOCK (connection);
|
||||
dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
|
||||
return NULL;
|
||||
}
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
#endif
|
||||
|
||||
if (!dbus_connection_send_with_reply (connection, message,
|
||||
&pending, timeout_milliseconds))
|
||||
{
|
||||
|
|
@ -5860,6 +5972,45 @@ dbus_connection_get_max_message_size (DBusConnection *connection)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the maximum number of unix fds a message on this
|
||||
* connection is allowed to receive. Messages with more unix fds will
|
||||
* result in disconnecting the connection.
|
||||
*
|
||||
* @param connection a #DBusConnection
|
||||
* @param size maximum message unix fds the connection can receive
|
||||
*/
|
||||
void
|
||||
dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
|
||||
long n)
|
||||
{
|
||||
_dbus_return_if_fail (connection != NULL);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
_dbus_transport_set_max_message_unix_fds (connection->transport,
|
||||
n);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value set by dbus_connection_set_max_message_unix_fds().
|
||||
*
|
||||
* @param connection the connection
|
||||
* @returns the max numer of unix fds of a single message
|
||||
*/
|
||||
long
|
||||
dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
|
||||
{
|
||||
long res;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, 0);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
res = _dbus_transport_get_max_message_unix_fds (connection->transport);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum total number of bytes that can be used for all messages
|
||||
* received on this connection. Messages count toward the maximum until
|
||||
|
|
@ -5916,6 +6067,48 @@ dbus_connection_get_max_received_size (DBusConnection *connection)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum total number of unix fds that can be used for all messages
|
||||
* received on this connection. Messages count toward the maximum until
|
||||
* they are finalized. When the maximum is reached, the connection will
|
||||
* not read more data until some messages are finalized.
|
||||
*
|
||||
* The semantics are analogous to those of dbus_connection_set_max_received_size().
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param size the maximum size in bytes of all outstanding messages
|
||||
*/
|
||||
void
|
||||
dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
|
||||
long n)
|
||||
{
|
||||
_dbus_return_if_fail (connection != NULL);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
_dbus_transport_set_max_received_unix_fds (connection->transport,
|
||||
n);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value set by dbus_connection_set_max_received_unix_fds().
|
||||
*
|
||||
* @param connection the connection
|
||||
* @returns the max unix fds of all live messages
|
||||
*/
|
||||
long
|
||||
dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
|
||||
{
|
||||
long res;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, 0);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
res = _dbus_transport_get_max_received_unix_fds (connection->transport);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the approximate size in bytes of all messages in the outgoing
|
||||
* message queue. The size is approximate in that you shouldn't use
|
||||
|
|
@ -5932,9 +6125,29 @@ dbus_connection_get_outgoing_size (DBusConnection *connection)
|
|||
long res;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, 0);
|
||||
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
res = _dbus_counter_get_value (connection->outgoing_counter);
|
||||
res = _dbus_counter_get_size_value (connection->outgoing_counter);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the approximate number of uni fds of all messages in the
|
||||
* outgoing message queue.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @returns the number of unix fds that have been queued up but not sent
|
||||
*/
|
||||
long
|
||||
dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
|
||||
{
|
||||
long res;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, 0);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ dbus_bool_t dbus_connection_get_is_connected (DBusConnection
|
|||
dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection);
|
||||
dbus_bool_t dbus_connection_get_is_anonymous (DBusConnection *connection);
|
||||
char* dbus_connection_get_server_id (DBusConnection *connection);
|
||||
dbus_bool_t dbus_connection_can_send_type (DBusConnection *connection,
|
||||
int type);
|
||||
void dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
|
||||
dbus_bool_t exit_on_disconnect);
|
||||
void dbus_connection_flush (DBusConnection *connection);
|
||||
|
|
@ -279,7 +281,16 @@ long dbus_connection_get_max_message_size (DBusConnection *connection);
|
|||
void dbus_connection_set_max_received_size (DBusConnection *connection,
|
||||
long size);
|
||||
long dbus_connection_get_max_received_size (DBusConnection *connection);
|
||||
|
||||
void dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
|
||||
long n);
|
||||
long dbus_connection_get_max_message_unix_fds (DBusConnection *connection);
|
||||
void dbus_connection_set_max_received_unix_fds(DBusConnection *connection,
|
||||
long n);
|
||||
long dbus_connection_get_max_received_unix_fds(DBusConnection *connection);
|
||||
|
||||
long dbus_connection_get_outgoing_size (DBusConnection *connection);
|
||||
long dbus_connection_get_outgoing_unix_fds (DBusConnection *connection);
|
||||
|
||||
DBusPreallocatedSend* dbus_connection_preallocate_send (DBusConnection *connection);
|
||||
void dbus_connection_free_preallocated_send (DBusConnection *connection,
|
||||
|
|
|
|||
|
|
@ -294,18 +294,23 @@ _DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
|
|||
_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
|
||||
/* 5-10 */
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (bus);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (bus_datas);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (system_users);
|
||||
/* 10-15 */
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (message_cache);
|
||||
/* 10-14 */
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (win_fds);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
|
||||
|
||||
#if !DBUS_USE_SYNC
|
||||
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
|
||||
#define _DBUS_N_GLOBAL_LOCKS (15)
|
||||
#else
|
||||
#define _DBUS_N_GLOBAL_LOCKS (14)
|
||||
#endif
|
||||
|
||||
dbus_bool_t _dbus_threads_init_debug (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ _dbus_marshal_set_basic (DBusString *str,
|
|||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
pos = _DBUS_ALIGN_VALUE (pos, 4);
|
||||
set_4_octets (str, pos, vp->u32, byte_order);
|
||||
if (old_end_pos)
|
||||
|
|
@ -540,6 +541,7 @@ _dbus_marshal_read_basic (const DBusString *str,
|
|||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
{
|
||||
volatile dbus_uint32_t *vp = value;
|
||||
pos = _DBUS_ALIGN_VALUE (pos, 4);
|
||||
|
|
@ -839,6 +841,7 @@ _dbus_marshal_write_basic (DBusString *str,
|
|||
break;
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
return marshal_4_octets (str, insert_at, vp->u32,
|
||||
byte_order, pos_after);
|
||||
break;
|
||||
|
|
@ -1066,6 +1069,7 @@ _dbus_marshal_write_fixed_multi (DBusString *str,
|
|||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
|
||||
break;
|
||||
case DBUS_TYPE_INT64:
|
||||
|
|
@ -1114,6 +1118,7 @@ _dbus_marshal_skip_basic (const DBusString *str,
|
|||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
*pos = _DBUS_ALIGN_VALUE (*pos, 4);
|
||||
*pos += 4;
|
||||
break;
|
||||
|
|
@ -1202,6 +1207,7 @@ _dbus_type_get_alignment (int typecode)
|
|||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
/* this stuff is 4 since it starts with a length */
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
|
|
@ -1256,6 +1262,7 @@ _dbus_type_is_valid (int typecode)
|
|||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_DICT_ENTRY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
|
|
@ -1316,6 +1323,8 @@ _dbus_type_to_string (int typecode)
|
|||
return "begin_dict_entry";
|
||||
case DBUS_DICT_ENTRY_END_CHAR:
|
||||
return "end_dict_entry";
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
return "unix_fd";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,21 +26,27 @@
|
|||
#define DBUS_MARSHAL_BASIC_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus-protocol.h>
|
||||
#include <dbus/dbus-types.h>
|
||||
#include <dbus/dbus-arch-deps.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
|
||||
#ifndef PACKAGE
|
||||
#error "config.h not included here"
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define DBUS_COMPILER_BYTE_ORDER DBUS_BIG_ENDIAN
|
||||
#else
|
||||
#define DBUS_COMPILER_BYTE_ORDER DBUS_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
#define DBUS_UINT16_SWAP_LE_BE_CONSTANT(val) bswap_16(val)
|
||||
#define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val) bswap_32(val)
|
||||
#else /* HAVE_BYTESWAP_H */
|
||||
|
||||
#define DBUS_UINT16_SWAP_LE_BE_CONSTANT(val) ((dbus_uint16_t) ( \
|
||||
(dbus_uint16_t) ((dbus_uint16_t) (val) >> 8) | \
|
||||
(dbus_uint16_t) ((dbus_uint16_t) (val) << 8)))
|
||||
|
|
@ -51,8 +57,14 @@
|
|||
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >> 8) | \
|
||||
(((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24)))
|
||||
|
||||
#endif /* HAVE_BYTESWAP_H */
|
||||
|
||||
#ifdef DBUS_HAVE_INT64
|
||||
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val) bswap_64(val)
|
||||
#else /* HAVE_BYTESWAP_H */
|
||||
|
||||
#define DBUS_UINT64_SWAP_LE_BE_CONSTANT(val) ((dbus_uint64_t) ( \
|
||||
(((dbus_uint64_t) (val) & \
|
||||
(dbus_uint64_t) DBUS_UINT64_CONSTANT (0x00000000000000ff)) << 56) | \
|
||||
|
|
@ -72,6 +84,8 @@
|
|||
(dbus_uint64_t) DBUS_UINT64_CONSTANT (0xff00000000000000)) >> 56)))
|
||||
#endif /* DBUS_HAVE_INT64 */
|
||||
|
||||
#endif /* HAVE_BYTESWAP_H */
|
||||
|
||||
#define DBUS_UINT16_SWAP_LE_BE(val) (DBUS_UINT16_SWAP_LE_BE_CONSTANT (val))
|
||||
#define DBUS_INT16_SWAP_LE_BE(val) ((dbus_int16_t)DBUS_UINT16_SWAP_LE_BE_CONSTANT (val))
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,11 @@ byteswap_body_helper (DBusTypeReader *reader,
|
|||
}
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
/* fds can only be passed on a local machine, so byte order must always match */
|
||||
_dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense");
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@
|
|||
#include <dbus/dbus-protocol.h>
|
||||
#include <dbus/dbus-marshal-recursive.h>
|
||||
|
||||
#ifndef PACKAGE
|
||||
#error "config.h not included here"
|
||||
#endif
|
||||
|
||||
void _dbus_marshal_byteswap (const DBusString *signature,
|
||||
int signature_start,
|
||||
int old_byte_order,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,8 @@ _dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
|
|||
{ DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
|
||||
{ DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
|
||||
{ DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
|
||||
{ DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }
|
||||
{ DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE },
|
||||
{ DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 }
|
||||
};
|
||||
|
||||
/** Macro to look up the correct type for a field */
|
||||
|
|
@ -888,6 +889,10 @@ load_and_validate_field (DBusHeader *header,
|
|||
}
|
||||
break;
|
||||
|
||||
case DBUS_HEADER_FIELD_UNIX_FDS:
|
||||
/* Every value makes sense */
|
||||
break;
|
||||
|
||||
case DBUS_HEADER_FIELD_SIGNATURE:
|
||||
/* SIGNATURE validated generically due to its type */
|
||||
string_validation_func = NULL;
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@
|
|||
#include <dbus/dbus-marshal-basic.h>
|
||||
#include <dbus/dbus-marshal-validate.h>
|
||||
|
||||
#ifndef PACKAGE
|
||||
#error "config.h not included here"
|
||||
#endif
|
||||
|
||||
typedef struct DBusHeader DBusHeader;
|
||||
typedef struct DBusHeaderField DBusHeaderField;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@
|
|||
#include <dbus/dbus-protocol.h>
|
||||
#include <dbus/dbus-list.h>
|
||||
|
||||
#ifndef PACKAGE
|
||||
#error "config.h not included here"
|
||||
#endif
|
||||
|
||||
typedef struct DBusTypeReader DBusTypeReader;
|
||||
typedef struct DBusTypeWriter DBusTypeWriter;
|
||||
typedef struct DBusTypeReaderClass DBusTypeReaderClass;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
|
|||
case DBUS_TYPE_UINT16:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
|
|
@ -319,12 +320,13 @@ validate_body_helper (DBusTypeReader *reader,
|
|||
case DBUS_TYPE_BYTE:
|
||||
++p;
|
||||
break;
|
||||
|
||||
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_INT16:
|
||||
case DBUS_TYPE_UINT16:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
|
|
|
|||
|
|
@ -26,10 +26,6 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
#ifndef PACKAGE
|
||||
#error "config.h not included here"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup DBusMarshal
|
||||
*
|
||||
|
|
@ -117,6 +113,7 @@ typedef enum
|
|||
DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS = 53,
|
||||
DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY = 54,
|
||||
DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE = 55,
|
||||
DBUS_INVALID_MISSING_UNIX_FDS = 56,
|
||||
DBUS_VALIDITY_LAST
|
||||
} DBusValidity;
|
||||
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ _dbus_md5_final (DBusMD5Context *context,
|
|||
/* some kind of security paranoia, though it seems pointless
|
||||
* to me given the nonzeroed stuff flying around
|
||||
*/
|
||||
memset ((void*)context, '\0', sizeof (DBusMD5Context));
|
||||
_DBUS_ZERO(*context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ void* dbus_realloc (void *memory,
|
|||
size_t bytes);
|
||||
void dbus_free (void *memory);
|
||||
|
||||
#define dbus_new(type, count) ((type*)dbus_malloc (sizeof (type) * (count)));
|
||||
#define dbus_new0(type, count) ((type*)dbus_malloc0 (sizeof (type) * (count)));
|
||||
#define dbus_new(type, count) ((type*)dbus_malloc (sizeof (type) * (count)))
|
||||
#define dbus_new0(type, count) ((type*)dbus_malloc0 (sizeof (type) * (count)))
|
||||
|
||||
void dbus_free_string_array (char **str_array);
|
||||
|
||||
|
|
|
|||
|
|
@ -949,6 +949,7 @@ static const int typecodes[] = {
|
|||
DBUS_STRUCT_END_CHAR,
|
||||
DBUS_DICT_ENTRY_BEGIN_CHAR,
|
||||
DBUS_DICT_ENTRY_END_CHAR,
|
||||
DBUS_TYPE_UNIX_FD,
|
||||
255 /* random invalid typecode */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -34,14 +34,17 @@ typedef struct DBusMessageLoader DBusMessageLoader;
|
|||
void _dbus_message_get_network_data (DBusMessage *message,
|
||||
const DBusString **header,
|
||||
const DBusString **body);
|
||||
void _dbus_message_get_unix_fds (DBusMessage *message,
|
||||
const int **fds,
|
||||
unsigned *n_fds);
|
||||
|
||||
void _dbus_message_lock (DBusMessage *message);
|
||||
void _dbus_message_unlock (DBusMessage *message);
|
||||
dbus_bool_t _dbus_message_add_size_counter (DBusMessage *message,
|
||||
dbus_bool_t _dbus_message_add_counter (DBusMessage *message,
|
||||
DBusCounter *counter);
|
||||
void _dbus_message_add_size_counter_link (DBusMessage *message,
|
||||
void _dbus_message_add_counter_link (DBusMessage *message,
|
||||
DBusList *link);
|
||||
void _dbus_message_remove_size_counter (DBusMessage *message,
|
||||
void _dbus_message_remove_counter (DBusMessage *message,
|
||||
DBusCounter *counter,
|
||||
DBusList **link_return);
|
||||
|
||||
|
|
@ -54,6 +57,14 @@ void _dbus_message_loader_get_buffer (DBusMessageLoader
|
|||
void _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
|
||||
DBusString *buffer,
|
||||
int bytes_read);
|
||||
|
||||
dbus_bool_t _dbus_message_loader_get_unix_fds (DBusMessageLoader *loader,
|
||||
int **fds,
|
||||
unsigned *max_n_fds);
|
||||
void _dbus_message_loader_return_unix_fds (DBusMessageLoader *loader,
|
||||
int *fds,
|
||||
unsigned n_fds);
|
||||
|
||||
dbus_bool_t _dbus_message_loader_queue_messages (DBusMessageLoader *loader);
|
||||
DBusMessage* _dbus_message_loader_peek_message (DBusMessageLoader *loader);
|
||||
DBusMessage* _dbus_message_loader_pop_message (DBusMessageLoader *loader);
|
||||
|
|
@ -67,6 +78,10 @@ void _dbus_message_loader_set_max_message_size (DBusMessageLoader
|
|||
long size);
|
||||
long _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader);
|
||||
|
||||
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader,
|
||||
long n);
|
||||
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader);
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_MESSAGE_INTERNAL_H */
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#ifndef DBUS_MESSAGE_PRIVATE_H
|
||||
#define DBUS_MESSAGE_PRIVATE_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dbus/dbus-message.h>
|
||||
#include <dbus/dbus-message-internal.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
|
|
@ -66,12 +68,21 @@ struct DBusMessageLoader
|
|||
DBusList *messages; /**< Complete messages. */
|
||||
|
||||
long max_message_size; /**< Maximum size of a message */
|
||||
long max_message_unix_fds; /**< Maximum unix fds in a message */
|
||||
|
||||
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
|
||||
DBusValidity corruption_reason; /**< why we were corrupted */
|
||||
|
||||
unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
|
||||
|
||||
DBusValidity corruption_reason; /**< why we were corrupted */
|
||||
unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
unsigned int unix_fds_outstanding : 1; /**< Someone is using the unix fd array to read */
|
||||
|
||||
int *unix_fds; /**< File descriptors that have been read from the transport but not yet been handed to any message. Array will be allocated at first use. */
|
||||
unsigned n_unix_fds_allocated; /**< Number of file descriptors this array has space for */
|
||||
unsigned n_unix_fds; /**< Number of valid file descriptors in array */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -100,8 +111,8 @@ struct DBusMessage
|
|||
#ifndef DBUS_DISABLE_CHECKS
|
||||
unsigned int in_cache : 1; /**< Has been "freed" since it's in the cache (this is a debug feature) */
|
||||
#endif
|
||||
|
||||
DBusList *size_counters; /**< 0-N DBusCounter used to track message size. */
|
||||
|
||||
DBusList *counters; /**< 0-N DBusCounter used to track message size/unix fds. */
|
||||
long size_counter_delta; /**< Size we incremented the size counters by. */
|
||||
|
||||
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
|
||||
|
|
@ -111,6 +122,17 @@ struct DBusMessage
|
|||
#ifndef DBUS_DISABLE_CHECKS
|
||||
int generation; /**< _dbus_current_generation when message was created */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
int *unix_fds;
|
||||
/**< Unix file descriptors associated with this message. These are
|
||||
closed when the message is destroyed, hence make sure to dup()
|
||||
them when adding or removing them here. */
|
||||
unsigned n_unix_fds; /**< Number of valid fds in the array */
|
||||
unsigned n_unix_fds_allocated; /**< Allocated size of the array */
|
||||
|
||||
long unix_fd_counter_delta; /**< Size we incremented the unix fd counter by */
|
||||
#endif
|
||||
};
|
||||
|
||||
dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
|
||||
|
|
@ -118,6 +140,9 @@ dbus_bool_t _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
|
|||
int first_arg_type,
|
||||
va_list var_args);
|
||||
|
||||
|
||||
void _dbus_check_fdleaks(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
|
|
|||
|
|
@ -27,6 +27,17 @@
|
|||
#include "dbus-message-private.h"
|
||||
#include "dbus-marshal-recursive.h"
|
||||
#include "dbus-string.h"
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
#include "dbus-sysdeps-unix.h"
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
/* Necessary for the Linux-specific fd leak checking code only */
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup DBusMessage
|
||||
|
|
@ -126,6 +137,50 @@ check_memleaks (void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
_dbus_check_fdleaks(void)
|
||||
{
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
DIR *d;
|
||||
|
||||
/* This works on Linux only */
|
||||
|
||||
if ((d = opendir("/proc/self/fd")))
|
||||
{
|
||||
struct dirent *de;
|
||||
|
||||
while ((de = readdir(d)))
|
||||
{
|
||||
long l;
|
||||
char *e = NULL;
|
||||
int fd;
|
||||
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
errno = 0;
|
||||
l = strtol(de->d_name, &e, 10);
|
||||
_dbus_assert(errno == 0 && e && !*e);
|
||||
|
||||
fd = (int) l;
|
||||
|
||||
if (fd < 3)
|
||||
continue;
|
||||
|
||||
if (fd == dirfd(d))
|
||||
continue;
|
||||
|
||||
_dbus_warn("file descriptor %i leaked in %s.\n", fd, __FILE__);
|
||||
_dbus_assert_not_reached("fdleaks");
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
check_have_valid_message (DBusMessageLoader *loader)
|
||||
{
|
||||
|
|
@ -895,7 +950,7 @@ verify_test_message (DBusMessage *message)
|
|||
dbus_bool_t
|
||||
_dbus_message_test (const char *test_data_dir)
|
||||
{
|
||||
DBusMessage *message;
|
||||
DBusMessage *message, *message_without_unix_fds;
|
||||
DBusMessageLoader *loader;
|
||||
int i;
|
||||
const char *data;
|
||||
|
|
@ -940,6 +995,9 @@ _dbus_message_test (const char *test_data_dir)
|
|||
unsigned char v2_BYTE;
|
||||
dbus_bool_t v_BOOLEAN;
|
||||
DBusMessageIter iter, array_iter, struct_iter;
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
int v_UNIX_FD;
|
||||
#endif
|
||||
|
||||
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
|
||||
"/org/freedesktop/TestPath",
|
||||
|
|
@ -1058,6 +1116,9 @@ _dbus_message_test (const char *test_data_dir)
|
|||
v_BOOLEAN = TRUE;
|
||||
v_BYTE = 42;
|
||||
v2_BYTE = 24;
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
v_UNIX_FD = 1;
|
||||
#endif
|
||||
|
||||
dbus_message_append_args (message,
|
||||
DBUS_TYPE_INT16, &v_INT16,
|
||||
|
|
@ -1091,6 +1152,7 @@ _dbus_message_test (const char *test_data_dir)
|
|||
_DBUS_N_ELEMENTS (our_boolean_array),
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &v_ARRAY_STRING,
|
||||
_DBUS_N_ELEMENTS (our_string_array),
|
||||
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
i = 0;
|
||||
|
|
@ -1125,7 +1187,16 @@ _dbus_message_test (const char *test_data_dir)
|
|||
sig[i++] = DBUS_TYPE_BOOLEAN;
|
||||
sig[i++] = DBUS_TYPE_ARRAY;
|
||||
sig[i++] = DBUS_TYPE_STRING;
|
||||
sig[i++] = DBUS_TYPE_INVALID;
|
||||
|
||||
message_without_unix_fds = dbus_message_copy(message);
|
||||
_dbus_assert(message_without_unix_fds);
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
dbus_message_append_args (message,
|
||||
DBUS_TYPE_UNIX_FD, &v_UNIX_FD,
|
||||
DBUS_TYPE_INVALID);
|
||||
sig[i++] = DBUS_TYPE_UNIX_FD;
|
||||
#endif
|
||||
sig[i++] = DBUS_TYPE_INVALID;
|
||||
|
||||
_dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
|
||||
|
||||
|
|
@ -1202,6 +1273,20 @@ _dbus_message_test (const char *test_data_dir)
|
|||
_dbus_message_loader_return_buffer (loader, buffer, 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
{
|
||||
int *unix_fds;
|
||||
unsigned n_unix_fds;
|
||||
/* Write unix fd */
|
||||
_dbus_message_loader_get_unix_fds(loader, &unix_fds, &n_unix_fds);
|
||||
_dbus_assert(n_unix_fds > 0);
|
||||
_dbus_assert(message->n_unix_fds == 1);
|
||||
unix_fds[0] = _dbus_dup(message->unix_fds[0], NULL);
|
||||
_dbus_assert(unix_fds[0] >= 0);
|
||||
_dbus_message_loader_return_unix_fds(loader, unix_fds, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
dbus_message_unref (message);
|
||||
|
||||
/* Now pop back the message */
|
||||
|
|
@ -1218,7 +1303,14 @@ _dbus_message_test (const char *test_data_dir)
|
|||
if (dbus_message_get_reply_serial (message) != 5678)
|
||||
_dbus_assert_not_reached ("reply serial fields differ");
|
||||
|
||||
verify_test_message (message);
|
||||
dbus_message_unref (message);
|
||||
|
||||
/* ovveride the serial, since it was reset by dbus_message_copy() */
|
||||
dbus_message_set_serial(message_without_unix_fds, 8901);
|
||||
|
||||
dbus_message_lock (message_without_unix_fds);
|
||||
|
||||
verify_test_message (message_without_unix_fds);
|
||||
|
||||
{
|
||||
/* Marshal and demarshal the message. */
|
||||
|
|
@ -1229,7 +1321,7 @@ _dbus_message_test (const char *test_data_dir)
|
|||
int len = 0;
|
||||
char garbage_header[DBUS_MINIMUM_HEADER_SIZE] = "xxx";
|
||||
|
||||
if (!dbus_message_marshal (message, &marshalled, &len))
|
||||
if (!dbus_message_marshal (message_without_unix_fds, &marshalled, &len))
|
||||
_dbus_assert_not_reached ("failed to marshal message");
|
||||
|
||||
_dbus_assert (len != 0);
|
||||
|
|
@ -1268,10 +1360,11 @@ _dbus_message_test (const char *test_data_dir)
|
|||
_dbus_assert (dbus_message_demarshal_bytes_needed (garbage_header, DBUS_MINIMUM_HEADER_SIZE) == -1);
|
||||
}
|
||||
|
||||
dbus_message_unref (message);
|
||||
dbus_message_unref (message_without_unix_fds);
|
||||
_dbus_message_loader_unref (loader);
|
||||
|
||||
check_memleaks ();
|
||||
_dbus_check_fdleaks();
|
||||
|
||||
/* Check that we can abandon a container */
|
||||
message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
|
||||
|
|
@ -1333,9 +1426,10 @@ _dbus_message_test (const char *test_data_dir)
|
|||
print_validities_seen (FALSE);
|
||||
print_validities_seen (TRUE);
|
||||
}
|
||||
|
||||
|
||||
check_memleaks ();
|
||||
|
||||
_dbus_check_fdleaks();
|
||||
|
||||
/* Now load every message in test_data_dir if we have one */
|
||||
if (test_data_dir == NULL)
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@
|
|||
#include "dbus-memory.h"
|
||||
#include "dbus-list.h"
|
||||
#include "dbus-threads-internal.h"
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
#include "dbus-sysdeps-unix.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void dbus_message_finalize (DBusMessage *message);
|
||||
|
|
@ -159,6 +163,30 @@ _dbus_message_get_network_data (DBusMessage *message,
|
|||
*body = &message->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unix fds to be sent over the network for this message.
|
||||
* This function is guaranteed to always return the same data once a
|
||||
* message is locked (with dbus_message_lock()).
|
||||
*
|
||||
* @param message the message.
|
||||
* @param fds return location of unix fd array
|
||||
* @param n_fds return number of entries in array
|
||||
*/
|
||||
void _dbus_message_get_unix_fds(DBusMessage *message,
|
||||
const int **fds,
|
||||
unsigned *n_fds)
|
||||
{
|
||||
_dbus_assert (message->locked);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
*fds = message->unix_fds;
|
||||
*n_fds = message->n_unix_fds;
|
||||
#else
|
||||
*fds = NULL;
|
||||
*n_fds = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serial number of a message.
|
||||
* This can only be done once on a message.
|
||||
|
|
@ -181,20 +209,19 @@ dbus_message_set_serial (DBusMessage *message,
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds a counter to be incremented immediately with the
|
||||
* size of this message, and decremented by the size
|
||||
* of this message when this message if finalized.
|
||||
* The link contains a counter with its refcount already
|
||||
* incremented, but the counter itself not incremented.
|
||||
* Ownership of link and counter refcount is passed to
|
||||
* the message.
|
||||
* Adds a counter to be incremented immediately with the size/unix fds
|
||||
* of this message, and decremented by the size/unix fds of this
|
||||
* message when this message if finalized. The link contains a
|
||||
* counter with its refcount already incremented, but the counter
|
||||
* itself not incremented. Ownership of link and counter refcount is
|
||||
* passed to the message.
|
||||
*
|
||||
* @param message the message
|
||||
* @param link link with counter as data
|
||||
*/
|
||||
void
|
||||
_dbus_message_add_size_counter_link (DBusMessage *message,
|
||||
DBusList *link)
|
||||
_dbus_message_add_counter_link (DBusMessage *message,
|
||||
DBusList *link)
|
||||
{
|
||||
/* right now we don't recompute the delta when message
|
||||
* size changes, and that's OK for current purposes
|
||||
|
|
@ -202,35 +229,43 @@ _dbus_message_add_size_counter_link (DBusMessage *message,
|
|||
* Do recompute it whenever there are no outstanding counters,
|
||||
* since it's basically free.
|
||||
*/
|
||||
if (message->size_counters == NULL)
|
||||
if (message->counters == NULL)
|
||||
{
|
||||
message->size_counter_delta =
|
||||
_dbus_string_get_length (&message->header.data) +
|
||||
_dbus_string_get_length (&message->body);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
message->unix_fd_counter_delta = message->n_unix_fds;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
_dbus_verbose ("message has size %ld\n",
|
||||
message->size_counter_delta);
|
||||
#endif
|
||||
}
|
||||
|
||||
_dbus_list_append_link (&message->size_counters, link);
|
||||
_dbus_list_append_link (&message->counters, link);
|
||||
|
||||
_dbus_counter_adjust (link->data, message->size_counter_delta);
|
||||
_dbus_counter_adjust_size (link->data, message->size_counter_delta);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a counter to be incremented immediately with the
|
||||
* size of this message, and decremented by the size
|
||||
* of this message when this message if finalized.
|
||||
* Adds a counter to be incremented immediately with the size/unix fds
|
||||
* of this message, and decremented by the size/unix fds of this
|
||||
* message when this message if finalized.
|
||||
*
|
||||
* @param message the message
|
||||
* @param counter the counter
|
||||
* @returns #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_message_add_size_counter (DBusMessage *message,
|
||||
DBusCounter *counter)
|
||||
_dbus_message_add_counter (DBusMessage *message,
|
||||
DBusCounter *counter)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
|
|
@ -239,38 +274,42 @@ _dbus_message_add_size_counter (DBusMessage *message,
|
|||
return FALSE;
|
||||
|
||||
_dbus_counter_ref (counter);
|
||||
_dbus_message_add_size_counter_link (message, link);
|
||||
_dbus_message_add_counter_link (message, link);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a counter tracking the size of this message, and decrements
|
||||
* the counter by the size of this message.
|
||||
* Removes a counter tracking the size/unix fds of this message, and
|
||||
* decrements the counter by the size/unix fds of this message.
|
||||
*
|
||||
* @param message the message
|
||||
* @param link_return return the link used
|
||||
* @param counter the counter
|
||||
*/
|
||||
void
|
||||
_dbus_message_remove_size_counter (DBusMessage *message,
|
||||
DBusCounter *counter,
|
||||
DBusList **link_return)
|
||||
_dbus_message_remove_counter (DBusMessage *message,
|
||||
DBusCounter *counter,
|
||||
DBusList **link_return)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
link = _dbus_list_find_last (&message->size_counters,
|
||||
link = _dbus_list_find_last (&message->counters,
|
||||
counter);
|
||||
_dbus_assert (link != NULL);
|
||||
|
||||
_dbus_list_unlink (&message->size_counters,
|
||||
_dbus_list_unlink (&message->counters,
|
||||
link);
|
||||
if (link_return)
|
||||
*link_return = link;
|
||||
else
|
||||
_dbus_list_free_link (link);
|
||||
|
||||
_dbus_counter_adjust (counter, - message->size_counter_delta);
|
||||
_dbus_counter_adjust_size (counter, - message->size_counter_delta);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
|
||||
#endif
|
||||
|
||||
_dbus_counter_unref (counter);
|
||||
}
|
||||
|
|
@ -487,21 +526,51 @@ dbus_message_get_cached (void)
|
|||
_dbus_assert (message != NULL);
|
||||
|
||||
_dbus_assert (message->refcount.value == 0);
|
||||
_dbus_assert (message->size_counters == NULL);
|
||||
_dbus_assert (message->counters == NULL);
|
||||
|
||||
_DBUS_UNLOCK (message_cache);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
static void
|
||||
free_size_counter (void *element,
|
||||
void *data)
|
||||
close_unix_fds(int *fds, unsigned *n_fds)
|
||||
{
|
||||
DBusError e;
|
||||
int i;
|
||||
|
||||
if (*n_fds <= 0)
|
||||
return;
|
||||
|
||||
dbus_error_init(&e);
|
||||
|
||||
for (i = 0; i < *n_fds; i++)
|
||||
{
|
||||
if (!_dbus_close(fds[i], &e))
|
||||
{
|
||||
_dbus_warn("Failed to close file descriptor: %s\n", e.message);
|
||||
dbus_error_free(&e);
|
||||
}
|
||||
}
|
||||
|
||||
*n_fds = 0;
|
||||
|
||||
/* We don't free the array here, in case we can recycle it later */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
free_counter (void *element,
|
||||
void *data)
|
||||
{
|
||||
DBusCounter *counter = element;
|
||||
DBusMessage *message = data;
|
||||
|
||||
_dbus_counter_adjust (counter, - message->size_counter_delta);
|
||||
_dbus_counter_adjust_size (counter, - message->size_counter_delta);
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
|
||||
#endif
|
||||
|
||||
_dbus_counter_unref (counter);
|
||||
}
|
||||
|
|
@ -524,9 +593,13 @@ dbus_message_cache_or_finalize (DBusMessage *message)
|
|||
*/
|
||||
_dbus_data_slot_list_clear (&message->slot_list);
|
||||
|
||||
_dbus_list_foreach (&message->size_counters,
|
||||
free_size_counter, message);
|
||||
_dbus_list_clear (&message->size_counters);
|
||||
_dbus_list_foreach (&message->counters,
|
||||
free_counter, message);
|
||||
_dbus_list_clear (&message->counters);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
close_unix_fds(message->unix_fds, &message->n_unix_fds);
|
||||
#endif
|
||||
|
||||
was_cached = FALSE;
|
||||
|
||||
|
|
@ -634,6 +707,8 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
|
|||
* dbus_message_get_args() is the place to go for complete
|
||||
* documentation.
|
||||
*
|
||||
* @todo This may leak memory and file descriptors if parsing fails. See #21259
|
||||
*
|
||||
* @see dbus_message_get_args
|
||||
* @param iter the message iter
|
||||
* @param error error to be filled in
|
||||
|
|
@ -673,7 +748,38 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (dbus_type_is_basic (spec_type))
|
||||
if (spec_type == DBUS_TYPE_UNIX_FD)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
DBusBasicValue idx;
|
||||
int *pfd, nfd;
|
||||
|
||||
pfd = va_arg (var_args, int*);
|
||||
_dbus_assert(pfd);
|
||||
|
||||
_dbus_type_reader_read_basic(&real->u.reader, &idx);
|
||||
|
||||
if (idx.u32 >= real->message->n_unix_fds)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
|
||||
"Message refers to file descriptor at index %i,"
|
||||
"but has only %i descriptors attached.\n",
|
||||
idx.u32,
|
||||
real->message->n_unix_fds);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
|
||||
goto out;
|
||||
|
||||
*pfd = nfd;
|
||||
#else
|
||||
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
|
||||
"Platform does not support file desciptor passing.\n");
|
||||
goto out;
|
||||
#endif
|
||||
}
|
||||
else if (dbus_type_is_basic (spec_type))
|
||||
{
|
||||
DBusBasicValue *ptr;
|
||||
|
||||
|
|
@ -707,7 +813,8 @@ _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (dbus_type_is_fixed (spec_element_type))
|
||||
if (dbus_type_is_fixed (spec_element_type) &&
|
||||
element_type != DBUS_TYPE_UNIX_FD)
|
||||
{
|
||||
ptr = va_arg (var_args, const DBusBasicValue**);
|
||||
n_elements_p = va_arg (var_args, int*);
|
||||
|
|
@ -936,13 +1043,18 @@ dbus_message_finalize (DBusMessage *message)
|
|||
/* This calls application callbacks! */
|
||||
_dbus_data_slot_list_free (&message->slot_list);
|
||||
|
||||
_dbus_list_foreach (&message->size_counters,
|
||||
free_size_counter, message);
|
||||
_dbus_list_clear (&message->size_counters);
|
||||
_dbus_list_foreach (&message->counters,
|
||||
free_counter, message);
|
||||
_dbus_list_clear (&message->counters);
|
||||
|
||||
_dbus_header_free (&message->header);
|
||||
_dbus_string_free (&message->body);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
close_unix_fds(message->unix_fds, &message->n_unix_fds);
|
||||
dbus_free(message->unix_fds);
|
||||
#endif
|
||||
|
||||
_dbus_assert (message->refcount.value == 0);
|
||||
|
||||
dbus_free (message);
|
||||
|
|
@ -969,6 +1081,11 @@ dbus_message_new_empty_header (void)
|
|||
#ifndef DBUS_DISABLE_CHECKS
|
||||
message->generation = _dbus_current_generation;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
message->unix_fds = NULL;
|
||||
message->n_unix_fds_allocated = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
message->refcount.value = 1;
|
||||
|
|
@ -977,10 +1094,15 @@ dbus_message_new_empty_header (void)
|
|||
#ifndef DBUS_DISABLE_CHECKS
|
||||
message->in_cache = FALSE;
|
||||
#endif
|
||||
message->size_counters = NULL;
|
||||
message->counters = NULL;
|
||||
message->size_counter_delta = 0;
|
||||
message->changed_stamp = 0;
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
message->n_unix_fds = 0;
|
||||
message->unix_fd_counter_delta = 0;
|
||||
#endif
|
||||
|
||||
if (!from_cache)
|
||||
_dbus_data_slot_list_init (&message->slot_list);
|
||||
|
||||
|
|
@ -1308,8 +1430,10 @@ dbus_message_new_error_printf (DBusMessage *reply_to,
|
|||
* outgoing message queue and thus not modifiable) the new message
|
||||
* will not be locked.
|
||||
*
|
||||
* @todo This function can't be used in programs that try to recover from OOM errors.
|
||||
*
|
||||
* @param message the message
|
||||
* @returns the new message.or #NULL if not enough memory
|
||||
* @returns the new message.or #NULL if not enough memory or Unix file descriptors (in case the message to copy includes Unix file descriptors) can be allocated.
|
||||
*/
|
||||
DBusMessage *
|
||||
dbus_message_copy (const DBusMessage *message)
|
||||
|
|
@ -1347,11 +1471,36 @@ dbus_message_copy (const DBusMessage *message)
|
|||
&retval->body, 0))
|
||||
goto failed_copy;
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
retval->unix_fds = dbus_new(int, message->n_unix_fds);
|
||||
if (retval->unix_fds == NULL && message->n_unix_fds > 0)
|
||||
goto failed_copy;
|
||||
|
||||
retval->n_unix_fds_allocated = message->n_unix_fds;
|
||||
|
||||
for (retval->n_unix_fds = 0;
|
||||
retval->n_unix_fds < message->n_unix_fds;
|
||||
retval->n_unix_fds++)
|
||||
{
|
||||
retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
|
||||
|
||||
if (retval->unix_fds[retval->n_unix_fds] < 0)
|
||||
goto failed_copy;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
|
||||
failed_copy:
|
||||
_dbus_header_free (&retval->header);
|
||||
_dbus_string_free (&retval->body);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
|
||||
dbus_free(retval->unix_fds);
|
||||
#endif
|
||||
|
||||
dbus_free (retval);
|
||||
|
||||
return NULL;
|
||||
|
|
@ -1429,9 +1578,10 @@ dbus_message_get_type (DBusMessage *message)
|
|||
* Appends fields to a message given a variable argument list. The
|
||||
* variable argument list should contain the type of each argument
|
||||
* followed by the value to append. Appendable types are basic types,
|
||||
* and arrays of fixed-length basic types. To append variable-length
|
||||
* basic types, or any more complex value, you have to use an iterator
|
||||
* rather than this function.
|
||||
* and arrays of fixed-length basic types (except arrays of Unix file
|
||||
* descriptors). To append variable-length basic types, or any more
|
||||
* complex value, you have to use an iterator rather than this
|
||||
* function.
|
||||
*
|
||||
* To append a basic type, specify its type code followed by the
|
||||
* address of the value. For example:
|
||||
|
|
@ -1446,18 +1596,22 @@ dbus_message_get_type (DBusMessage *message)
|
|||
* DBUS_TYPE_INVALID);
|
||||
* @endcode
|
||||
*
|
||||
* To append an array of fixed-length basic types, pass in the
|
||||
* DBUS_TYPE_ARRAY typecode, the element typecode, the address of
|
||||
* the array pointer, and a 32-bit integer giving the number of
|
||||
* elements in the array. So for example:
|
||||
* @code
|
||||
* const dbus_int32_t array[] = { 1, 2, 3 };
|
||||
* const dbus_int32_t *v_ARRAY = array;
|
||||
* dbus_message_append_args (message,
|
||||
* DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3,
|
||||
* DBUS_TYPE_INVALID);
|
||||
* To append an array of fixed-length basic types (except Unix file
|
||||
* descriptors), pass in the DBUS_TYPE_ARRAY typecode, the element
|
||||
* typecode, the address of the array pointer, and a 32-bit integer
|
||||
* giving the number of elements in the array. So for example: @code
|
||||
* const dbus_int32_t array[] = { 1, 2, 3 }; const dbus_int32_t
|
||||
* *v_ARRAY = array; dbus_message_append_args (message,
|
||||
* DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3, DBUS_TYPE_INVALID);
|
||||
* @endcode
|
||||
*
|
||||
* This function does not support arrays of Unix file descriptors. If
|
||||
* you need those you need to manually recurse into the array.
|
||||
*
|
||||
* For Unix file descriptors this function will internally duplicate
|
||||
* the descriptor you passed in. Hence you may close the descriptor
|
||||
* immediately after this call.
|
||||
*
|
||||
* @warning in C, given "int array[]", "&array == array" (the
|
||||
* comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
|
||||
* So if you're using an array instead of a pointer you have to create
|
||||
|
|
@ -1555,8 +1709,9 @@ dbus_message_append_args_valist (DBusMessage *message,
|
|||
buf,
|
||||
&array))
|
||||
goto failed;
|
||||
|
||||
if (dbus_type_is_fixed (element_type))
|
||||
|
||||
if (dbus_type_is_fixed (element_type) &&
|
||||
element_type != DBUS_TYPE_UNIX_FD)
|
||||
{
|
||||
const DBusBasicValue **value;
|
||||
int n_elements;
|
||||
|
|
@ -1639,7 +1794,16 @@ dbus_message_append_args_valist (DBusMessage *message,
|
|||
* signature are supported; but these are returned as allocated memory
|
||||
* and must be freed with dbus_free_string_array(), while the other
|
||||
* types are returned as const references. To get a string array
|
||||
* pass in "char ***array_location" and "int *n_elements"
|
||||
* pass in "char ***array_location" and "int *n_elements".
|
||||
*
|
||||
* Similar to dbus_message_get_fixed_array() this function does not
|
||||
* support arrays of type DBUS_TYPE_UNIX_FD. If you need to parse
|
||||
* messages with arrays of Unix file descriptors you need to recurse
|
||||
* into the array manually.
|
||||
*
|
||||
* Unix file descriptors that are read with this function will have
|
||||
* the FD_CLOEXEC flag set. If you need them without this flag set,
|
||||
* make sure to unset it with fcntl().
|
||||
*
|
||||
* The variable argument list should contain the type of the argument
|
||||
* followed by a pointer to where the value should be stored. The list
|
||||
|
|
@ -1864,10 +2028,10 @@ dbus_message_iter_get_element_type (DBusMessageIter *iter)
|
|||
* you won't be able to recurse further. There's no array of int32 to
|
||||
* recurse into.
|
||||
*
|
||||
* If a container is an array of fixed-length types, it is much more
|
||||
* efficient to use dbus_message_iter_get_fixed_array() to get the
|
||||
* whole array in one shot, rather than individually walking over the
|
||||
* array elements.
|
||||
* If a container is an array of fixed-length types (except Unix file
|
||||
* descriptors), it is much more efficient to use
|
||||
* dbus_message_iter_get_fixed_array() to get the whole array in one
|
||||
* shot, rather than individually walking over the array elements.
|
||||
*
|
||||
* Be sure you have somehow checked that
|
||||
* dbus_message_iter_get_arg_type() matches the type you are expecting
|
||||
|
|
@ -1937,17 +2101,24 @@ dbus_message_iter_get_signature (DBusMessageIter *iter)
|
|||
* and for string a "const char**". The returned value is
|
||||
* by reference and should not be freed.
|
||||
*
|
||||
* This call duplicates Unix file descriptors when reading them. It is
|
||||
* your job to close them when you don't need them anymore.
|
||||
*
|
||||
* Unix file descriptors that are read with this function will have
|
||||
* the FD_CLOEXEC flag set. If you need them without this flag set,
|
||||
* make sure to unset it with fcntl().
|
||||
*
|
||||
* Be sure you have somehow checked that
|
||||
* dbus_message_iter_get_arg_type() matches the type you are
|
||||
* expecting, or you'll crash when you try to use an integer as a
|
||||
* string or something.
|
||||
*
|
||||
* To read any container type (array, struct, dict) you will need
|
||||
* to recurse into the container with dbus_message_iter_recurse().
|
||||
* If the container is an array of fixed-length values, you can
|
||||
* get all the array elements at once with
|
||||
* dbus_message_iter_get_fixed_array(). Otherwise, you have to
|
||||
* iterate over the container's contents one value at a time.
|
||||
* To read any container type (array, struct, dict) you will need to
|
||||
* recurse into the container with dbus_message_iter_recurse(). If
|
||||
* the container is an array of fixed-length values (except Unix file
|
||||
* descriptors), you can get all the array elements at once with
|
||||
* dbus_message_iter_get_fixed_array(). Otherwise, you have to iterate
|
||||
* over the container's contents one value at a time.
|
||||
*
|
||||
* All basic-typed values are guaranteed to fit in 8 bytes. So you can
|
||||
* write code like this:
|
||||
|
|
@ -1977,8 +2148,30 @@ dbus_message_iter_get_basic (DBusMessageIter *iter,
|
|||
_dbus_return_if_fail (_dbus_message_iter_check (real));
|
||||
_dbus_return_if_fail (value != NULL);
|
||||
|
||||
_dbus_type_reader_read_basic (&real->u.reader,
|
||||
value);
|
||||
if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
DBusBasicValue idx;
|
||||
|
||||
_dbus_type_reader_read_basic(&real->u.reader, &idx);
|
||||
|
||||
if (idx.u32 >= real->message->n_unix_fds) {
|
||||
/* Hmm, we cannot really signal an error here, so let's make
|
||||
sure to return an invalid fd. */
|
||||
*((int*) value) = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
*((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
|
||||
#else
|
||||
*((int*) value) = -1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
_dbus_type_reader_read_basic (&real->u.reader,
|
||||
value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2015,6 +2208,10 @@ dbus_message_iter_get_array_len (DBusMessageIter *iter)
|
|||
* such as integers, bool, double. The returned block will be from the
|
||||
* current position in the array until the end of the array.
|
||||
*
|
||||
* There is one exception here: although DBUS_TYPE_UNIX_FD is
|
||||
* considered a 'fixed' type arrays of this type may not be read with
|
||||
* this function.
|
||||
*
|
||||
* The message iter should be "in" the array (that is, you recurse into the
|
||||
* array, and then you call dbus_message_iter_get_fixed_array() on the
|
||||
* "sub-iterator" created by dbus_message_iter_recurse()).
|
||||
|
|
@ -2051,7 +2248,7 @@ dbus_message_iter_get_fixed_array (DBusMessageIter *iter,
|
|||
_dbus_return_if_fail (_dbus_message_iter_check (real));
|
||||
_dbus_return_if_fail (value != NULL);
|
||||
_dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
|
||||
dbus_type_is_fixed (subtype));
|
||||
(dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
|
||||
|
||||
_dbus_type_reader_read_fixed_multi (&real->u.reader,
|
||||
value, n_elements);
|
||||
|
|
@ -2250,6 +2447,40 @@ _dbus_message_iter_append_check (DBusMessageRealIter *iter)
|
|||
}
|
||||
#endif /* DBUS_DISABLE_CHECKS */
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
static int *
|
||||
expand_fd_array(DBusMessage *m,
|
||||
unsigned n)
|
||||
{
|
||||
_dbus_assert(m);
|
||||
|
||||
/* This makes space for adding n new fds to the array and returns a
|
||||
pointer to the place were the first fd should be put. */
|
||||
|
||||
if (m->n_unix_fds + n > m->n_unix_fds_allocated)
|
||||
{
|
||||
unsigned k;
|
||||
int *p;
|
||||
|
||||
/* Make twice as much space as necessary */
|
||||
k = (m->n_unix_fds + n) * 2;
|
||||
|
||||
/* Allocate at least four */
|
||||
if (k < 4)
|
||||
k = 4;
|
||||
|
||||
p = dbus_realloc(m->unix_fds, k * sizeof(int));
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
m->unix_fds = p;
|
||||
m->n_unix_fds_allocated = k;
|
||||
}
|
||||
|
||||
return m->unix_fds + m->n_unix_fds;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Appends a basic-typed value to the message. The basic types are the
|
||||
* non-container types such as integer and string.
|
||||
|
|
@ -2257,6 +2488,10 @@ _dbus_message_iter_append_check (DBusMessageRealIter *iter)
|
|||
* The "value" argument should be the address of a basic-typed value.
|
||||
* So for string, const char**. For integer, dbus_int32_t*.
|
||||
*
|
||||
* For Unix file descriptors this function will internally duplicate
|
||||
* the descriptor you passed in. Hence you may close the descriptor
|
||||
* immediately after this call.
|
||||
*
|
||||
* @todo If this fails due to lack of memory, the message is hosed and
|
||||
* you have to start over building the whole message.
|
||||
*
|
||||
|
|
@ -2281,7 +2516,50 @@ dbus_message_iter_append_basic (DBusMessageIter *iter,
|
|||
if (!_dbus_message_iter_open_signature (real))
|
||||
return FALSE;
|
||||
|
||||
ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
|
||||
if (type == DBUS_TYPE_UNIX_FD)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
int *fds;
|
||||
dbus_uint32_t u;
|
||||
|
||||
/* First step, include the fd in the fd list of this message */
|
||||
if (!(fds = expand_fd_array(real->message, 1)))
|
||||
return FALSE;
|
||||
|
||||
*fds = _dbus_dup(*(int*) value, NULL);
|
||||
if (*fds < 0)
|
||||
return FALSE;
|
||||
|
||||
u = real->message->n_unix_fds;
|
||||
|
||||
/* Second step, write the index to the fd */
|
||||
if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
|
||||
_dbus_close(*fds, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
real->message->n_unix_fds += 1;
|
||||
u += 1;
|
||||
|
||||
/* Final step, update the header accordingly */
|
||||
ret = _dbus_header_set_field_basic (&real->message->header,
|
||||
DBUS_HEADER_FIELD_UNIX_FDS,
|
||||
DBUS_TYPE_UINT32,
|
||||
&u);
|
||||
|
||||
/* If any of these operations fail the message is
|
||||
hosed. However, no memory or fds should be leaked since what
|
||||
has been added to message has been added to the message, and
|
||||
can hence be accounted for when the message is being
|
||||
freed. */
|
||||
#else
|
||||
ret = FALSE;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
|
||||
}
|
||||
|
||||
if (!_dbus_message_iter_close_signature (real))
|
||||
ret = FALSE;
|
||||
|
|
@ -2292,10 +2570,10 @@ dbus_message_iter_append_basic (DBusMessageIter *iter,
|
|||
/**
|
||||
* Appends a block of fixed-length values to an array. The
|
||||
* fixed-length types are all basic types that are not string-like. So
|
||||
* int32, double, bool, etc. You must call
|
||||
* dbus_message_iter_open_container() to open an array of values
|
||||
* before calling this function. You may call this function multiple
|
||||
* times (and intermixed with calls to
|
||||
* int32, double, bool, etc. (Unix file descriptors however are not
|
||||
* supported.) You must call dbus_message_iter_open_container() to
|
||||
* open an array of values before calling this function. You may call
|
||||
* this function multiple times (and intermixed with calls to
|
||||
* dbus_message_iter_append_basic()) for the same array.
|
||||
*
|
||||
* The "value" argument should be the address of the array. So for
|
||||
|
|
@ -2318,6 +2596,10 @@ dbus_message_iter_append_basic (DBusMessageIter *iter,
|
|||
* @todo If this fails due to lack of memory, the message is hosed and
|
||||
* you have to start over building the whole message.
|
||||
*
|
||||
* For Unix file descriptors this function will internally duplicate
|
||||
* the descriptor you passed in. Hence you may close the descriptor
|
||||
* immediately after this call.
|
||||
*
|
||||
* @param iter the append iterator
|
||||
* @param element_type the type of the array elements
|
||||
* @param value the address of the array
|
||||
|
|
@ -2335,7 +2617,7 @@ dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
|
|||
|
||||
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
|
||||
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
|
||||
_dbus_return_val_if_fail (dbus_type_is_fixed (element_type), FALSE);
|
||||
_dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
|
||||
_dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
|
||||
_dbus_return_val_if_fail (value != NULL, FALSE);
|
||||
_dbus_return_val_if_fail (n_elements >= 0, FALSE);
|
||||
|
|
@ -3337,6 +3619,20 @@ dbus_set_error_from_message (DBusError *error,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a message contains unix fds
|
||||
*
|
||||
* @param message the message
|
||||
* @returns #TRUE if the message contains unix fds
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_message_contains_unix_fds(DBusMessage *message)
|
||||
{
|
||||
_dbus_assert(message);
|
||||
|
||||
return message->n_unix_fds > 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
|
@ -3380,6 +3676,12 @@ _dbus_message_loader_new (void)
|
|||
/* this can be configured by the app, but defaults to the protocol max */
|
||||
loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
|
||||
|
||||
/* We set a very relatively conservative default here since due to how
|
||||
SCM_RIGHTS works we need to preallocate an fd array of the maximum
|
||||
number of unix fds we want to receive in advance. A
|
||||
try-and-reallocate loop is not possible. */
|
||||
loader->max_message_unix_fds = 1024;
|
||||
|
||||
if (!_dbus_string_init (&loader->data))
|
||||
{
|
||||
dbus_free (loader);
|
||||
|
|
@ -3390,6 +3692,12 @@ _dbus_message_loader_new (void)
|
|||
_dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
|
||||
_dbus_string_set_length (&loader->data, 0);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
loader->unix_fds = NULL;
|
||||
loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
|
||||
loader->unix_fds_outstanding = FALSE;
|
||||
#endif
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
|
@ -3419,6 +3727,10 @@ _dbus_message_loader_unref (DBusMessageLoader *loader)
|
|||
loader->refcount -= 1;
|
||||
if (loader->refcount == 0)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
|
||||
dbus_free(loader->unix_fds);
|
||||
#endif
|
||||
_dbus_list_foreach (&loader->messages,
|
||||
(DBusForeachFunction) dbus_message_unref,
|
||||
NULL);
|
||||
|
|
@ -3478,6 +3790,81 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
|
|||
loader->buffer_outstanding = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer to use for reading unix fds from the network.
|
||||
*
|
||||
* This works similar to _dbus_message_loader_get_buffer()
|
||||
*
|
||||
* @param loader the message loader.
|
||||
* @param fds the array to read fds into
|
||||
* @param max_n_fds how many fds to read at most
|
||||
* @return TRUE on success, FALSE on OOM
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
|
||||
int **fds,
|
||||
unsigned *max_n_fds)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_assert (!loader->unix_fds_outstanding);
|
||||
|
||||
/* Allocate space where we can put the fds we read. We allocate
|
||||
space for max_message_unix_fds since this is an
|
||||
upper limit how many fds can be received within a single
|
||||
message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
|
||||
we are allocating the maximum possible array size right from the
|
||||
beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
|
||||
there is no better way. */
|
||||
|
||||
if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
|
||||
{
|
||||
int *a = dbus_realloc(loader->unix_fds,
|
||||
loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
|
||||
|
||||
if (!a)
|
||||
return FALSE;
|
||||
|
||||
loader->unix_fds = a;
|
||||
loader->n_unix_fds_allocated = loader->max_message_unix_fds;
|
||||
}
|
||||
|
||||
*fds = loader->unix_fds + loader->n_unix_fds;
|
||||
*max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
|
||||
|
||||
loader->unix_fds_outstanding = TRUE;
|
||||
return TRUE;
|
||||
#else
|
||||
_dbus_assert_not_reached("Platform doesn't support unix fd passing");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer obtained from _dbus_message_loader_get_unix_fds().
|
||||
*
|
||||
* This works similar to _dbus_message_loader_return_buffer()
|
||||
*
|
||||
* @param loader the message loader.
|
||||
* @param fds the array fds were read into
|
||||
* @param max_n_fds how many fds were read
|
||||
*/
|
||||
|
||||
void
|
||||
_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
|
||||
int *fds,
|
||||
unsigned n_fds)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_assert(loader->unix_fds_outstanding);
|
||||
_dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
|
||||
_dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
|
||||
|
||||
loader->n_unix_fds += n_fds;
|
||||
loader->unix_fds_outstanding = FALSE;
|
||||
#else
|
||||
_dbus_assert_not_reached("Platform doesn't support unix fd passing");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME when we move the header out of the buffer, that memmoves all
|
||||
* buffered messages. Kind of crappy.
|
||||
|
|
@ -3517,6 +3904,7 @@ load_message (DBusMessageLoader *loader,
|
|||
const DBusString *type_str;
|
||||
int type_pos;
|
||||
DBusValidationMode mode;
|
||||
dbus_uint32_t n_unix_fds = 0;
|
||||
|
||||
mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
|
||||
|
||||
|
|
@ -3586,6 +3974,59 @@ load_message (DBusMessageLoader *loader,
|
|||
}
|
||||
}
|
||||
|
||||
/* 3. COPY OVER UNIX FDS */
|
||||
_dbus_header_get_field_basic(&message->header,
|
||||
DBUS_HEADER_FIELD_UNIX_FDS,
|
||||
DBUS_TYPE_UINT32,
|
||||
&n_unix_fds);
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (n_unix_fds > loader->n_unix_fds)
|
||||
{
|
||||
_dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
|
||||
n_unix_fds, loader->n_unix_fds);
|
||||
|
||||
loader->corrupted = TRUE;
|
||||
loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* If this was a recycled message there might still be
|
||||
some memory allocated for the fds */
|
||||
dbus_free(message->unix_fds);
|
||||
|
||||
if (n_unix_fds > 0)
|
||||
{
|
||||
message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
|
||||
if (message->unix_fds == NULL)
|
||||
{
|
||||
_dbus_verbose ("Failed to allocate file descriptor array\n");
|
||||
oom = TRUE;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
|
||||
loader->n_unix_fds -= n_unix_fds;
|
||||
memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
|
||||
}
|
||||
else
|
||||
message->unix_fds = NULL;
|
||||
|
||||
#else
|
||||
|
||||
if (n_unix_fds > 0)
|
||||
{
|
||||
_dbus_verbose ("Hmm, message claims to come with file descriptors "
|
||||
"but that's not supported on our platform, disconnecting.\n");
|
||||
|
||||
loader->corrupted = TRUE;
|
||||
loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* 3. COPY OVER BODY AND QUEUE MESSAGE */
|
||||
|
||||
if (!_dbus_list_append (&loader->messages, message))
|
||||
|
|
@ -3815,6 +4256,37 @@ _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
|
|||
return loader->max_message_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum unix fds per message we allow.
|
||||
*
|
||||
* @param loader the loader
|
||||
* @param size the max number of unix fds in a message
|
||||
*/
|
||||
void
|
||||
_dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader,
|
||||
long n)
|
||||
{
|
||||
if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
|
||||
{
|
||||
_dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
|
||||
n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
|
||||
n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
|
||||
}
|
||||
loader->max_message_unix_fds = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum allowed number of unix fds per message
|
||||
*
|
||||
* @param loader the loader
|
||||
* @returns max unix fds
|
||||
*/
|
||||
long
|
||||
_dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader)
|
||||
{
|
||||
return loader->max_message_unix_fds;
|
||||
}
|
||||
|
||||
static DBusDataSlotAllocator slot_allocator;
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (message_slots);
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ dbus_bool_t dbus_message_get_args_valist (DBusMessage *message,
|
|||
int first_arg_type,
|
||||
va_list var_args);
|
||||
|
||||
dbus_bool_t dbus_message_contains_unix_fds (DBusMessage *message);
|
||||
|
||||
dbus_bool_t dbus_message_iter_init (DBusMessage *message,
|
||||
DBusMessageIter *iter);
|
||||
|
|
|
|||
|
|
@ -110,6 +110,10 @@ extern "C" {
|
|||
#define DBUS_TYPE_SIGNATURE ((int) 'g')
|
||||
/** #DBUS_TYPE_SIGNATURE as a string literal instead of a int literal */
|
||||
#define DBUS_TYPE_SIGNATURE_AS_STRING "g"
|
||||
/** Type code marking a unix file descriptor */
|
||||
#define DBUS_TYPE_UNIX_FD ((int) 'h')
|
||||
/** #DBUS_TYPE_UNIX_FD as a string literal instead of a int literal */
|
||||
#define DBUS_TYPE_UNIX_FD_AS_STRING "h"
|
||||
|
||||
/* Compound types */
|
||||
/** Type code marking a D-Bus array type */
|
||||
|
|
@ -207,6 +211,14 @@ extern "C" {
|
|||
/** Number of bits you need in an unsigned to store the max message size */
|
||||
#define DBUS_MAXIMUM_MESSAGE_LENGTH_BITS 27
|
||||
|
||||
/** The maximum total number of unix fds in a message. Similar
|
||||
* rationale as DBUS_MAXIMUM_MESSAGE_LENGTH. However we divide by four
|
||||
* given that one fd is an int and hence at least 32 bits.
|
||||
*/
|
||||
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS (DBUS_MAXIMUM_MESSAGE_LENGTH/4)
|
||||
/** Number of bits you need in an unsigned to store the max message unix fds */
|
||||
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS_BITS (DBUS_MAXIMUM_MESSAGE_LENGTH_BITS-2)
|
||||
|
||||
/** Depth of recursion in the type tree. This is automatically limited
|
||||
* to DBUS_MAXIMUM_SIGNATURE_LENGTH since you could only have an array
|
||||
* of array of array of ... that fit in the max signature. But that's
|
||||
|
|
@ -276,6 +288,12 @@ extern "C" {
|
|||
* Header field code for the type signature of a message.
|
||||
*/
|
||||
#define DBUS_HEADER_FIELD_SIGNATURE 8
|
||||
/**
|
||||
* Header field code for the number of unix file descriptors associated
|
||||
* with this message.
|
||||
*/
|
||||
#define DBUS_HEADER_FIELD_UNIX_FDS 9
|
||||
|
||||
|
||||
/**
|
||||
* Value of the highest-numbered header field code, can be used to determine
|
||||
|
|
@ -283,7 +301,7 @@ extern "C" {
|
|||
* that unknown codes must be ignored, so check for that before
|
||||
* indexing the array.
|
||||
*/
|
||||
#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_SIGNATURE
|
||||
#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_UNIX_FDS
|
||||
|
||||
/** Header format is defined as a signature:
|
||||
* byte byte order
|
||||
|
|
@ -415,6 +433,9 @@ extern "C" {
|
|||
#define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN "org.freedesktop.DBus.Error.AdtAuditDataUnknown"
|
||||
/** There's already an object with the requested object path. */
|
||||
#define DBUS_ERROR_OBJECT_PATH_IN_USE "org.freedesktop.DBus.Error.ObjectPathInUse"
|
||||
/** The message meta data does not match the payload. e.g. expected
|
||||
number of file descriptors were not sent over the socket this message was received on. */
|
||||
#define DBUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage"
|
||||
|
||||
/* XML introspection format */
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
* @brief DBusCounter and other stuff related to resource limits
|
||||
*
|
||||
* Types and functions related to tracking resource limits,
|
||||
* such as the maximum amount of memory a connection can use
|
||||
* such as the maximum amount of memory/unix fds a connection can use
|
||||
* for messages, etc.
|
||||
*/
|
||||
|
||||
|
|
@ -53,9 +53,12 @@ struct DBusCounter
|
|||
{
|
||||
int refcount; /**< reference count */
|
||||
|
||||
long value; /**< current counter value */
|
||||
long size_value; /**< current size counter value */
|
||||
long unix_fd_value; /**< current unix fd counter value */
|
||||
|
||||
long notify_size_guard_value; /**< call notify function when crossing this size value */
|
||||
long notify_unix_fd_guard_value; /**< call notify function when crossing this unix fd value */
|
||||
|
||||
long notify_guard_value; /**< call notify function when crossing this value */
|
||||
DBusCounterNotifyFunction notify_function; /**< notify function */
|
||||
void *notify_data; /**< data for notify function */
|
||||
};
|
||||
|
|
@ -83,9 +86,11 @@ _dbus_counter_new (void)
|
|||
return NULL;
|
||||
|
||||
counter->refcount = 1;
|
||||
counter->value = 0;
|
||||
counter->size_value = 0;
|
||||
counter->unix_fd_value = 0;
|
||||
|
||||
counter->notify_guard_value = 0;
|
||||
counter->notify_size_guard_value = 0;
|
||||
counter->notify_unix_fd_guard_value = 0;
|
||||
counter->notify_function = NULL;
|
||||
counter->notify_data = NULL;
|
||||
|
||||
|
|
@ -129,64 +134,109 @@ _dbus_counter_unref (DBusCounter *counter)
|
|||
}
|
||||
|
||||
/**
|
||||
* Adjusts the value of the counter by the given
|
||||
* Adjusts the value of the size counter by the given
|
||||
* delta which may be positive or negative.
|
||||
* Calls the notify function from _dbus_counter_set_notify()
|
||||
* if that function has been specified.
|
||||
*
|
||||
* @param counter the counter
|
||||
* @param delta value to add to the counter's current value
|
||||
* @param delta value to add to the size counter's current value
|
||||
*/
|
||||
void
|
||||
_dbus_counter_adjust (DBusCounter *counter,
|
||||
long delta)
|
||||
_dbus_counter_adjust_size (DBusCounter *counter,
|
||||
long delta)
|
||||
{
|
||||
long old = counter->value;
|
||||
|
||||
counter->value += delta;
|
||||
long old = counter->size_value;
|
||||
|
||||
counter->size_value += delta;
|
||||
|
||||
#if 0
|
||||
_dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
|
||||
old, delta, counter->value);
|
||||
old, delta, counter->size_value);
|
||||
#endif
|
||||
|
||||
|
||||
if (counter->notify_function != NULL &&
|
||||
((old < counter->notify_guard_value &&
|
||||
counter->value >= counter->notify_guard_value) ||
|
||||
(old >= counter->notify_guard_value &&
|
||||
counter->value < counter->notify_guard_value)))
|
||||
((old < counter->notify_size_guard_value &&
|
||||
counter->size_value >= counter->notify_size_guard_value) ||
|
||||
(old >= counter->notify_size_guard_value &&
|
||||
counter->size_value < counter->notify_size_guard_value)))
|
||||
(* counter->notify_function) (counter, counter->notify_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the counter.
|
||||
* Adjusts the value of the unix fd counter by the given
|
||||
* delta which may be positive or negative.
|
||||
* Calls the notify function from _dbus_counter_set_notify()
|
||||
* if that function has been specified.
|
||||
*
|
||||
* @param counter the counter
|
||||
* @returns its current value
|
||||
* @param delta value to add to the unix fds counter's current value
|
||||
*/
|
||||
void
|
||||
_dbus_counter_adjust_unix_fd (DBusCounter *counter,
|
||||
long delta)
|
||||
{
|
||||
long old = counter->unix_fd_value;
|
||||
|
||||
counter->unix_fd_value += delta;
|
||||
|
||||
#if 0
|
||||
_dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
|
||||
old, delta, counter->unix_fd_value);
|
||||
#endif
|
||||
|
||||
if (counter->notify_function != NULL &&
|
||||
((old < counter->notify_unix_fd_guard_value &&
|
||||
counter->unix_fd_value >= counter->notify_unix_fd_guard_value) ||
|
||||
(old >= counter->notify_unix_fd_guard_value &&
|
||||
counter->unix_fd_value < counter->notify_unix_fd_guard_value)))
|
||||
(* counter->notify_function) (counter, counter->notify_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the size counter.
|
||||
*
|
||||
* @param counter the counter
|
||||
* @returns its current size value
|
||||
*/
|
||||
long
|
||||
_dbus_counter_get_value (DBusCounter *counter)
|
||||
_dbus_counter_get_size_value (DBusCounter *counter)
|
||||
{
|
||||
return counter->value;
|
||||
return counter->size_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the unix fd counter.
|
||||
*
|
||||
* @param counter the counter
|
||||
* @returns its current unix fd value
|
||||
*/
|
||||
long
|
||||
_dbus_counter_get_unix_fd_value (DBusCounter *counter)
|
||||
{
|
||||
return counter->unix_fd_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the notify function for this counter; the notify function is
|
||||
* called whenever the counter's value crosses the guard value in
|
||||
* called whenever the counter's values cross the guard values in
|
||||
* either direction (moving up, or moving down).
|
||||
*
|
||||
* @param counter the counter
|
||||
* @param guard_value the value we're notified if the counter crosses
|
||||
* @param size_guard_value the value we're notified if the size counter crosses
|
||||
* @param unix_fd_guard_value the value we're notified if the unix fd counter crosses
|
||||
* @param function function to call in order to notify
|
||||
* @param user_data data to pass to the function
|
||||
*/
|
||||
void
|
||||
_dbus_counter_set_notify (DBusCounter *counter,
|
||||
long guard_value,
|
||||
long size_guard_value,
|
||||
long unix_fd_guard_value,
|
||||
DBusCounterNotifyFunction function,
|
||||
void *user_data)
|
||||
{
|
||||
counter->notify_guard_value = guard_value;
|
||||
counter->notify_size_guard_value = size_guard_value;
|
||||
counter->notify_unix_fd_guard_value = unix_fd_guard_value;
|
||||
counter->notify_function = function;
|
||||
counter->notify_data = user_data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,19 @@ typedef void (* DBusCounterNotifyFunction) (DBusCounter *counter,
|
|||
DBusCounter* _dbus_counter_new (void);
|
||||
DBusCounter* _dbus_counter_ref (DBusCounter *counter);
|
||||
void _dbus_counter_unref (DBusCounter *counter);
|
||||
void _dbus_counter_adjust (DBusCounter *counter,
|
||||
long delta);
|
||||
long _dbus_counter_get_value (DBusCounter *counter);
|
||||
|
||||
void _dbus_counter_set_notify (DBusCounter *counter,
|
||||
long guard_value,
|
||||
DBusCounterNotifyFunction function,
|
||||
void *user_data);
|
||||
void _dbus_counter_adjust_size (DBusCounter *counter,
|
||||
long delta);
|
||||
void _dbus_counter_adjust_unix_fd (DBusCounter *counter,
|
||||
long delta);
|
||||
long _dbus_counter_get_size_value (DBusCounter *counter);
|
||||
long _dbus_counter_get_unix_fd_value (DBusCounter *counter);
|
||||
|
||||
void _dbus_counter_set_notify (DBusCounter *counter,
|
||||
long size_guard_value,
|
||||
long unix_fd_guard_value,
|
||||
DBusCounterNotifyFunction function,
|
||||
void *user_data);
|
||||
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
|
|
|||
|
|
@ -253,9 +253,6 @@ _dbus_transport_debug_pipe_new (const char *server_name,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_fd_set_close_on_exec (client_fd);
|
||||
_dbus_fd_set_close_on_exec (server_fd);
|
||||
|
||||
client_transport = _dbus_transport_new_for_socket (client_fd,
|
||||
NULL, &address);
|
||||
if (client_transport == NULL)
|
||||
|
|
|
|||
|
|
@ -195,8 +195,6 @@ socket_handle_watch (DBusWatch *watch,
|
|||
}
|
||||
else
|
||||
{
|
||||
_dbus_fd_set_close_on_exec (client_fd);
|
||||
|
||||
if (!handle_new_client_fd_and_unlock (server, client_fd))
|
||||
_dbus_verbose ("Rejected client connection due to lack of memory\n");
|
||||
}
|
||||
|
|
@ -413,9 +411,6 @@ _dbus_server_new_for_tcp_socket (const char *host,
|
|||
goto failed_1;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < nlisten_fds ; i++)
|
||||
_dbus_fd_set_close_on_exec (listen_fds[i]);
|
||||
|
||||
_dbus_string_init_const (&host_str, host);
|
||||
if (!_dbus_string_append (&address, "tcp:host=") ||
|
||||
!_dbus_address_append_escaped (&address, &host_str) ||
|
||||
|
|
|
|||
|
|
@ -201,8 +201,7 @@ _dbus_server_new_for_domain_socket (const char *path,
|
|||
}
|
||||
|
||||
listen_fd = _dbus_listen_unix_socket (path, abstract, error);
|
||||
_dbus_fd_set_close_on_exec (listen_fd);
|
||||
|
||||
|
||||
if (listen_fd < 0)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ _dbus_sha_final (DBusSHAContext *context,
|
|||
/* some kind of security paranoia, though it seems pointless
|
||||
* to me given the nonzeroed stuff flying around
|
||||
*/
|
||||
memset ((void*)context, '\0', sizeof (DBusSHAContext));
|
||||
_DBUS_ZERO(*context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@ dbus_type_is_fixed (int typecode)
|
|||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
case DBUS_TYPE_UNIX_FD:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "dbus-spawn.h"
|
||||
#include "dbus-sysdeps-unix.h"
|
||||
#include "dbus-internals.h"
|
||||
|
|
@ -805,9 +808,25 @@ static dbus_bool_t
|
|||
make_pipe (int p[2],
|
||||
DBusError *error)
|
||||
{
|
||||
int retval;
|
||||
|
||||
#ifdef HAVE_PIPE2
|
||||
dbus_bool_t cloexec_done;
|
||||
|
||||
retval = pipe2 (p, O_CLOEXEC);
|
||||
cloexec_done = retval >= 0;
|
||||
|
||||
/* Check if kernel seems to be too old to know pipe2(). We assume
|
||||
that if pipe2 is available, O_CLOEXEC is too. */
|
||||
if (retval < 0 && errno == ENOSYS)
|
||||
#endif
|
||||
{
|
||||
retval = pipe(p);
|
||||
}
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (pipe (p) < 0)
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
DBUS_ERROR_SPAWN_FAILED,
|
||||
|
|
@ -816,6 +835,14 @@ make_pipe (int p[2],
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PIPE2
|
||||
if (!cloexec_done)
|
||||
#endif
|
||||
{
|
||||
_dbus_fd_set_close_on_exec (p[0]);
|
||||
_dbus_fd_set_close_on_exec (p[1]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1117,15 +1144,9 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
|
|||
if (!make_pipe (child_err_report_pipe, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
_dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]);
|
||||
_dbus_fd_set_close_on_exec (child_err_report_pipe[WRITE_END]);
|
||||
|
||||
if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
|
||||
goto cleanup_and_fail;
|
||||
|
||||
_dbus_fd_set_close_on_exec (babysitter_pipe[0]);
|
||||
_dbus_fd_set_close_on_exec (babysitter_pipe[1]);
|
||||
|
||||
/* Setting up the babysitter is only useful in the parent,
|
||||
* but we don't want to run out of memory and fail
|
||||
* after we've already forked, since then we'd leak
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <config.h>
|
||||
|
||||
#include "dbus-internals.h"
|
||||
#include "dbus-sysdeps.h"
|
||||
|
|
@ -94,9 +94,28 @@ _dbus_open_socket (int *fd_p,
|
|||
int protocol,
|
||||
DBusError *error)
|
||||
{
|
||||
*fd_p = socket (domain, type, protocol);
|
||||
#ifdef SOCK_CLOEXEC
|
||||
dbus_bool_t cloexec_done;
|
||||
|
||||
*fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
|
||||
cloexec_done = *fd_p >= 0;
|
||||
|
||||
/* Check if kernel seems to be too old to know SOCK_CLOEXEC */
|
||||
if (*fd_p < 0 && errno == EINVAL)
|
||||
#endif
|
||||
{
|
||||
*fd_p = socket (domain, type, protocol);
|
||||
}
|
||||
|
||||
if (*fd_p >= 0)
|
||||
{
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (!cloexec_done)
|
||||
#endif
|
||||
{
|
||||
_dbus_fd_set_close_on_exec(*fd_p);
|
||||
}
|
||||
|
||||
_dbus_verbose ("socket fd %d opened\n", *fd_p);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -120,6 +139,9 @@ _dbus_open_tcp_socket (int *fd,
|
|||
/**
|
||||
* Opens a UNIX domain socket (as in the socket() call).
|
||||
* Does not bind the socket.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned
|
||||
*
|
||||
* @param fd return location for socket descriptor
|
||||
* @param error return location for an error
|
||||
* @returns #FALSE if error is set
|
||||
|
|
@ -179,7 +201,259 @@ _dbus_write_socket (int fd,
|
|||
int start,
|
||||
int len)
|
||||
{
|
||||
#ifdef MSG_NOSIGNAL
|
||||
const char *data;
|
||||
int bytes_written;
|
||||
|
||||
data = _dbus_string_get_const_data_len (buffer, start, len);
|
||||
|
||||
again:
|
||||
|
||||
bytes_written = send (fd, data, len, MSG_NOSIGNAL);
|
||||
|
||||
if (bytes_written < 0 && errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return bytes_written;
|
||||
|
||||
#else
|
||||
return _dbus_write (fd, buffer, start, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Like _dbus_read_socket() but also tries to read unix fds from the
|
||||
* socket. When there are more fds to read than space in the array
|
||||
* passed this function will fail with ENOSPC.
|
||||
*
|
||||
* @param fd the socket
|
||||
* @param buffer string to append data to
|
||||
* @param count max amount of data to read
|
||||
* @param fds array to place read file descriptors in
|
||||
* @param n_fds on input space in fds array, on output how many fds actually got read
|
||||
* @returns number of bytes appended to string
|
||||
*/
|
||||
int
|
||||
_dbus_read_socket_with_unix_fds (int fd,
|
||||
DBusString *buffer,
|
||||
int count,
|
||||
int *fds,
|
||||
int *n_fds) {
|
||||
#ifndef HAVE_UNIX_FD_PASSING
|
||||
int r;
|
||||
|
||||
if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
|
||||
return r;
|
||||
|
||||
*n_fds = 0;
|
||||
return r;
|
||||
|
||||
#else
|
||||
int bytes_read;
|
||||
int start;
|
||||
struct msghdr m;
|
||||
struct iovec iov;
|
||||
|
||||
_dbus_assert (count >= 0);
|
||||
_dbus_assert (*n_fds >= 0);
|
||||
|
||||
start = _dbus_string_get_length (buffer);
|
||||
|
||||
if (!_dbus_string_lengthen (buffer, count))
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
_DBUS_ZERO(iov);
|
||||
iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
|
||||
iov.iov_len = count;
|
||||
|
||||
_DBUS_ZERO(m);
|
||||
m.msg_iov = &iov;
|
||||
m.msg_iovlen = 1;
|
||||
|
||||
/* Hmm, we have no clue how long the control data will actually be
|
||||
that is queued for us. The least we can do is assume that the
|
||||
caller knows. Hence let's make space for the number of fds that
|
||||
we shall read at max plus the cmsg header. */
|
||||
m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
|
||||
|
||||
/* It's probably safe to assume that systems with SCM_RIGHTS also
|
||||
know alloca() */
|
||||
m.msg_control = alloca(m.msg_controllen);
|
||||
memset(m.msg_control, 0, m.msg_controllen);
|
||||
|
||||
again:
|
||||
|
||||
bytes_read = recvmsg(fd, &m, 0
|
||||
#ifdef MSG_CMSG_CLOEXEC
|
||||
|MSG_CMSG_CLOEXEC
|
||||
#endif
|
||||
);
|
||||
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
else
|
||||
{
|
||||
/* put length back (note that this doesn't actually realloc anything) */
|
||||
_dbus_string_set_length (buffer, start);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
dbus_bool_t found = FALSE;
|
||||
|
||||
if (m.msg_flags & MSG_CTRUNC)
|
||||
{
|
||||
/* Hmm, apparently the control data was truncated. The bad
|
||||
thing is that we might have completely lost a couple of fds
|
||||
without chance to recover them. Hence let's treat this as a
|
||||
serious error. */
|
||||
|
||||
errno = ENOSPC;
|
||||
_dbus_string_set_length (buffer, start);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
|
||||
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
_dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
|
||||
*n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
|
||||
memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
|
||||
found = TRUE;
|
||||
|
||||
/* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
|
||||
worked, hence we need to go through this list and set
|
||||
CLOEXEC everywhere in any case */
|
||||
for (i = 0; i < *n_fds; i++)
|
||||
_dbus_fd_set_close_on_exec(fds[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
*n_fds = 0;
|
||||
|
||||
/* put length back (doesn't actually realloc) */
|
||||
_dbus_string_set_length (buffer, start + bytes_read);
|
||||
|
||||
#if 0
|
||||
if (bytes_read > 0)
|
||||
_dbus_verbose_bytes_of_string (buffer, start, bytes_read);
|
||||
#endif
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
_dbus_write_socket_with_unix_fds(int fd,
|
||||
const DBusString *buffer,
|
||||
int start,
|
||||
int len,
|
||||
const int *fds,
|
||||
int n_fds) {
|
||||
|
||||
#ifndef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (n_fds > 0) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _dbus_write_socket(fd, buffer, start, len);
|
||||
#else
|
||||
return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
_dbus_write_socket_with_unix_fds_two(int fd,
|
||||
const DBusString *buffer1,
|
||||
int start1,
|
||||
int len1,
|
||||
const DBusString *buffer2,
|
||||
int start2,
|
||||
int len2,
|
||||
const int *fds,
|
||||
int n_fds) {
|
||||
|
||||
#ifndef HAVE_UNIX_FD_PASSING
|
||||
|
||||
if (n_fds > 0) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _dbus_write_socket_two(fd,
|
||||
buffer1, start1, len1,
|
||||
buffer2, start2, len2);
|
||||
#else
|
||||
|
||||
struct msghdr m;
|
||||
struct cmsghdr *cm;
|
||||
struct iovec iov[2];
|
||||
int bytes_written;
|
||||
|
||||
_dbus_assert (len1 >= 0);
|
||||
_dbus_assert (len2 >= 0);
|
||||
_dbus_assert (n_fds >= 0);
|
||||
|
||||
_DBUS_ZERO(iov);
|
||||
iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
|
||||
iov[0].iov_len = len1;
|
||||
|
||||
if (buffer2)
|
||||
{
|
||||
iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
|
||||
iov[1].iov_len = len2;
|
||||
}
|
||||
|
||||
_DBUS_ZERO(m);
|
||||
m.msg_iov = iov;
|
||||
m.msg_iovlen = buffer2 ? 2 : 1;
|
||||
|
||||
if (n_fds > 0)
|
||||
{
|
||||
m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
|
||||
m.msg_control = alloca(m.msg_controllen);
|
||||
memset(m.msg_control, 0, m.msg_controllen);
|
||||
|
||||
cm = CMSG_FIRSTHDR(&m);
|
||||
cm->cmsg_level = SOL_SOCKET;
|
||||
cm->cmsg_type = SCM_RIGHTS;
|
||||
cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
|
||||
memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
|
||||
}
|
||||
|
||||
again:
|
||||
|
||||
bytes_written = sendmsg (fd, &m, 0
|
||||
#ifdef MSG_NOSIGNAL
|
||||
|MSG_NOSIGNAL
|
||||
#endif
|
||||
);
|
||||
|
||||
if (bytes_written < 0 && errno == EINTR)
|
||||
goto again;
|
||||
|
||||
#if 0
|
||||
if (bytes_written > 0)
|
||||
_dbus_verbose_bytes_of_string (buffer, start, bytes_written);
|
||||
#endif
|
||||
|
||||
return bytes_written;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -255,8 +529,52 @@ _dbus_write_socket_two (int fd,
|
|||
int start2,
|
||||
int len2)
|
||||
{
|
||||
#ifdef MSG_NOSIGNAL
|
||||
struct iovec vectors[2];
|
||||
const char *data1;
|
||||
const char *data2;
|
||||
int bytes_written;
|
||||
struct msghdr m;
|
||||
|
||||
_dbus_assert (buffer1 != NULL);
|
||||
_dbus_assert (start1 >= 0);
|
||||
_dbus_assert (start2 >= 0);
|
||||
_dbus_assert (len1 >= 0);
|
||||
_dbus_assert (len2 >= 0);
|
||||
|
||||
data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
|
||||
|
||||
if (buffer2 != NULL)
|
||||
data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
|
||||
else
|
||||
{
|
||||
data2 = NULL;
|
||||
start2 = 0;
|
||||
len2 = 0;
|
||||
}
|
||||
|
||||
vectors[0].iov_base = (char*) data1;
|
||||
vectors[0].iov_len = len1;
|
||||
vectors[1].iov_base = (char*) data2;
|
||||
vectors[1].iov_len = len2;
|
||||
|
||||
_DBUS_ZERO(m);
|
||||
m.msg_iov = vectors;
|
||||
m.msg_iovlen = data2 ? 2 : 1;
|
||||
|
||||
again:
|
||||
|
||||
bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
|
||||
|
||||
if (bytes_written < 0 && errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return bytes_written;
|
||||
|
||||
#else
|
||||
return _dbus_write_two (fd, buffer1, start1, len1,
|
||||
buffer2, start2, len2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -474,6 +792,8 @@ _dbus_write_two (int fd,
|
|||
* requested (it's possible only on Linux; see "man 7 unix" on Linux).
|
||||
* On non-Linux abstract socket usage always fails.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned.
|
||||
*
|
||||
* @param path the path to UNIX domain socket
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for error code
|
||||
|
|
@ -610,6 +930,8 @@ _dbus_set_local_creds (int fd, dbus_bool_t on)
|
|||
* see "man 7 unix" on Linux).
|
||||
* On non-Linux abstract socket usage always fails.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned
|
||||
*
|
||||
* @param path the socket name
|
||||
* @param abstract #TRUE to use abstract namespace
|
||||
* @param error return location for errors
|
||||
|
|
@ -746,6 +1068,8 @@ _dbus_listen_unix_socket (const char *path,
|
|||
* and port. The connection fd is returned, and is set up as
|
||||
* nonblocking.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned
|
||||
*
|
||||
* @param host the host name to connect to
|
||||
* @param port the port to connect to
|
||||
* @param family the address family to listen on, NULL for all
|
||||
|
|
@ -853,6 +1177,8 @@ _dbus_connect_tcp_socket (const char *host,
|
|||
* a random free port is used and returned in the port parameter.
|
||||
* If inaddr_any is specified, the hostname is ignored.
|
||||
*
|
||||
* This will set FD_CLOEXEC for the socket returned
|
||||
*
|
||||
* @param host the host name to listen on
|
||||
* @param port the port to listen on, if zero a free port will be used
|
||||
* @param family the address family to listen on, NULL for all
|
||||
|
|
@ -1056,13 +1382,13 @@ write_credentials_byte (int server_fd,
|
|||
iov.iov_base = buf;
|
||||
iov.iov_len = 1;
|
||||
|
||||
memset (&msg, 0, sizeof (msg));
|
||||
_DBUS_ZERO(msg);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
msg.msg_control = (caddr_t) &cmsg;
|
||||
msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
|
||||
memset (&cmsg, 0, sizeof (cmsg));
|
||||
_DBUS_ZERO(cmsg);
|
||||
cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
|
||||
cmsg.hdr.cmsg_level = SOL_SOCKET;
|
||||
cmsg.hdr.cmsg_type = SCM_CREDS;
|
||||
|
|
@ -1172,12 +1498,12 @@ _dbus_read_credentials_socket (int client_fd,
|
|||
iov.iov_base = &buf;
|
||||
iov.iov_len = 1;
|
||||
|
||||
memset (&msg, 0, sizeof (msg));
|
||||
_DBUS_ZERO(msg);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
|
||||
memset (&cmsg, 0, sizeof (cmsg));
|
||||
_DBUS_ZERO(cmsg);
|
||||
msg.msg_control = (caddr_t) &cmsg;
|
||||
msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
|
||||
#endif
|
||||
|
|
@ -1377,6 +1703,8 @@ _dbus_send_credentials_socket (int server_fd,
|
|||
* Accepts a connection on a listening socket.
|
||||
* Handles EINTR for you.
|
||||
*
|
||||
* This will enable FD_CLOEXEC for the returned socket.
|
||||
*
|
||||
* @param listen_fd the listen file descriptor
|
||||
* @returns the connection fd of the client, or -1 on error
|
||||
*/
|
||||
|
|
@ -1386,12 +1714,25 @@ _dbus_accept (int listen_fd)
|
|||
int client_fd;
|
||||
struct sockaddr addr;
|
||||
socklen_t addrlen;
|
||||
#ifdef HAVE_ACCEPT4
|
||||
dbus_bool_t cloexec_done;
|
||||
#endif
|
||||
|
||||
addrlen = sizeof (addr);
|
||||
|
||||
|
||||
retry:
|
||||
client_fd = accept (listen_fd, &addr, &addrlen);
|
||||
|
||||
|
||||
#ifdef HAVE_ACCEPT4
|
||||
/* We assume that if accept4 is available SOCK_CLOEXEC is too */
|
||||
client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC);
|
||||
cloexec_done = client_fd >= 0;
|
||||
|
||||
if (client_fd < 0 && errno == ENOSYS)
|
||||
#endif
|
||||
{
|
||||
client_fd = accept (listen_fd, &addr, &addrlen);
|
||||
}
|
||||
|
||||
if (client_fd < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
|
|
@ -1399,7 +1740,14 @@ _dbus_accept (int listen_fd)
|
|||
}
|
||||
|
||||
_dbus_verbose ("client fd %d accepted\n", client_fd);
|
||||
|
||||
|
||||
#ifdef HAVE_ACCEPT4
|
||||
if (!cloexec_done)
|
||||
#endif
|
||||
{
|
||||
_dbus_fd_set_close_on_exec(client_fd);
|
||||
}
|
||||
|
||||
return client_fd;
|
||||
}
|
||||
|
||||
|
|
@ -1864,23 +2212,8 @@ _dbus_parse_uid (const DBusString *uid_str,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#if !DBUS_USE_SYNC
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
|
||||
|
||||
#if DBUS_USE_ATOMIC_INT_486_COND
|
||||
/* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
|
||||
/* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
|
||||
static inline dbus_int32_t
|
||||
atomic_exchange_and_add (DBusAtomic *atomic,
|
||||
volatile dbus_int32_t val)
|
||||
{
|
||||
register dbus_int32_t result;
|
||||
|
||||
__asm__ __volatile__ ("lock; xaddl %0,%1"
|
||||
: "=r" (result), "=m" (atomic->value)
|
||||
: "0" (val), "m" (atomic->value));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -1888,14 +2221,12 @@ atomic_exchange_and_add (DBusAtomic *atomic,
|
|||
*
|
||||
* @param atomic pointer to the integer to increment
|
||||
* @returns the value before incrementing
|
||||
*
|
||||
* @todo implement arch-specific faster atomic ops
|
||||
*/
|
||||
dbus_int32_t
|
||||
_dbus_atomic_inc (DBusAtomic *atomic)
|
||||
{
|
||||
#if DBUS_USE_ATOMIC_INT_486_COND
|
||||
return atomic_exchange_and_add (atomic, 1);
|
||||
#if DBUS_USE_SYNC
|
||||
return __sync_add_and_fetch(&atomic->value, 1)-1;
|
||||
#else
|
||||
dbus_int32_t res;
|
||||
_DBUS_LOCK (atomic);
|
||||
|
|
@ -1911,14 +2242,12 @@ _dbus_atomic_inc (DBusAtomic *atomic)
|
|||
*
|
||||
* @param atomic pointer to the integer to decrement
|
||||
* @returns the value before decrementing
|
||||
*
|
||||
* @todo implement arch-specific faster atomic ops
|
||||
*/
|
||||
dbus_int32_t
|
||||
_dbus_atomic_dec (DBusAtomic *atomic)
|
||||
{
|
||||
#if DBUS_USE_ATOMIC_INT_486_COND
|
||||
return atomic_exchange_and_add (atomic, -1);
|
||||
#if DBUS_USE_SYNC
|
||||
return __sync_sub_and_fetch(&atomic->value, 1)+1;
|
||||
#else
|
||||
dbus_int32_t res;
|
||||
|
||||
|
|
@ -2682,6 +3011,48 @@ _dbus_close (int fd,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates a file descriptor. Makes sure the fd returned is >= 3
|
||||
* (i.e. avoids stdin/stdout/stderr). Sets O_CLOEXEC.
|
||||
*
|
||||
* @param fd the file descriptor to duplicate
|
||||
* @returns duplicated file descriptor
|
||||
* */
|
||||
int
|
||||
_dbus_dup(int fd,
|
||||
DBusError *error)
|
||||
{
|
||||
int new_fd;
|
||||
|
||||
#ifdef F_DUPFD_CLOEXEC
|
||||
dbus_bool_t cloexec_done;
|
||||
|
||||
new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
cloexec_done = new_fd >= 0;
|
||||
|
||||
if (new_fd < 0 && errno == EINVAL)
|
||||
#endif
|
||||
{
|
||||
new_fd = fcntl(fd, F_DUPFD, 3);
|
||||
}
|
||||
|
||||
if (new_fd < 0) {
|
||||
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Could not duplicate fd %d", fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef F_DUPFD_CLOEXEC
|
||||
if (!cloexec_done)
|
||||
#endif
|
||||
{
|
||||
_dbus_fd_set_close_on_exec(new_fd);
|
||||
}
|
||||
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a file descriptor to be nonblocking.
|
||||
*
|
||||
|
|
@ -2761,6 +3132,8 @@ _dbus_print_backtrace (void)
|
|||
* Creates a full-duplex pipe (as in socketpair()).
|
||||
* Sets both ends of the pipe nonblocking.
|
||||
*
|
||||
* Marks both file descriptors as close-on-exec
|
||||
*
|
||||
* @todo libdbus only uses this for the debug-pipe server, so in
|
||||
* principle it could be in dbus-sysdeps-util.c, except that
|
||||
* dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
|
||||
|
|
@ -2780,16 +3153,37 @@ _dbus_full_duplex_pipe (int *fd1,
|
|||
{
|
||||
#ifdef HAVE_SOCKETPAIR
|
||||
int fds[2];
|
||||
int retval;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
|
||||
#ifdef SOCK_CLOEXEC
|
||||
dbus_bool_t cloexec_done;
|
||||
|
||||
retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
|
||||
cloexec_done = retval >= 0;
|
||||
|
||||
if (retval < 0 && errno == EINVAL)
|
||||
#endif
|
||||
{
|
||||
retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
|
||||
}
|
||||
|
||||
if (retval < 0)
|
||||
{
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
"Could not create full-duplex pipe");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
if (!cloexec_done)
|
||||
#endif
|
||||
{
|
||||
_dbus_fd_set_close_on_exec (fds[0]);
|
||||
_dbus_fd_set_close_on_exec (fds[1]);
|
||||
}
|
||||
|
||||
if (!blocking &&
|
||||
(!_dbus_set_fd_nonblocking (fds[0], NULL) ||
|
||||
!_dbus_set_fd_nonblocking (fds[1], NULL)))
|
||||
|
|
@ -3487,4 +3881,36 @@ _dbus_get_is_errno_eagain_or_ewouldblock (void)
|
|||
return errno == EAGAIN || errno == EWOULDBLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether file descriptors may be passed via the socket
|
||||
*
|
||||
* @param fd the socket
|
||||
* @return TRUE when fd passing over this socket is supported
|
||||
*
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_socket_can_pass_unix_fd(int fd) {
|
||||
|
||||
#ifdef SCM_RIGHTS
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage storage;
|
||||
struct sockaddr_un un;
|
||||
} sa_buf;
|
||||
|
||||
socklen_t sa_len = sizeof(sa_buf);
|
||||
|
||||
_DBUS_ZERO(sa_buf);
|
||||
|
||||
if (getsockname(fd, &sa_buf.sa, &sa_len) < 0)
|
||||
return FALSE;
|
||||
|
||||
return sa_buf.sa.sa_family == AF_UNIX;
|
||||
|
||||
#else
|
||||
return FALSE;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* tests in dbus-sysdeps-util.c */
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ DBUS_BEGIN_DECLS
|
|||
dbus_bool_t
|
||||
_dbus_close (int fd,
|
||||
DBusError *error);
|
||||
int
|
||||
int _dbus_dup (int fd,
|
||||
DBusError *error);
|
||||
int
|
||||
_dbus_read (int fd,
|
||||
DBusString *buffer,
|
||||
int count);
|
||||
|
|
|
|||
|
|
@ -2616,7 +2616,7 @@ static void dump_backtrace_for_thread(HANDLE hThread)
|
|||
|
||||
DPRINTF("Backtrace:\n");
|
||||
|
||||
memset(&context, 0, sizeof(context));
|
||||
_DBUS_ZERO(context);
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
|
||||
SuspendThread(hThread);
|
||||
|
|
@ -2628,7 +2628,7 @@ static void dump_backtrace_for_thread(HANDLE hThread)
|
|||
return;
|
||||
}
|
||||
|
||||
memset(&sf, 0, sizeof(sf));
|
||||
_DBUS_ZERO(sf);
|
||||
|
||||
#ifdef __i386__
|
||||
sf.AddrFrame.Offset = context.Ebp;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,28 @@ int _dbus_write_socket_two (int fd,
|
|||
const DBusString *buffer2,
|
||||
int start2,
|
||||
int len2);
|
||||
|
||||
int _dbus_read_socket_with_unix_fds (int fd,
|
||||
DBusString *buffer,
|
||||
int count,
|
||||
int *fds,
|
||||
int *n_fds);
|
||||
int _dbus_write_socket_with_unix_fds (int fd,
|
||||
const DBusString *buffer,
|
||||
int start,
|
||||
int len,
|
||||
const int *fds,
|
||||
int n_fds);
|
||||
int _dbus_write_socket_with_unix_fds_two (int fd,
|
||||
const DBusString *buffer1,
|
||||
int start1,
|
||||
int len1,
|
||||
const DBusString *buffer2,
|
||||
int start2,
|
||||
int len2,
|
||||
const int *fds,
|
||||
int n_fds);
|
||||
|
||||
int _dbus_connect_tcp_socket (const char *host,
|
||||
const char *port,
|
||||
const char *family,
|
||||
|
|
@ -192,6 +214,8 @@ dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid)
|
|||
dbus_bool_t _dbus_append_keyring_directory_for_credentials (DBusString *directory,
|
||||
DBusCredentials *credentials);
|
||||
|
||||
dbus_bool_t _dbus_socket_can_pass_unix_fd(int fd);
|
||||
|
||||
/** Opaque type representing an atomically-modifiable integer
|
||||
* that can be used from multiple threads.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -424,7 +424,9 @@ init_locks (void)
|
|||
LOCK_ADDR (pending_call_slots),
|
||||
LOCK_ADDR (server_slots),
|
||||
LOCK_ADDR (message_slots),
|
||||
#if !DBUS_USE_SYNC
|
||||
LOCK_ADDR (atomic),
|
||||
#endif
|
||||
LOCK_ADDR (bus),
|
||||
LOCK_ADDR (bus_datas),
|
||||
LOCK_ADDR (shutdown_funcs),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#ifndef DBUS_TRANSPORT_PROTECTED_H
|
||||
#define DBUS_TRANSPORT_PROTECTED_H
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <dbus/dbus-errors.h>
|
||||
#include <dbus/dbus-transport.h>
|
||||
|
|
@ -92,9 +94,9 @@ struct DBusTransport
|
|||
DBusCredentials *credentials; /**< Credentials of other end read from the socket */
|
||||
|
||||
long max_live_messages_size; /**< Max total size of received messages. */
|
||||
long max_live_messages_unix_fds; /**< Max total unix fds of received messages. */
|
||||
|
||||
DBusCounter *live_messages_size; /**< Counter for size of all live messages. */
|
||||
|
||||
DBusCounter *live_messages; /**< Counter for size/unix fds of all live messages. */
|
||||
|
||||
char *address; /**< Address of the server we are connecting to (#NULL for the server side of a transport) */
|
||||
|
||||
|
|
@ -138,6 +140,9 @@ DBusTransportOpenResult _dbus_transport_open_platform_specific (DBusAddressEntry
|
|||
DBusTransport **transport_p,
|
||||
DBusError *error);
|
||||
|
||||
#define DBUS_TRANSPORT_CAN_SEND_UNIX_FD(x) \
|
||||
_dbus_auth_get_unix_fd_negotiated((x)->auth)
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
||||
#endif /* DBUS_TRANSPORT_PROTECTED_H */
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#include "dbus-watch.h"
|
||||
#include "dbus-credentials.h"
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup DBusTransportSocket DBusTransport implementations for sockets
|
||||
* @ingroup DBusInternals
|
||||
|
|
@ -192,7 +191,8 @@ check_read_watch (DBusTransport *transport)
|
|||
|
||||
if (_dbus_transport_get_is_authenticated (transport))
|
||||
need_read_watch =
|
||||
_dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
|
||||
(_dbus_counter_get_size_value (transport->live_messages) < transport->max_live_messages_size) &&
|
||||
(_dbus_counter_get_unix_fd_value (transport->live_messages) < transport->max_live_messages_unix_fds);
|
||||
else
|
||||
{
|
||||
if (transport->receive_credentials_pending)
|
||||
|
|
@ -551,6 +551,9 @@ do_writing (DBusTransport *transport)
|
|||
|
||||
if (_dbus_auth_needs_encoding (transport->auth))
|
||||
{
|
||||
/* Does fd passing even make sense with encoded data? */
|
||||
_dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
|
||||
|
||||
if (_dbus_string_get_length (&socket_transport->encoded_outgoing) == 0)
|
||||
{
|
||||
if (!_dbus_auth_encode_data (transport->auth,
|
||||
|
|
@ -588,27 +591,53 @@ do_writing (DBusTransport *transport)
|
|||
|
||||
#if 0
|
||||
_dbus_verbose ("message is %d bytes\n",
|
||||
total_bytes_to_write);
|
||||
total_bytes_to_write);
|
||||
#endif
|
||||
|
||||
if (socket_transport->message_bytes_written < header_len)
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
if (socket_transport->message_bytes_written <= 0 && DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
|
||||
{
|
||||
/* Send the fds along with the first byte of the message */
|
||||
const int *unix_fds;
|
||||
unsigned n;
|
||||
|
||||
_dbus_message_get_unix_fds(message, &unix_fds, &n);
|
||||
|
||||
bytes_written =
|
||||
_dbus_write_socket_two (socket_transport->fd,
|
||||
header,
|
||||
socket_transport->message_bytes_written,
|
||||
header_len - socket_transport->message_bytes_written,
|
||||
body,
|
||||
0, body_len);
|
||||
_dbus_write_socket_with_unix_fds_two (socket_transport->fd,
|
||||
header,
|
||||
socket_transport->message_bytes_written,
|
||||
header_len - socket_transport->message_bytes_written,
|
||||
body,
|
||||
0, body_len,
|
||||
unix_fds,
|
||||
n);
|
||||
|
||||
if (bytes_written > 0 && n > 0)
|
||||
_dbus_verbose("Wrote %i unix fds\n", n);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bytes_written =
|
||||
_dbus_write_socket (socket_transport->fd,
|
||||
body,
|
||||
(socket_transport->message_bytes_written - header_len),
|
||||
body_len -
|
||||
(socket_transport->message_bytes_written - header_len));
|
||||
if (socket_transport->message_bytes_written < header_len)
|
||||
{
|
||||
bytes_written =
|
||||
_dbus_write_socket_two (socket_transport->fd,
|
||||
header,
|
||||
socket_transport->message_bytes_written,
|
||||
header_len - socket_transport->message_bytes_written,
|
||||
body,
|
||||
0, body_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_written =
|
||||
_dbus_write_socket (socket_transport->fd,
|
||||
body,
|
||||
(socket_transport->message_bytes_written - header_len),
|
||||
body_len -
|
||||
(socket_transport->message_bytes_written - header_len));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -704,6 +733,9 @@ do_reading (DBusTransport *transport)
|
|||
|
||||
if (_dbus_auth_needs_decoding (transport->auth))
|
||||
{
|
||||
/* Does fd passing even make sense with encoded data? */
|
||||
_dbus_assert(!DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport));
|
||||
|
||||
if (_dbus_string_get_length (&socket_transport->encoded_incoming) > 0)
|
||||
bytes_read = _dbus_string_get_length (&socket_transport->encoded_incoming);
|
||||
else
|
||||
|
|
@ -748,10 +780,37 @@ do_reading (DBusTransport *transport)
|
|||
{
|
||||
_dbus_message_loader_get_buffer (transport->loader,
|
||||
&buffer);
|
||||
|
||||
bytes_read = _dbus_read_socket (socket_transport->fd,
|
||||
buffer, socket_transport->max_bytes_read_per_iteration);
|
||||
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
if (DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport))
|
||||
{
|
||||
int *fds, n_fds;
|
||||
|
||||
if (!_dbus_message_loader_get_unix_fds(transport->loader, &fds, &n_fds))
|
||||
{
|
||||
_dbus_verbose ("Out of memory reading file descriptors\n");
|
||||
_dbus_message_loader_return_buffer (transport->loader, buffer, 0);
|
||||
oom = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes_read = _dbus_read_socket_with_unix_fds(socket_transport->fd,
|
||||
buffer,
|
||||
socket_transport->max_bytes_read_per_iteration,
|
||||
fds, &n_fds);
|
||||
|
||||
if (bytes_read >= 0 && n_fds > 0)
|
||||
_dbus_verbose("Read %i unix fds\n", n_fds);
|
||||
|
||||
_dbus_message_loader_return_unix_fds(transport->loader, fds, bytes_read < 0 ? 0 : n_fds);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bytes_read = _dbus_read_socket (socket_transport->fd,
|
||||
buffer, socket_transport->max_bytes_read_per_iteration);
|
||||
}
|
||||
|
||||
_dbus_message_loader_return_buffer (transport->loader,
|
||||
buffer,
|
||||
bytes_read < 0 ? 0 : bytes_read);
|
||||
|
|
@ -1204,7 +1263,11 @@ _dbus_transport_new_for_socket (int fd,
|
|||
&socket_vtable,
|
||||
server_guid, address))
|
||||
goto failed_4;
|
||||
|
||||
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
_dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd));
|
||||
#endif
|
||||
|
||||
socket_transport->fd = fd;
|
||||
socket_transport->message_bytes_written = 0;
|
||||
|
||||
|
|
@ -1282,8 +1345,6 @@ _dbus_transport_new_for_tcp_socket (const char *host,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_fd_set_close_on_exec (fd);
|
||||
|
||||
_dbus_verbose ("Successfully connected to tcp socket %s:%s\n",
|
||||
host, port);
|
||||
|
||||
|
|
|
|||
|
|
@ -85,8 +85,6 @@ _dbus_transport_new_for_domain_socket (const char *path,
|
|||
goto failed_0;
|
||||
}
|
||||
|
||||
_dbus_fd_set_close_on_exec (fd);
|
||||
|
||||
_dbus_verbose ("Successfully connected to unix socket %s\n",
|
||||
path);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "dbus-auth.h"
|
||||
#include "dbus-address.h"
|
||||
#include "dbus-credentials.h"
|
||||
#include "dbus-message-private.h"
|
||||
#include "dbus-marshal-header.h"
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#include "dbus-server-debug-pipe.h"
|
||||
#endif
|
||||
|
|
@ -55,7 +57,7 @@
|
|||
*/
|
||||
|
||||
static void
|
||||
live_messages_size_notify (DBusCounter *counter,
|
||||
live_messages_notify (DBusCounter *counter,
|
||||
void *user_data)
|
||||
{
|
||||
DBusTransport *transport = user_data;
|
||||
|
|
@ -63,8 +65,10 @@ live_messages_size_notify (DBusCounter *counter,
|
|||
_dbus_transport_ref (transport);
|
||||
|
||||
#if 0
|
||||
_dbus_verbose ("Counter value is now %d\n",
|
||||
(int) _dbus_counter_get_value (counter));
|
||||
_dbus_verbose ("Size counter value is now %d\n",
|
||||
(int) _dbus_counter_get_size_value (counter));
|
||||
_dbus_verbose ("Unix FD counter value is now %d\n",
|
||||
(int) _dbus_counter_get_unix_fd_value (counter));
|
||||
#endif
|
||||
|
||||
/* disable or re-enable the read watch for the transport if
|
||||
|
|
@ -155,7 +159,7 @@ _dbus_transport_init_base (DBusTransport *transport,
|
|||
transport->vtable = vtable;
|
||||
transport->loader = loader;
|
||||
transport->auth = auth;
|
||||
transport->live_messages_size = counter;
|
||||
transport->live_messages = counter;
|
||||
transport->authenticated = FALSE;
|
||||
transport->disconnected = FALSE;
|
||||
transport->is_server = (server_guid != NULL);
|
||||
|
|
@ -178,17 +182,22 @@ _dbus_transport_init_base (DBusTransport *transport,
|
|||
*/
|
||||
transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
|
||||
|
||||
/* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
|
||||
should be more than enough */
|
||||
transport->max_live_messages_unix_fds = 4096;
|
||||
|
||||
/* credentials read from socket if any */
|
||||
transport->credentials = creds;
|
||||
|
||||
_dbus_counter_set_notify (transport->live_messages_size,
|
||||
|
||||
_dbus_counter_set_notify (transport->live_messages,
|
||||
transport->max_live_messages_size,
|
||||
live_messages_size_notify,
|
||||
transport->max_live_messages_unix_fds,
|
||||
live_messages_notify,
|
||||
transport);
|
||||
|
||||
if (transport->address)
|
||||
_dbus_verbose ("Initialized transport on address %s\n", transport->address);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -212,9 +221,9 @@ _dbus_transport_finalize_base (DBusTransport *transport)
|
|||
|
||||
_dbus_message_loader_unref (transport->loader);
|
||||
_dbus_auth_unref (transport->auth);
|
||||
_dbus_counter_set_notify (transport->live_messages_size,
|
||||
0, NULL, NULL);
|
||||
_dbus_counter_unref (transport->live_messages_size);
|
||||
_dbus_counter_set_notify (transport->live_messages,
|
||||
0, 0, NULL, NULL);
|
||||
_dbus_counter_unref (transport->live_messages);
|
||||
dbus_free (transport->address);
|
||||
dbus_free (transport->expected_guid);
|
||||
if (transport->credentials)
|
||||
|
|
@ -802,6 +811,18 @@ _dbus_transport_get_is_anonymous (DBusTransport *transport)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the transport supports sending unix fds.
|
||||
*
|
||||
* @param transport the transport
|
||||
* @returns #TRUE if TRUE it is possible to send unix fds across the transport.
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_transport_can_pass_unix_fd(DBusTransport *transport)
|
||||
{
|
||||
return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of a transport. It will be
|
||||
* #NULL for a server-side transport.
|
||||
|
|
@ -1059,7 +1080,8 @@ recover_unused_bytes (DBusTransport *transport)
|
|||
DBusDispatchStatus
|
||||
_dbus_transport_get_dispatch_status (DBusTransport *transport)
|
||||
{
|
||||
if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
|
||||
if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
|
||||
_dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
|
||||
return DBUS_DISPATCH_COMPLETE; /* complete for now */
|
||||
|
||||
if (!_dbus_transport_get_is_authenticated (transport))
|
||||
|
|
@ -1116,7 +1138,7 @@ _dbus_transport_queue_messages (DBusTransport *transport)
|
|||
|
||||
_dbus_verbose ("queueing received message %p\n", message);
|
||||
|
||||
if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
|
||||
if (!_dbus_message_add_counter (message, transport->live_messages))
|
||||
{
|
||||
_dbus_message_loader_putback_message_link (transport->loader,
|
||||
link);
|
||||
|
|
@ -1153,6 +1175,19 @@ _dbus_transport_set_max_message_size (DBusTransport *transport,
|
|||
_dbus_message_loader_set_max_message_size (transport->loader, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_set_max_message_unix_fds().
|
||||
*
|
||||
* @param transport the transport
|
||||
* @param n the max number of unix fds of a single message
|
||||
*/
|
||||
void
|
||||
_dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
|
||||
long n)
|
||||
{
|
||||
_dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_get_max_message_size().
|
||||
*
|
||||
|
|
@ -1165,6 +1200,18 @@ _dbus_transport_get_max_message_size (DBusTransport *transport)
|
|||
return _dbus_message_loader_get_max_message_size (transport->loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_get_max_message_unix_fds().
|
||||
*
|
||||
* @param transport the transport
|
||||
* @returns max message unix fds
|
||||
*/
|
||||
long
|
||||
_dbus_transport_get_max_message_unix_fds (DBusTransport *transport)
|
||||
{
|
||||
return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_set_max_received_size().
|
||||
*
|
||||
|
|
@ -1176,12 +1223,30 @@ _dbus_transport_set_max_received_size (DBusTransport *transport,
|
|||
long size)
|
||||
{
|
||||
transport->max_live_messages_size = size;
|
||||
_dbus_counter_set_notify (transport->live_messages_size,
|
||||
_dbus_counter_set_notify (transport->live_messages,
|
||||
transport->max_live_messages_size,
|
||||
live_messages_size_notify,
|
||||
transport->max_live_messages_unix_fds,
|
||||
live_messages_notify,
|
||||
transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_set_max_received_unix_fds().
|
||||
*
|
||||
* @param transport the transport
|
||||
* @param n the max unix fds of all incoming messages
|
||||
*/
|
||||
void
|
||||
_dbus_transport_set_max_received_unix_fds (DBusTransport *transport,
|
||||
long n)
|
||||
{
|
||||
transport->max_live_messages_unix_fds = n;
|
||||
_dbus_counter_set_notify (transport->live_messages,
|
||||
transport->max_live_messages_size,
|
||||
transport->max_live_messages_unix_fds,
|
||||
live_messages_notify,
|
||||
transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_get_max_received_size().
|
||||
|
|
@ -1195,6 +1260,18 @@ _dbus_transport_get_max_received_size (DBusTransport *transport)
|
|||
return transport->max_live_messages_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_set_max_received_unix_fds().
|
||||
*
|
||||
* @param transport the transport
|
||||
* @returns max unix fds for all live messages
|
||||
*/
|
||||
long
|
||||
_dbus_transport_get_max_received_unix_fds (DBusTransport *transport)
|
||||
{
|
||||
return transport->max_live_messages_unix_fds;
|
||||
}
|
||||
|
||||
/**
|
||||
* See dbus_connection_get_unix_user().
|
||||
*
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ void _dbus_transport_disconnect (DBusTransport
|
|||
dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_can_pass_unix_fd (DBusTransport *transport);
|
||||
|
||||
const char* _dbus_transport_get_address (DBusTransport *transport);
|
||||
const char* _dbus_transport_get_server_id (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport,
|
||||
|
|
@ -52,12 +54,21 @@ void _dbus_transport_do_iteration (DBusTransport
|
|||
int timeout_milliseconds);
|
||||
DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_queue_messages (DBusTransport *transport);
|
||||
|
||||
void _dbus_transport_set_max_message_size (DBusTransport *transport,
|
||||
long size);
|
||||
long _dbus_transport_get_max_message_size (DBusTransport *transport);
|
||||
void _dbus_transport_set_max_received_size (DBusTransport *transport,
|
||||
long size);
|
||||
long _dbus_transport_get_max_received_size (DBusTransport *transport);
|
||||
|
||||
void _dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
|
||||
long n);
|
||||
long _dbus_transport_get_max_message_unix_fds (DBusTransport *transport);
|
||||
void _dbus_transport_set_max_received_unix_fds(DBusTransport *transport,
|
||||
long n);
|
||||
long _dbus_transport_get_max_received_unix_fds(DBusTransport *transport);
|
||||
|
||||
dbus_bool_t _dbus_transport_get_socket_fd (DBusTransport *transport,
|
||||
int *fd_p);
|
||||
dbus_bool_t _dbus_transport_get_unix_user (DBusTransport *transport,
|
||||
|
|
|
|||
|
|
@ -415,6 +415,10 @@
|
|||
<entry><literal>DICT_ENTRY</literal></entry>
|
||||
<entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry>
|
||||
<entry>Entry in a dict or map (array of key-value pairs)</entry>
|
||||
</row><row>
|
||||
<entry><literal>UNIX_FD</literal></entry>
|
||||
<entry>104 (ASCII 'h')</entry>
|
||||
<entry>Unix file descriptor</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
|
@ -579,6 +583,15 @@
|
|||
<entry>
|
||||
8
|
||||
</entry>
|
||||
</row><row>
|
||||
<entry><literal>UNIX_FD</literal></entry>
|
||||
<entry>32-bit unsigned integer in the message's byte
|
||||
order. The actual file descriptors need to be
|
||||
transferred out-of-band via some platform specific
|
||||
mechanism. On the wire, values of this type store the index to the
|
||||
file descriptor in the array of file descriptors that
|
||||
accompany the message.</entry>
|
||||
<entry>4</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
|
@ -999,6 +1012,22 @@
|
|||
If omitted, it is assumed to be the
|
||||
empty signature "" (i.e. the body must be 0-length).</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>UNIX_FDS</literal></entry>
|
||||
<entry>9</entry>
|
||||
<entry><literal>UINT32</literal></entry>
|
||||
<entry>optional</entry>
|
||||
<entry>The number of Unix file descriptors that
|
||||
accompany the message. If omitted, it is assumed
|
||||
that no Unix file descriptors accompany the
|
||||
message. The actual file descriptors need to be
|
||||
transferred via platform specific mechanism
|
||||
out-of-band. They must be sent at the same time as
|
||||
part of the message itself. They may not be sent
|
||||
before the first byte of the message itself is
|
||||
transferred or after the last byte of the message
|
||||
itself.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
|
@ -1410,6 +1439,7 @@
|
|||
<listitem><para>BEGIN</para></listitem>
|
||||
<listitem><para>DATA <data in hex encoding></para></listitem>
|
||||
<listitem><para>ERROR [human-readable error explanation]</para></listitem>
|
||||
<listitem><para>NEGOTIATE_UNIX_FD</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
From server to client are as follows:
|
||||
|
|
@ -1419,6 +1449,7 @@
|
|||
<listitem><para>OK <GUID in hex></para></listitem>
|
||||
<listitem><para>DATA <data in hex encoding></para></listitem>
|
||||
<listitem><para>ERROR</para></listitem>
|
||||
<listitem><para>AGREE_UNIX_FD</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
|
|
@ -1479,16 +1510,17 @@
|
|||
If authentication succeeds after exchanging DATA commands,
|
||||
an OK command must be sent to the client.
|
||||
</para>
|
||||
<para>
|
||||
The first octet received by the client after the \r\n of the OK
|
||||
command must be the first octet of the authenticated/encrypted
|
||||
stream of D-Bus messages.
|
||||
</para>
|
||||
<para>
|
||||
The first octet received by the server after the \r\n of the BEGIN
|
||||
command from the client must be the first octet of the
|
||||
authenticated/encrypted stream of D-Bus messages.
|
||||
</para>
|
||||
<para>
|
||||
If BEGIN is received by the server, the first octet received
|
||||
by the client after the \r\n of the OK command must be the
|
||||
first octet of the authenticated/encrypted stream of D-Bus
|
||||
messages.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-command-cancel">
|
||||
<title>CANCEL Command</title>
|
||||
|
|
@ -1542,20 +1574,24 @@
|
|||
<sect2 id="auth-command-ok">
|
||||
<title>OK Command</title>
|
||||
<para>
|
||||
The OK command indicates that the client has been authenticated,
|
||||
and that further communication will be a stream of D-Bus messages
|
||||
(optionally encrypted, as negotiated) rather than this protocol.
|
||||
The OK command indicates that the client has been
|
||||
authenticated. The client may now proceed with negotiating
|
||||
Unix file descriptor passing. To do that it shall send
|
||||
NEGOTIATE_UNIX_FD to the server.
|
||||
</para>
|
||||
<para>
|
||||
The first octet received by the client after the \r\n of the OK
|
||||
command must be the first octet of the authenticated/encrypted
|
||||
stream of D-Bus messages.
|
||||
Otherwise, the client must respond to the OK command by
|
||||
sending a BEGIN command, followed by its stream of messages,
|
||||
or by disconnecting. The server must not accept additional
|
||||
commands using this protocol after the BEGIN command has been
|
||||
received. Further communication will be a stream of D-Bus
|
||||
messages (optionally encrypted, as negotiated) rather than
|
||||
this protocol.
|
||||
</para>
|
||||
<para>
|
||||
The client must respond to the OK command by sending a BEGIN
|
||||
command, followed by its stream of messages, or by disconnecting.
|
||||
The server must not accept additional commands using this protocol
|
||||
after the OK command has been sent.
|
||||
If a client sends BEGIN the first octet received by the client
|
||||
after the \r\n of the OK command must be the first octet of
|
||||
the authenticated/encrypted stream of D-Bus messages.
|
||||
</para>
|
||||
<para>
|
||||
The OK command has one argument, which is the GUID of the server.
|
||||
|
|
@ -1589,6 +1625,56 @@
|
|||
negotiate extensions or changes to the D-Bus protocol in the future.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-command-negotiate-unix-fd">
|
||||
<title>NEGOTIATE_UNIX_FD Command</title>
|
||||
<para>
|
||||
The NEGOTIATE_UNIX_FD command indicates that the client
|
||||
supports Unix file descriptor passing. This command may only
|
||||
be sent after the connection is authenticated, i.e. after OK
|
||||
was received by the client. This command may only be sent on
|
||||
transports that support Unix file descriptor passing.
|
||||
</para>
|
||||
<para>
|
||||
On receiving NEGOTIATE_UNIX_FD the server must respond with
|
||||
either AGREE_UNIX_FD or ERROR. It shall respond the former if
|
||||
the transport chosen supports Unix file descriptor passing and
|
||||
the server supports this feature. It shall respond the latter
|
||||
if the transport does not support Unix file descriptor
|
||||
passing, the server does not support this feature, or the
|
||||
server decides not to enable file descriptor passing due to
|
||||
security or other reasons.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-command-agree-unix-fd">
|
||||
<title>AGREE_UNIX_FD Command</title>
|
||||
<para>
|
||||
The AGREE_UNIX_FD command indicates that the server supports
|
||||
Unix file descriptor passing. This command may only be sent
|
||||
after the connection is authenticated, and the client sent
|
||||
NEGOTIATE_UNIX_FD to enable Unix file descriptor passing. This
|
||||
command may only be sent on transports that support Unix file
|
||||
descriptor passing.
|
||||
</para>
|
||||
<para>
|
||||
On receiving AGREE_UNIX_FD the client must respond with BEGIN,
|
||||
followed by its stream of messages, or by disconnecting. The
|
||||
server must not accept additional commands using this protocol
|
||||
after the BEGIN command has been received. Further
|
||||
communication will be a stream of D-Bus messages (optionally
|
||||
encrypted, as negotiated) rather than this protocol.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-command-future">
|
||||
<title>Future Extensions</title>
|
||||
<para>
|
||||
Future extensions to the authentication and negotiation
|
||||
protocol are possible. For that new commands may be
|
||||
introduced. If a client or server receives an unknown command
|
||||
it shall respond with ERROR and not consider this fatal. New
|
||||
commands may be introduced both before, and after
|
||||
authentication, i.e. both before and after the OK command.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-examples">
|
||||
<title>Authentication examples</title>
|
||||
|
||||
|
|
@ -1669,6 +1755,30 @@
|
|||
C: BEGIN
|
||||
</programlisting>
|
||||
</figure>
|
||||
<figure>
|
||||
<title>Example of successful magic cookie authentication with successful negotiation of Unix FD passing</title>
|
||||
<programlisting>
|
||||
(MAGIC_COOKIE is a made up mechanism)
|
||||
|
||||
C: AUTH MAGIC_COOKIE 3138363935333137393635383634
|
||||
S: OK 1234deadbeef
|
||||
C: NEGOTIATE_UNIX_FD
|
||||
S: AGREE_UNIX_FD
|
||||
C: BEGIN
|
||||
</programlisting>
|
||||
</figure>
|
||||
<figure>
|
||||
<title>Example of successful magic cookie authentication with unsuccessful negotiation of Unix FD passing</title>
|
||||
<programlisting>
|
||||
(MAGIC_COOKIE is a made up mechanism)
|
||||
|
||||
C: AUTH MAGIC_COOKIE 3138363935333137393635383634
|
||||
S: OK 1234deadbeef
|
||||
C: NEGOTIATE_UNIX_FD
|
||||
S: ERROR
|
||||
C: BEGIN
|
||||
</programlisting>
|
||||
</figure>
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="auth-states">
|
||||
|
|
@ -4078,4 +4188,3 @@
|
|||
|
||||
</glossary>
|
||||
</article>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue