# include <unistd.h>
# include <sys/socket.h>
# include <sys/types.h>
+# include <sys/wait.h>
# include <pwd.h>
#endif
}
#ifdef DBUS_UNIX
+static gboolean
+can_become_user_or_skip (uid_t uid)
+{
+ gchar *message;
+ pid_t child_pid;
+ pid_t pid;
+ int wstatus;
+
+ /* We can't switch to the uid without affecting the whole process,
+ * which we don't necessarily want to do, so try it in a child process. */
+ child_pid = fork ();
+
+ if (child_pid < 0)
+ g_error ("fork: %s", g_strerror (errno));
+
+ if (child_pid == 0)
+ {
+ /* Child process: try to become uid, exit 0 on success, exit with
+ * status = errno on failure */
+
+ if (setuid (uid) != 0)
+ {
+ /* make sure we report failure even if errno is wrong */
+ if (errno == 0)
+ errno = ENODATA;
+
+ _exit (errno);
+ }
+
+ /* success */
+ _exit (0);
+ }
+
+ /* Parent process: wait for child and report result */
+
+ pid = waitpid (child_pid, &wstatus, 0);
+ g_assert_cmpuint (child_pid, ==, pid);
+
+ if (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) == 0)
+ return TRUE;
+
+ if (WIFEXITED (wstatus))
+ message = g_strdup_printf ("unable to become uid %lu: %s",
+ (unsigned long) uid,
+ g_strerror (WEXITSTATUS (wstatus)));
+ else
+ message = g_strdup_printf ("unable to become uid %lu: unknown wait status %d",
+ (unsigned long) uid,
+ wstatus);
+
+ g_test_skip (message);
+ g_free (message);
+ return FALSE;
+}
+
static void
child_setup (gpointer user_data)
{
return NULL;
}
+ if (!can_become_user_or_skip (pwd->pw_uid))
+ return NULL;
+
if (user == TEST_USER_ROOT_DROP_TO_MESSAGEBUS)
{
/* Let the dbus-daemon start as root and drop privileges
return NULL;
}
+ if (!can_become_user_or_skip (pwd->pw_uid))
+ return NULL;
+
break;
case TEST_USER_ME: