diff --git a/bus/dispatch.c b/bus/dispatch.c index 7a61953..02b1883 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -1310,6 +1310,11 @@ check_get_connection_unix_process_id (BusContext *context, #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__linux__) || \ defined(__OpenBSD__) + /* In principle NetBSD should also be in that list, but + * its implementation of PID-passing doesn't work + * over a socketpair() as used in the debug-pipe transport. + * We test this functionality in a more realistic situation + * in test/dbus-daemon.c. */ warn_unexpected (connection, message, "not this error"); goto out; diff --git a/configure.ac b/configure.ac index 2a7f83f..9e827e6 100644 --- a/configure.ac +++ b/configure.ac @@ -815,6 +815,11 @@ if test x$dbus_have_struct_cmsgcred = xyes; then AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure]) fi +AC_CHECK_MEMBER([struct unpcbid.unp_pid], + [AC_DEFINE([HAVE_UNPCBID], 1, [Have unpcbid structure])], + [], + [[#include ]]) + AC_CHECK_FUNCS(getpeerucred getpeereid) AC_CHECK_FUNCS(pipe2 accept4) diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index b95cad6..53ac1c0 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -993,7 +993,8 @@ do_exec (int child_err_report_fd, DBusSpawnChildSetupFunc child_setup, void *user_data) { -#ifdef DBUS_ENABLE_EMBEDDED_TESTS +/* #ifdef DBUS_ENABLE_EMBEDDED_TESTS */ +#ifdef XXXPW int i, max_open; #endif @@ -1004,7 +1005,8 @@ do_exec (int child_err_report_fd, if (child_setup) (* child_setup) (user_data); -#ifdef DBUS_ENABLE_EMBEDDED_TESTS +/* #ifdef DBUS_ENABLE_EMBEDDED_TESTS */ +#ifdef XXXPW max_open = sysconf (_SC_OPEN_MAX); for (i = 3; i < max_open; i++) @@ -1017,7 +1019,7 @@ do_exec (int child_err_report_fd, retval = fcntl (i, F_GETFD); if (retval != -1 && !(retval & FD_CLOEXEC)) - _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i); + _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i); } #endif diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 170d865..2d8ce32 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1741,16 +1741,58 @@ _dbus_read_credentials_socket (int client_fd, #endif int cr_len = sizeof (cr); - if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && - cr_len == sizeof (cr)) + if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0) { - pid_read = cr.pid; - uid_read = cr.uid; + _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n", + _dbus_strerror (errno)); + } + else if (cr_len != sizeof (cr)) + { + _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n", + cr_len, (int) sizeof (cr)); + } + else + { + pid_read = cr.pid; + uid_read = cr.uid; + } +#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID) + /* Another variant of the above - used on NetBSD + */ + struct unpcbid cr; + socklen_t cr_len = sizeof (cr); + struct sockaddr_storage store; + socklen_t store_len = sizeof(store); + + if (getsockname (client_fd, sstosa(&store), &store_len) != 0) + { + _dbus_verbose ("Failed to getsockname: %s\n", + _dbus_strerror (errno)); + } + _dbus_verbose ("getsockname: length: %d family: ", store.ss_len); + switch (store.ss_family) + { + case PF_UNSPEC: _dbus_verbose ("PF_UNSPEC\n"); break; + case PF_LOCAL: _dbus_verbose ("PF_LOCAL\n"); break; + case PF_INET: _dbus_verbose ("PF_INET\n"); break; + case PF_LINK: _dbus_verbose ("PF_LINK\n"); break; + case PF_INET6: _dbus_verbose ("PF_INET6\n"); break; + default: _dbus_verbose ("%d\n", store.ss_family); break; + } + if (getsockopt (client_fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0) + { + _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n", + _dbus_strerror (errno)); + } + else if (cr_len != sizeof (cr)) + { + _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n", + cr_len, (int) sizeof (cr)); } else { - _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", - cr_len, (int) sizeof (cr), _dbus_strerror (errno)); + pid_read = cr.unp_pid; + uid_read = cr.unp_euid; } #elif defined(HAVE_CMSGCRED) /* We only check for HAVE_CMSGCRED, but we're really assuming that the diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index 4b3b61e..803ac75 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -458,6 +458,60 @@ test_creds (Fixture *f, } static void +test_processid (Fixture *f, + gconstpointer context) +{ + const char *unique = dbus_bus_get_unique_name (f->left_conn); + DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionUnixProcessID"); + DBusPendingCall *pc; + DBusError error = DBUS_ERROR_INIT; + guint32 pid; + + if (m == NULL) + g_error ("OOM"); + + if (!dbus_message_append_args (m, + DBUS_TYPE_STRING, &unique, + DBUS_TYPE_INVALID)) + g_error ("OOM"); + + if (!dbus_connection_send_with_reply (f->left_conn, m, &pc, + DBUS_TIMEOUT_USE_DEFAULT) || + pc == NULL) + g_error ("OOM"); + + dbus_message_unref (m); + m = NULL; + + if (dbus_pending_call_get_completed (pc)) + pending_call_store_reply (pc, &m); + else if (!dbus_pending_call_set_notify (pc, pending_call_store_reply, + &m, NULL)) + g_error ("OOM"); + + while (m == NULL) + test_main_context_iterate (f->ctx, TRUE); + + g_assert_cmpstr (dbus_message_get_signature (m), ==, "u"); + + g_assert_true (dbus_message_get_args (m, &error, + DBUS_TYPE_UINT32, &pid, + DBUS_TYPE_INVALID)); +// g_assert_no_error (&error); + + g_message ("GetConnectionUnixProcessID returned %u", pid); + +#ifdef G_OS_UNIX + g_assert_cmpuint (pid, ==, getpid ()); +#elif defined(G_OS_WIN32) + g_assert_cmpuint (pid, ==, GetCurrentProcessId ()); +#else + g_assert_not_reached (); +#endif +} + +static void teardown (Fixture *f, gconstpointer context G_GNUC_UNUSED) { @@ -514,6 +568,7 @@ main (int argc, g_test_add ("/echo/limited", Fixture, &limited_config, setup, test_echo, teardown); g_test_add ("/creds", Fixture, NULL, setup, test_creds, teardown); + g_test_add ("/processid", Fixture, NULL, setup, test_processid, teardown); return g_test_run (); }