/**
 * polkit_backend_session_monitor_get_session_for_subject:
 * @monitor: A #PolkitBackendSessionMonitor.
 * @subject: A #PolkitSubject.
 * @error: Return location for error.
 *
 * Gets the session corresponding to @subject or %NULL if no session exists.
 *
 * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref().
 */
PolkitSubject *
polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor,
                                                        PolkitSubject               *subject,
                                                        GError                     **error)
{
  PolkitUnixProcess *tmp_process = NULL;
  PolkitUnixProcess *process = NULL;
  PolkitSubject *session = NULL;
  char *session_id = NULL;
  pid_t pid;
#if HAVE_SD_UID_GET_DISPLAY
  uid_t uid;
#endif

  if (POLKIT_IS_UNIX_PROCESS (subject))
    process = POLKIT_UNIX_PROCESS (subject); /* We already have a process */
  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
    {
      /* Convert bus name to process */
      tmp_process = (PolkitUnixProcess*)polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject), NULL, error);
      if (!tmp_process)
	goto out;
      process = tmp_process;
    }
  else
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Cannot get session for subject of type %s",
                   g_type_name (G_TYPE_FROM_INSTANCE (subject)));
    }

  /* Now do process -> pid -> same session */
  g_assert (process != NULL);
  pid = polkit_unix_process_get_pid (process);

  if (sd_pid_get_session (pid, &session_id) >= 0)
    {
      session = polkit_unix_session_new (session_id);
      goto out;
    }

#if HAVE_SD_UID_GET_DISPLAY
  /* Now do process -> uid -> graphical session (systemd version 213)*/
  if (sd_pid_get_owner_uid (pid, &uid) < 0)
    goto out;

  if (sd_uid_get_display (uid, &session_id) >= 0)
    {
      session = polkit_unix_session_new (session_id);
      goto out;
    }
#endif

 out:
  free (session_id);
  if (tmp_process) g_object_unref (tmp_process);
  return session;
}
Exemple #2
0
static int file_of_session(const char *session, char **_p) {
        char *p;
        int r;

        assert(_p);

        if (session) {
                if (!session_id_valid(session))
                        return -EINVAL;

                p = strappend("/run/systemd/sessions/", session);
        } else {
                _cleanup_free_ char *buf = NULL;

                r = sd_pid_get_session(0, &buf);
                if (r < 0)
                        return r;

                p = strappend("/run/systemd/sessions/", buf);
        }

        if (!p)
                return -ENOMEM;

        *_p = p;
        return 0;
}
Exemple #3
0
Eina_Bool logind_init(E_DBus_Connection *conn)
{
#if HAVE_LIBSYSTEMD_LOGIN
  char *id;

  DBG("Requesting systemd-login session via library");

  if (sd_pid_get_session (empower_pid, &id) < 0)
    return EINA_FALSE;

  _logind_session_id = eina_stringshare_add(id);
  free(id);
  return EINA_TRUE;
#else
  DBusMessage *msg;
  DBusMessageIter itr;

  DBG("Requesting systemd-login session via dbus");
  msg = dbus_message_new_method_call(LOGIND_BUS, LOGIND_PATH, LOGIND_INTERFACE, "GetSessionByPID");

  if (!msg)
    return EINA_FALSE;

  dbus_message_iter_init_append(msg, &itr);
  dbus_message_iter_append_basic(&itr, DBUS_TYPE_UINT32, &empower_pid);

  e_dbus_message_send(conn, msg, _logind_session_id_done, 5000, NULL);

  return EINA_TRUE;
#endif
}
Exemple #4
0
/**
 * pk_dbus_get_session_systemd:
 **/
static gchar *
pk_dbus_get_session_systemd (guint pid)
{
	g_autofree gchar *session_id = NULL;
	uid_t uid;

	/* do process -> pid -> same session */
	if (sd_pid_get_session (pid, &session_id) >= 0)
		return pk_dbus_make_logind_session_id (session_id);

	/* do process -> uid -> graphical session */
	if (sd_pid_get_owner_uid (pid, &uid) < 0)
		return NULL;
	if (sd_uid_get_display (uid, &session_id) >= 0)
		return pk_dbus_make_logind_session_id (session_id);

	return NULL;
}
Exemple #5
0
static const gchar *
get_seat (void)
{
  static gsize once = 0;
  static char *seat = NULL;

  if (g_once_init_enter (&once))
    {
      char *session = NULL;
      if (sd_pid_get_session (getpid (), &session) == 0)
        {
          sd_session_get_seat (session, &seat);
          free (session);
          /* we intentionally leak seat here... */
        }
      g_once_init_leave (&once, (gsize) 1);
    }
  return seat;
}
Exemple #6
0
static bool
weston_launch_allowed(struct weston_launch *wl)
{
	struct group *gr;
	gid_t *groups;
	int i;
#ifdef HAVE_SYSTEMD_LOGIN
	char *session, *seat;
	int err;
#endif

	if (getuid() == 0)
		return true;

	gr = getgrnam("weston-launch");
	if (gr) {
		groups = read_groups();
		if (groups) {
			for (i = 0; groups[i]; ++i) {
				if (groups[i] == gr->gr_gid) {
					free(groups);
					return true;
				}
			}
			free(groups);
		}
	}

#ifdef HAVE_SYSTEMD_LOGIN
	err = sd_pid_get_session(getpid(), &session);
	if (err == 0 && session) {
		if (sd_session_is_active(session) &&
		    sd_session_get_seat(session, &seat) == 0) {
			free(seat);
			free(session);
			return true;
		}
		free(session);
	}
#endif

	return false;
}
Exemple #7
0
/**
 * pk_dbus_get_session_systemd:
 **/
static gchar *
pk_dbus_get_session_systemd (guint pid)
{
	gchar *session = NULL;
	gchar *session_tmp = NULL;
	gint rc;

	rc = sd_pid_get_session (pid, &session_tmp);
	if (rc < 0) {
		g_warning ("failed to get session, errno %i", rc);
		goto out;
	}
	if (session_tmp == NULL) {
		g_warning ("no session for %i", pid);
		goto out;
	}

	/* convert to a GLib allocated string */
	session = g_strdup_printf ("/org/freedesktop/logind/session-%s",
				   session_tmp);
out:
	free (session_tmp);
	return session;
}
Exemple #8
0
int main(int argc, char* argv[]) {
        int r, k;
        uid_t u, u2;
        char *seat, *type, *class, *display;
        char *session;
        char *state;
        char *session2;
        char *t;
        char **seats, **sessions;
        uid_t *uids;
        unsigned n;
        struct pollfd pollfd;
        sd_login_monitor *m;

        assert_se(sd_pid_get_session(0, &session) == 0);
        printf("session = %s\n", session);

        assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
        printf("user = %lu\n", (unsigned long) u2);

        r = sd_uid_get_sessions(u2, false, &sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_sessions(u2, false, NULL));

        r = sd_uid_get_seats(u2, false, &seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("seats = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_seats(u2, false, NULL));

        r = sd_session_is_active(session);
        assert_se(r >= 0);
        printf("active = %s\n", yes_no(r));

        r = sd_session_get_state(session, &state);
        assert_se(r >= 0);
        printf("state = %s\n", state);
        free(state);

        assert_se(sd_session_get_uid(session, &u) >= 0);
        printf("uid = %lu\n", (unsigned long) u);
        assert_se(u == u2);

        assert_se(sd_session_get_type(session, &type) >= 0);
        printf("type = %s\n", type);
        free(type);

        assert_se(sd_session_get_class(session, &class) >= 0);
        printf("class = %s\n", class);
        free(class);

        assert_se(sd_session_get_display(session, &display) >= 0);
        printf("display = %s\n", display);
        free(display);

        assert_se(sd_session_get_seat(session, &seat) >= 0);
        printf("seat = %s\n", seat);

        r = sd_seat_can_multi_session(seat);
        assert_se(r >= 0);
        printf("can do multi session = %s\n", yes_no(r));

        r = sd_seat_can_tty(seat);
        assert_se(r >= 0);
        printf("can do tty = %s\n", yes_no(r));

        r = sd_seat_can_graphical(seat);
        assert_se(r >= 0);
        printf("can do graphical = %s\n", yes_no(r));

        assert_se(sd_uid_get_state(u, &state) >= 0);
        printf("state = %s\n", state);

        assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);

        k = sd_uid_is_on_seat(u, 1, seat);
        assert_se(k >= 0);
        assert_se(!!r == !!r);

        assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
        printf("session2 = %s\n", session2);
        printf("uid2 = %lu\n", (unsigned long) u2);

        r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
        assert_se(r >= 0);
        printf("n_sessions = %i\n", r);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);
        printf("uids =");
        for (k = 0; k < (int) n; k++)
                printf(" %lu", (unsigned long) uids[k]);
        printf("\n");
        free(uids);

        assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);

        free(session);
        free(state);
        free(session2);
        free(seat);

        r = sd_get_seats(&seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("n_seats = %i\n", r);
        printf("seats = %s\n", t);
        free(t);

        assert_se(sd_get_seats(NULL) == r);

        r = sd_seat_get_active(NULL, &t, NULL);
        assert_se(r >= 0);
        printf("active session on current seat = %s\n", t);
        free(t);

        r = sd_get_sessions(&sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("n_sessions = %i\n", r);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(sd_get_sessions(NULL) == r);

        r = sd_get_uids(&uids);
        assert_se(r >= 0);

        printf("uids =");
        for (k = 0; k < r; k++)
                printf(" %lu", (unsigned long) uids[k]);
        printf("\n");
        free(uids);

        printf("n_uids = %i\n", r);
        assert_se(sd_get_uids(NULL) == r);

        r = sd_login_monitor_new("session", &m);
        assert_se(r >= 0);

        zero(pollfd);
        pollfd.fd = sd_login_monitor_get_fd(m);
        pollfd.events = POLLIN;

        for (n = 0; n < 5; n++) {
                r = poll(&pollfd, 1, -1);
                assert_se(r >= 0);

                sd_login_monitor_flush(m);
                printf("Wake!\n");
        }

        sd_login_monitor_unref(m);

        return 0;
}
Exemple #9
0
int main(int argc, char* argv[]) {
        int r, j = 0;
        _cleanup_free_ char *p = NULL;
        ssize_t n;
        pid_t pid;
        uid_t uid;
        gid_t gid;
        struct iovec iovec[14];
        _cleanup_free_ char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
                *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL,
                *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *t = NULL;

        prctl(PR_SET_DUMPABLE, 0);

        if (argc != _ARG_MAX) {
                log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
                log_open();

                log_error("Invalid number of arguments passed from kernel.");
                r = -EINVAL;
                goto finish;
        }

        r = parse_pid(argv[ARG_PID], &pid);
        if (r < 0) {
                log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
                log_open();

                log_error("Failed to parse PID.");
                goto finish;
        }

        if (cg_pid_get_unit(pid, &t) >= 0) {

                if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
                        /* Make sure we don't make use of the journal,
                         * if it's the journal which is crashing */
                        log_set_target(LOG_TARGET_KMSG);
                        log_open();

                        r = divert_coredump();
                        goto finish;
                }

                core_unit = strappend("COREDUMP_UNIT=", t);
        } else if (cg_pid_get_user_unit(pid, &t) >= 0)
                core_unit = strappend("COREDUMP_USER_UNIT=", t);

        if (core_unit)
                IOVEC_SET_STRING(iovec[j++], core_unit);

        /* OK, now we know it's not the journal, hence make use of
         * it */
        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
        log_open();

        r = parse_uid(argv[ARG_UID], &uid);
        if (r < 0) {
                log_error("Failed to parse UID.");
                goto finish;
        }

        r = parse_gid(argv[ARG_GID], &gid);
        if (r < 0) {
                log_error("Failed to parse GID.");
                goto finish;
        }

        core_pid = strappend("COREDUMP_PID=", argv[ARG_PID]);
        if (core_pid)
                IOVEC_SET_STRING(iovec[j++], core_pid);

        core_uid = strappend("COREDUMP_UID=", argv[ARG_UID]);
        if (core_uid)
                IOVEC_SET_STRING(iovec[j++], core_uid);

        core_gid = strappend("COREDUMP_GID=", argv[ARG_GID]);
        if (core_gid)
                IOVEC_SET_STRING(iovec[j++], core_gid);

        core_signal = strappend("COREDUMP_SIGNAL=", argv[ARG_SIGNAL]);
        if (core_signal)
                IOVEC_SET_STRING(iovec[j++], core_signal);

        core_comm = strappend("COREDUMP_COMM=", argv[ARG_COMM]);
        if (core_comm)
                IOVEC_SET_STRING(iovec[j++], core_comm);

#ifdef HAVE_LOGIND
        if (sd_pid_get_session(pid, &t) >= 0) {
                core_session = strappend("COREDUMP_SESSION=", t);
                free(t);

                if (core_session)
                        IOVEC_SET_STRING(iovec[j++], core_session);
        }

#endif

        if (get_process_exe(pid, &t) >= 0) {
                core_exe = strappend("COREDUMP_EXE=", t);
                free(t);

                if (core_exe)
                        IOVEC_SET_STRING(iovec[j++], core_exe);
        }

        if (get_process_cmdline(pid, 0, false, &t) >= 0) {
                core_cmdline = strappend("COREDUMP_CMDLINE=", t);
                free(t);

                if (core_cmdline)
                        IOVEC_SET_STRING(iovec[j++], core_cmdline);
        }

        core_timestamp = strjoin("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL);
        if (core_timestamp)
                IOVEC_SET_STRING(iovec[j++], core_timestamp);

        IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
        IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");

        core_message = strjoin("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL);
        if (core_message)
                IOVEC_SET_STRING(iovec[j++], core_message);

        /* Now, let's drop privileges to become the user who owns the
         * segfaulted process and allocate the coredump memory under
         * his uid. This also ensures that the credentials journald
         * will see are the ones of the coredumping user, thus making
         * sure the user himself gets access to the core dump. */

        if (setresgid(gid, gid, gid) < 0 ||
            setresuid(uid, uid, uid) < 0) {
                log_error("Failed to drop privileges: %m");
                r = -errno;
                goto finish;
        }

        p = malloc(9 + COREDUMP_MAX);
        if (!p) {
                r = log_oom();
                goto finish;
        }

        memcpy(p, "COREDUMP=", 9);

        n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false);
        if (n < 0) {
                log_error("Failed to read core dump data: %s", strerror(-n));
                r = (int) n;
                goto finish;
        }

        iovec[j].iov_base = p;
        iovec[j].iov_len = 9 + n;
        j++;

        r = sd_journal_sendv(iovec, j);
        if (r < 0)
                log_error("Failed to send coredump: %s", strerror(-r));

finish:
        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemple #10
0
Eina_Bool 
_ecore_drm_logind_connect(Ecore_Drm_Device *dev)
{
#ifdef HAVE_SYSTEMD
   char *seat;

   /* get session id */
   if (sd_pid_get_session(getpid(), &dev->session) < 0)
     {
        ERR("Could not get systemd session: %m");
        return EINA_FALSE;
     }

   if (sd_session_get_seat(dev->session, &seat) < 0)
     {
        ERR("Could not get systemd seat: %m");
        return EINA_FALSE;
     }
   else if (strcmp(dev->seat, seat))
     {
        ERR("Session seat '%s' differs from device seat '%s'", seat, dev->seat);
        free(seat);
        return EINA_FALSE;
     }

   free(seat);

   if (!_ecore_drm_logind_vt_get(dev)) return EINA_FALSE;
#endif

   if (!_ecore_drm_dbus_init(dev)) return EINA_FALSE;

   /* take control of session */
   if (!_ecore_drm_dbus_session_take())
     {
        ERR("Could not take control of session");
        goto take_err;
     }

   /* setup vt */
   if (!_ecore_drm_logind_vt_setup(dev))
     {
        ERR("Could not setup vt '%d'", dev->vt);
        goto vt_err;
     }

   /* setup handler for vt signals */
   if (!dev->tty.event_hdlr)
     {
        dev->tty.event_hdlr = 
          ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, 
                                  _ecore_drm_logind_cb_vt_signal, dev);
     }

   if (!active_hdlr)
     {
        active_hdlr = 
          ecore_event_handler_add(ECORE_DRM_EVENT_ACTIVATE, 
                                  _ecore_drm_logind_cb_activate, dev);
     }

   return EINA_TRUE;

vt_err:
   _ecore_drm_dbus_session_release();
take_err:
   _ecore_drm_dbus_shutdown();
   return EINA_FALSE;
}
Exemple #11
0
int main(int argc, char* argv[]) {

        /* The small core field we allocate on the stack, to keep things simple */
        char
                *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL,
                *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL,
                *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL,
                *core_slice = NULL;

        /* The larger ones we allocate on the heap */
        _cleanup_free_ char
                *core_timestamp = NULL,  *core_message = NULL, *coredump_data = NULL, *core_owner_uid = NULL,
                *core_open_fds = NULL, *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL,
                *core_proc_cgroup = NULL, *core_environ = NULL;

        _cleanup_free_ char *exe = NULL, *comm = NULL, *filename = NULL;
        const char *info[_INFO_LEN];

        _cleanup_close_ int coredump_fd = -1;

        struct iovec iovec[26];
        uint64_t coredump_size;
        int r, j = 0;
        uid_t uid, owner_uid;
        gid_t gid;
        pid_t pid;
        char *t;
        const char *p;

        /* Make sure we never enter a loop */
        prctl(PR_SET_DUMPABLE, 0);

        /* First, log to a safe place, since we don't know what
         * crashed and it might be journald which we'd rather not log
         * to then. */
        log_set_target(LOG_TARGET_KMSG);
        log_open();

        if (argc < INFO_COMM + 1) {
                log_error("Not enough arguments passed from kernel (%d, expected %d).",
                          argc - 1, INFO_COMM + 1 - 1);
                r = -EINVAL;
                goto finish;
        }

        /* Ignore all parse errors */
        parse_config();

        log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
        log_debug("Selected compression %s.", yes_no(arg_compress));

        r = parse_uid(argv[INFO_UID + 1], &uid);
        if (r < 0) {
                log_error("Failed to parse UID.");
                goto finish;
        }

        r = parse_pid(argv[INFO_PID + 1], &pid);
        if (r < 0) {
                log_error("Failed to parse PID.");
                goto finish;
        }

        r = parse_gid(argv[INFO_GID + 1], &gid);
        if (r < 0) {
                log_error("Failed to parse GID.");
                goto finish;
        }

        if (get_process_comm(pid, &comm) < 0) {
                log_warning("Failed to get COMM, falling back to the command line.");
                comm = strv_join(argv + INFO_COMM + 1, " ");
        }

        if (get_process_exe(pid, &exe) < 0)
                log_warning("Failed to get EXE.");

        info[INFO_PID] = argv[INFO_PID + 1];
        info[INFO_UID] = argv[INFO_UID + 1];
        info[INFO_GID] = argv[INFO_GID + 1];
        info[INFO_SIGNAL] = argv[INFO_SIGNAL + 1];
        info[INFO_TIMESTAMP] = argv[INFO_TIMESTAMP + 1];
        info[INFO_COMM] = comm;
        info[INFO_EXE] = exe;

        if (cg_pid_get_unit(pid, &t) >= 0) {

                if (streq(t, SPECIAL_JOURNALD_SERVICE)) {
                        free(t);

                        /* If we are journald, we cut things short,
                         * don't write to the journal, but still
                         * create a coredump. */

                        if (arg_storage != COREDUMP_STORAGE_NONE)
                                arg_storage = COREDUMP_STORAGE_EXTERNAL;

                        r = save_external_coredump(info, uid, &filename, &coredump_fd, &coredump_size);
                        if (r < 0)
                                goto finish;

                        r = maybe_remove_external_coredump(filename, coredump_size);
                        if (r < 0)
                                goto finish;

                        log_info("Detected coredump of the journal daemon itself, diverted to %s.", filename);
                        goto finish;
                }

                core_unit = strjoina("COREDUMP_UNIT=", t);
                free(t);

        } else if (cg_pid_get_user_unit(pid, &t) >= 0) {
                core_unit = strjoina("COREDUMP_USER_UNIT=", t);
                free(t);
        }

        if (core_unit)
                IOVEC_SET_STRING(iovec[j++], core_unit);

        /* OK, now we know it's not the journal, hence we can make use
         * of it now. */
        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
        log_open();

        core_pid = strjoina("COREDUMP_PID=", info[INFO_PID]);
        IOVEC_SET_STRING(iovec[j++], core_pid);

        core_uid = strjoina("COREDUMP_UID=", info[INFO_UID]);
        IOVEC_SET_STRING(iovec[j++], core_uid);

        core_gid = strjoina("COREDUMP_GID=", info[INFO_GID]);
        IOVEC_SET_STRING(iovec[j++], core_gid);

        core_signal = strjoina("COREDUMP_SIGNAL=", info[INFO_SIGNAL]);
        IOVEC_SET_STRING(iovec[j++], core_signal);

        if (sd_pid_get_session(pid, &t) >= 0) {
                core_session = strjoina("COREDUMP_SESSION=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_session);
        }

        if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
                r = asprintf(&core_owner_uid,
                             "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
                if (r > 0)
                        IOVEC_SET_STRING(iovec[j++], core_owner_uid);
        }

        if (sd_pid_get_slice(pid, &t) >= 0) {
                core_slice = strjoina("COREDUMP_SLICE=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_slice);
        }

        if (comm) {
                core_comm = strjoina("COREDUMP_COMM=", comm);
                IOVEC_SET_STRING(iovec[j++], core_comm);
        }

        if (exe) {
                core_exe = strjoina("COREDUMP_EXE=", exe);
                IOVEC_SET_STRING(iovec[j++], core_exe);
        }

        if (get_process_cmdline(pid, 0, false, &t) >= 0) {
                core_cmdline = strjoina("COREDUMP_CMDLINE=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_cmdline);
        }

        if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) {
                core_cgroup = strjoina("COREDUMP_CGROUP=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_cgroup);
        }

        if (compose_open_fds(pid, &t) >= 0) {
                core_open_fds = strappend("COREDUMP_OPEN_FDS=", t);
                free(t);

                if (core_open_fds)
                        IOVEC_SET_STRING(iovec[j++], core_open_fds);
        }

        p = procfs_file_alloca(pid, "status");
        if (read_full_file(p, &t, NULL) >= 0) {
                core_proc_status = strappend("COREDUMP_PROC_STATUS=", t);
                free(t);

                if (core_proc_status)
                        IOVEC_SET_STRING(iovec[j++], core_proc_status);
        }

        p = procfs_file_alloca(pid, "maps");
        if (read_full_file(p, &t, NULL) >= 0) {
                core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t);
                free(t);

                if (core_proc_maps)
                        IOVEC_SET_STRING(iovec[j++], core_proc_maps);
        }

        p = procfs_file_alloca(pid, "limits");
        if (read_full_file(p, &t, NULL) >= 0) {
                core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t);
                free(t);

                if (core_proc_limits)
                        IOVEC_SET_STRING(iovec[j++], core_proc_limits);
        }

        p = procfs_file_alloca(pid, "cgroup");
        if (read_full_file(p, &t, NULL) >=0) {
                core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t);
                free(t);

                if (core_proc_cgroup)
                        IOVEC_SET_STRING(iovec[j++], core_proc_cgroup);
        }

        if (get_process_cwd(pid, &t) >= 0) {
                core_cwd = strjoina("COREDUMP_CWD=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_cwd);
        }

        if (get_process_root(pid, &t) >= 0) {
                core_root = strjoina("COREDUMP_ROOT=", t);
                free(t);

                IOVEC_SET_STRING(iovec[j++], core_root);
        }

        if (get_process_environ(pid, &t) >= 0) {
                core_environ = strappend("COREDUMP_ENVIRON=", t);
                free(t);

                if (core_environ)
                        IOVEC_SET_STRING(iovec[j++], core_environ);
        }

        core_timestamp = strjoin("COREDUMP_TIMESTAMP=", info[INFO_TIMESTAMP], "000000", NULL);
        if (core_timestamp)
                IOVEC_SET_STRING(iovec[j++], core_timestamp);

        IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
        IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");

        /* Vacuum before we write anything again */
        coredump_vacuum(-1, arg_keep_free, arg_max_use);

        /* Always stream the coredump to disk, if that's possible */
        r = save_external_coredump(info, uid, &filename, &coredump_fd, &coredump_size);
        if (r < 0)
                /* skip whole core dumping part */
                goto log;

        /* If we don't want to keep the coredump on disk, remove it
         * now, as later on we will lack the privileges for
         * it. However, we keep the fd to it, so that we can still
         * process it and log it. */
        r = maybe_remove_external_coredump(filename, coredump_size);
        if (r < 0)
                goto finish;
        if (r == 0) {
                const char *coredump_filename;

                coredump_filename = strjoina("COREDUMP_FILENAME=", filename);
                IOVEC_SET_STRING(iovec[j++], coredump_filename);
        }

        /* Vacuum again, but exclude the coredump we just created */
        coredump_vacuum(coredump_fd, arg_keep_free, arg_max_use);

        /* Now, let's drop privileges to become the user who owns the
         * segfaulted process and allocate the coredump memory under
         * the user's uid. This also ensures that the credentials
         * journald will see are the ones of the coredumping user,
         * thus making sure the user gets access to the core
         * dump. Let's also get rid of all capabilities, if we run as
         * root, we won't need them anymore. */
        r = drop_privileges(uid, gid, 0);
        if (r < 0) {
                log_error_errno(r, "Failed to drop privileges: %m");
                goto finish;
        }

#ifdef HAVE_ELFUTILS
        /* Try to get a strack trace if we can */
        if (coredump_size <= arg_process_size_max) {
                _cleanup_free_ char *stacktrace = NULL;

                r = coredump_make_stack_trace(coredump_fd, exe, &stacktrace);
                if (r >= 0)
                        core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.\n\n", stacktrace, NULL);
                else if (r == -EINVAL)
                        log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno()));
                else
                        log_warning_errno(r, "Failed to generate stack trace: %m");
        }

        if (!core_message)
#endif
log:
        core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.", NULL);
        if (core_message)
                IOVEC_SET_STRING(iovec[j++], core_message);

        /* Optionally store the entire coredump in the journal */
        if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) &&
            coredump_size <= arg_journal_size_max) {
                size_t sz = 0;

                /* Store the coredump itself in the journal */

                r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz);
                if (r >= 0) {
                        iovec[j].iov_base = coredump_data;
                        iovec[j].iov_len = sz;
                        j++;
                }
        }

        r = sd_journal_sendv(iovec, j);
        if (r < 0)
                log_error_errno(r, "Failed to log coredump: %m");

finish:
        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemple #12
0
static void test_login(void) {
        int r, k;
        uid_t u, u2;
        char *seat, *type, *class, *display;
        char *session;
        char *state;
        char *session2;
        char *t;
        char **seats, **sessions, **machines;
        uid_t *uids;
        unsigned n;
        struct pollfd pollfd;
        sd_login_monitor *m;

        assert_se(sd_pid_get_session(0, &session) == 0);
        printf("session = %s\n", session);

        assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
        printf("user = %lu\n", (unsigned long) u2);

        r = sd_uid_get_sessions(u2, false, &sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_sessions(u2, false, NULL));

        r = sd_uid_get_seats(u2, false, &seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("seats = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_seats(u2, false, NULL));

        r = sd_session_is_active(session);
        assert_se(r >= 0);
        printf("active = %s\n", yes_no(r));

        r = sd_session_get_state(session, &state);
        assert_se(r >= 0);
        printf("state = %s\n", state);
        free(state);

        assert_se(sd_session_get_uid(session, &u) >= 0);
        printf("uid = %lu\n", (unsigned long) u);
        assert_se(u == u2);

        assert_se(sd_session_get_type(session, &type) >= 0);
        printf("type = %s\n", type);
        free(type);

        assert_se(sd_session_get_class(session, &class) >= 0);
        printf("class = %s\n", class);
        free(class);

        assert_se(sd_session_get_display(session, &display) >= 0);
        printf("display = %s\n", display);
        free(display);

        assert_se(sd_session_get_seat(session, &seat) >= 0);
        printf("seat = %s\n", seat);

        r = sd_seat_can_multi_session(seat);
        assert_se(r >= 0);
        printf("can do multi session = %s\n", yes_no(r));

        r = sd_seat_can_tty(seat);
        assert_se(r >= 0);
        printf("can do tty = %s\n", yes_no(r));

        r = sd_seat_can_graphical(seat);
        assert_se(r >= 0);
        printf("can do graphical = %s\n", yes_no(r));

        assert_se(sd_uid_get_state(u, &state) >= 0);
        printf("state = %s\n", state);

        assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);

        k = sd_uid_is_on_seat(u, 1, seat);
        assert_se(k >= 0);
        assert_se(!!r == !!r);

        assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
        printf("session2 = %s\n", session2);
        printf("uid2 = %lu\n", (unsigned long) u2);

        r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
        assert_se(r >= 0);
        printf("n_sessions = %i\n", r);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);
        printf("uids =");
        for (k = 0; k < (int) n; k++)
                printf(" %lu", (unsigned long) uids[k]);
        printf("\n");
        free(uids);

        assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);

        free(session);
        free(state);
        free(session2);
        free(seat);

        r = sd_get_seats(&seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("n_seats = %i\n", r);
        printf("seats = %s\n", t);
        free(t);

        assert_se(sd_get_seats(NULL) == r);

        r = sd_seat_get_active(NULL, &t, NULL);
        assert_se(r >= 0);
        printf("active session on current seat = %s\n", t);
        free(t);

        r = sd_get_sessions(&sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("n_sessions = %i\n", r);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(sd_get_sessions(NULL) == r);

        r = sd_get_uids(&uids);
        assert_se(r >= 0);

        printf("uids =");
        for (k = 0; k < r; k++)
                printf(" %lu", (unsigned long) uids[k]);
        printf("\n");
        free(uids);

        printf("n_uids = %i\n", r);
        assert_se(sd_get_uids(NULL) == r);

        r = sd_get_machine_names(&machines);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(machines));
        assert_se(t = strv_join(machines, ", "));
        strv_free(machines);
        printf("n_machines = %i\n", r);
        printf("machines = %s\n", t);
        free(t);

        r = sd_login_monitor_new("session", &m);
        assert_se(r >= 0);

        for (n = 0; n < 5; n++) {
                usec_t timeout, nw;

                zero(pollfd);
                assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0);
                assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0);

                assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0);

                nw = now(CLOCK_MONOTONIC);

                r = poll(&pollfd, 1,
                         timeout == (uint64_t) -1 ? -1 :
                         timeout > nw ? (int) ((timeout - nw) / 1000) :
                         0);

                assert_se(r >= 0);

                sd_login_monitor_flush(m);
                printf("Wake!\n");
        }

        sd_login_monitor_unref(m);
}
static int evcat_new(Evcat **out) {
        _cleanup_(evcat_freep) Evcat *e = NULL;
        int r;

        assert(out);

        e = new0(Evcat, 1);
        if (!e)
                return log_oom();

        r = sd_pid_get_session(getpid(), &e->session);
        if (r < 0)
                return log_error_errno(r, "Cannot retrieve logind session: %m");

        r = sd_session_get_seat(e->session, &e->seat);
        if (r < 0)
                return log_error_errno(r, "Cannot retrieve seat of logind session: %m");

        e->managed = is_managed(e->session);

        r = sd_event_default(&e->event);
        if (r < 0)
                return r;

        r = sd_bus_open_system(&e->bus);
        if (r < 0)
                return r;

        r = sd_bus_attach_event(e->bus, e->event, SD_EVENT_PRIORITY_NORMAL);
        if (r < 0)
                return r;

        r = sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1);
        if (r < 0)
                return r;

        r = sd_event_add_signal(e->event, NULL, SIGTERM, NULL, NULL);
        if (r < 0)
                return r;

        r = sd_event_add_signal(e->event, NULL, SIGINT, NULL, NULL);
        if (r < 0)
                return r;

        r = sysview_context_new(&e->sysview,
                                SYSVIEW_CONTEXT_SCAN_LOGIND |
                                SYSVIEW_CONTEXT_SCAN_EVDEV,
                                e->event,
                                e->bus,
                                NULL);
        if (r < 0)
                return r;

        r = idev_context_new(&e->idev, e->event, e->bus);
        if (r < 0)
                return r;

        *out = e;
        e = NULL;
        return 0;
}
Exemple #14
0
static int modeset_new(Modeset **out) {
        _cleanup_(modeset_freep) Modeset *m = NULL;
        int r;

        assert(out);

        m = new0(Modeset, 1);
        if (!m)
                return log_oom();

        r = sd_pid_get_session(getpid(), &m->session);
        if (r < 0)
                return log_error_errno(r, "Cannot retrieve logind session: %m");

        r = sd_session_get_seat(m->session, &m->seat);
        if (r < 0)
                return log_error_errno(r, "Cannot retrieve seat of logind session: %m");

        m->my_tty = is_my_tty(m->session);
        m->managed = m->my_tty && geteuid() > 0;

        m->r = rand() % 0xff;
        m->g = rand() % 0xff;
        m->b = rand() % 0xff;
        m->r_up = m->g_up = m->b_up = true;

        r = sd_event_default(&m->event);
        if (r < 0)
                return r;

        r = sd_bus_open_system(&m->bus);
        if (r < 0)
                return r;

        r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
        if (r < 0)
                return r;

        r = sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1);
        if (r < 0)
                return r;

        r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
        if (r < 0)
                return r;

        r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
        if (r < 0)
                return r;

        r = sd_event_add_exit(m->event, &m->exit_src, modeset_exit_fn, m);
        if (r < 0)
                return r;

        /* schedule before sd-bus close */
        r = sd_event_source_set_priority(m->exit_src, -10);
        if (r < 0)
                return r;

        r = sysview_context_new(&m->sysview,
                                SYSVIEW_CONTEXT_SCAN_LOGIND |
                                SYSVIEW_CONTEXT_SCAN_DRM,
                                m->event,
                                m->bus,
                                NULL);
        if (r < 0)
                return r;

        r = grdev_context_new(&m->grdev, m->event, m->bus);
        if (r < 0)
                return r;

        *out = m;
        m = NULL;
        return 0;
}
Exemple #15
0
/**
 * udisks_daemon_util_on_same_seat:
 * @daemon: A #UDisksDaemon.
 * @object: The #GDBusObject that the call is on or %NULL.
 * @process: The process to check for.
 *
 * Checks whether the device represented by @object (if any) is plugged into
 * a seat where the caller represented by @process is logged in.
 *
 * This works if @object is a drive or a block object.
 *
 * Returns: %TRUE if @object and @process is on the same seat, %FALSE otherwise.
 */
gboolean
udisks_daemon_util_on_same_seat (UDisksDaemon          *daemon,
                                 UDisksObject          *object,
                                 pid_t                  process)
{
#if !defined(HAVE_LIBSYSTEMD_LOGIN)
  /* if we don't have systemd, assume it's always the same seat */
  return TRUE;
#else
  gboolean ret = FALSE;
  char *session = NULL;
  char *seat = NULL;
  const gchar *drive_seat;
  UDisksObject *drive_object = NULL;
  UDisksDrive *drive = NULL;

  /* if we don't have logind, assume it's always the same seat */
  if (!LOGIND_AVAILABLE())
    return TRUE;

  if (UDISKS_IS_LINUX_BLOCK_OBJECT (object))
    {
      UDisksLinuxBlockObject *linux_block_object;
      UDisksBlock *block;
      linux_block_object = UDISKS_LINUX_BLOCK_OBJECT (object);
      block = udisks_object_get_block (UDISKS_OBJECT (linux_block_object));
      if (block != NULL)
        {
          drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block));
          g_object_unref (block);
        }
    }
  else if (UDISKS_IS_LINUX_DRIVE_OBJECT (object))
    {
      drive_object = g_object_ref (object);
    }

  if (drive_object == NULL)
    goto out;

  drive = udisks_object_get_drive (UDISKS_OBJECT (drive_object));
  if (drive == NULL)
    goto out;

  /* It's not unexpected to not find a session, nor a seat associated with @process */
  if (sd_pid_get_session (process, &session) == 0)
    sd_session_get_seat (session, &seat);

  /* If we don't know the seat of the caller, we assume the device is always on another seat */
  if (seat == NULL)
    goto out;

  drive_seat = udisks_drive_get_seat (drive);
  if (g_strcmp0 (seat, drive_seat) == 0)
    {
      ret = TRUE;
      goto out;
    }

 out:
  free (seat);
  free (session);
  g_clear_object (&drive_object);
  g_clear_object (&drive);
  return ret;
#endif /* HAVE_LIBSYSTEMD_LOGIN */
}
/**
 * polkit_backend_session_monitor_get_session_for_subject:
 * @monitor: A #PolkitBackendSessionMonitor.
 * @subject: A #PolkitSubject.
 * @error: Return location for error.
 *
 * Gets the session corresponding to @subject or %NULL if no session exists.
 *
 * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref().
 */
PolkitSubject *
polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor,
                                                        PolkitSubject               *subject,
                                                        GError                     **error)
{
  PolkitSubject *session;

  session = NULL;

  if (POLKIT_IS_UNIX_PROCESS (subject))
    {
      gchar *session_id;
      pid_t pid;

      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
      if (sd_pid_get_session (pid, &session_id) < 0)
        goto out;

      session = polkit_unix_session_new (session_id);
      free (session_id);
    }
  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
    {
      guint32 pid;
      gchar *session_id;
      GVariant *result;

      result = g_dbus_connection_call_sync (monitor->system_bus,
                                            "org.freedesktop.DBus",
                                            "/org/freedesktop/DBus",
                                            "org.freedesktop.DBus",
                                            "GetConnectionUnixProcessID",
                                            g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))),
                                            G_VARIANT_TYPE ("(u)"),
                                            G_DBUS_CALL_FLAGS_NONE,
                                            -1, /* timeout_msec */
                                            NULL, /* GCancellable */
                                            error);
      if (result == NULL)
        goto out;
      g_variant_get (result, "(u)", &pid);
      g_variant_unref (result);

      if (sd_pid_get_session (pid, &session_id) < 0)
        goto out;

      session = polkit_unix_session_new (session_id);
      free (session_id);
    }
  else
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_NOT_SUPPORTED,
                   "Cannot get user for subject of type %s",
                   g_type_name (G_TYPE_FROM_INSTANCE (subject)));
    }

 out:

  return session;
}
static int
launcher_logind_connect(struct weston_launcher **out, struct weston_compositor *compositor,
			int tty, const char *seat_id, bool sync_drm)
{
	struct launcher_logind *wl;
	struct wl_event_loop *loop;
	char *t;
	int r;

	wl = zalloc(sizeof(*wl));
	if (wl == NULL) {
		r = -ENOMEM;
		goto err_out;
	}

	wl->base.iface = &launcher_logind_iface;
	wl->compositor = compositor;
	wl->sync_drm = sync_drm;

	wl->seat = strdup(seat_id);
	if (!wl->seat) {
		r = -ENOMEM;
		goto err_wl;
	}

	r = sd_pid_get_session(getpid(), &wl->sid);
	if (r < 0) {
		weston_log("logind: not running in a systemd session\n");
		goto err_seat;
	}

	t = NULL;
	r = sd_session_get_seat(wl->sid, &t);
	if (r < 0) {
		weston_log("logind: failed to get session seat\n");
		free(t);
		goto err_session;
	} else if (strcmp(seat_id, t)) {
		weston_log("logind: weston's seat '%s' differs from session-seat '%s'\n",
			   seat_id, t);
		r = -EINVAL;
		free(t);
		goto err_session;
	}
	free(t);

	r = weston_sd_session_get_vt(wl->sid, &wl->vtnr);
	if (r < 0) {
		weston_log("logind: session not running on a VT\n");
		goto err_session;
	} else if (tty > 0 && wl->vtnr != (unsigned int )tty) {
		weston_log("logind: requested VT --tty=%d differs from real session VT %u\n",
			   tty, wl->vtnr);
		r = -EINVAL;
		goto err_session;
	}

	loop = wl_display_get_event_loop(compositor->wl_display);
	r = weston_dbus_open(loop, DBUS_BUS_SYSTEM, &wl->dbus, &wl->dbus_ctx);
	if (r < 0) {
		weston_log("logind: cannot connect to system dbus\n");
		goto err_session;
	}

	r = launcher_logind_setup_dbus(wl);
	if (r < 0)
		goto err_dbus;

	r = launcher_logind_take_control(wl);
	if (r < 0)
		goto err_dbus_cleanup;

	r = launcher_logind_activate(wl);
	if (r < 0)
		goto err_dbus_cleanup;

	weston_log("logind: session control granted\n");
	* (struct launcher_logind **) out = wl;
	return 0;

err_dbus_cleanup:
	launcher_logind_destroy_dbus(wl);
err_dbus:
	weston_dbus_close(wl->dbus, wl->dbus_ctx);
err_session:
	free(wl->sid);
err_seat:
	free(wl->seat);
err_wl:
	free(wl);
err_out:
	weston_log("logind: cannot setup systemd-logind helper (%d), using legacy fallback\n", r);
	errno = -r;
	return -1;
}
Exemple #18
0
static void test_login(void) {
        _cleanup_close_pair_ int pair[2] = { -1, -1 };
        _cleanup_free_ char *pp = NULL, *qq = NULL;
        int r, k;
        uid_t u, u2;
        char *seat, *type, *class, *display, *remote_user, *remote_host, *display_session;
        char *session;
        char *state;
        char *session2;
        char *t;
        char **seats, **sessions, **machines;
        uid_t *uids;
        unsigned n;
        struct pollfd pollfd;
        sd_login_monitor *m = NULL;

        assert_se(sd_pid_get_session(0, &session) == 0);
        printf("session = %s\n", session);

        assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
        printf("user = "******"\n", u2);

        display_session = NULL;
        r = sd_uid_get_display(u2, &display_session);
        assert_se(r >= 0 || r == -ENXIO);
        printf("user's display session = %s\n", strna(display_session));
        free(display_session);

        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
        sd_peer_get_session(pair[0], &pp);
        sd_peer_get_session(pair[1], &qq);
        assert_se(streq_ptr(pp, qq));

        r = sd_uid_get_sessions(u2, false, &sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_sessions(u2, false, NULL));

        r = sd_uid_get_seats(u2, false, &seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("seats = %s\n", t);
        free(t);

        assert_se(r == sd_uid_get_seats(u2, false, NULL));

        r = sd_session_is_active(session);
        assert_se(r >= 0);
        printf("active = %s\n", yes_no(r));

        r = sd_session_is_remote(session);
        assert_se(r >= 0);
        printf("remote = %s\n", yes_no(r));

        r = sd_session_get_state(session, &state);
        assert_se(r >= 0);
        printf("state = %s\n", state);
        free(state);

        assert_se(sd_session_get_uid(session, &u) >= 0);
        printf("uid = "UID_FMT"\n", u);
        assert_se(u == u2);

        assert_se(sd_session_get_type(session, &type) >= 0);
        printf("type = %s\n", type);
        free(type);

        assert_se(sd_session_get_class(session, &class) >= 0);
        printf("class = %s\n", class);
        free(class);

        display = NULL;
        r = sd_session_get_display(session, &display);
        assert_se(r >= 0 || r == -ENXIO);
        printf("display = %s\n", strna(display));
        free(display);

        remote_user = NULL;
        r = sd_session_get_remote_user(session, &remote_user);
        assert_se(r >= 0 || r == -ENXIO);
        printf("remote_user = %s\n", strna(remote_user));
        free(remote_user);

        remote_host = NULL;
        r = sd_session_get_remote_host(session, &remote_host);
        assert_se(r >= 0 || r == -ENXIO);
        printf("remote_host = %s\n", strna(remote_host));
        free(remote_host);

        assert_se(sd_session_get_seat(session, &seat) >= 0);
        printf("seat = %s\n", seat);

        r = sd_seat_can_multi_session(seat);
        assert_se(r >= 0);
        printf("can do multi session = %s\n", yes_no(r));

        r = sd_seat_can_tty(seat);
        assert_se(r >= 0);
        printf("can do tty = %s\n", yes_no(r));

        r = sd_seat_can_graphical(seat);
        assert_se(r >= 0);
        printf("can do graphical = %s\n", yes_no(r));

        assert_se(sd_uid_get_state(u, &state) >= 0);
        printf("state = %s\n", state);

        assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);

        k = sd_uid_is_on_seat(u, 1, seat);
        assert_se(k >= 0);
        assert_se(!!r == !!r);

        assert_se(sd_seat_get_active(seat, &session2, &u2) >= 0);
        printf("session2 = %s\n", session2);
        printf("uid2 = "UID_FMT"\n", u2);

        r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
        assert_se(r >= 0);
        printf("n_sessions = %i\n", r);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("sessions = %s\n", t);
        free(t);
        printf("uids =");
        for (k = 0; k < (int) n; k++)
                printf(" "UID_FMT, uids[k]);
        printf("\n");
        free(uids);

        assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);

        free(session);
        free(state);
        free(session2);
        free(seat);

        r = sd_get_seats(&seats);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(seats));
        assert_se(t = strv_join(seats, ", "));
        strv_free(seats);
        printf("n_seats = %i\n", r);
        printf("seats = %s\n", t);
        free(t);

        assert_se(sd_get_seats(NULL) == r);

        r = sd_seat_get_active(NULL, &t, NULL);
        assert_se(r >= 0);
        printf("active session on current seat = %s\n", t);
        free(t);

        r = sd_get_sessions(&sessions);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(sessions));
        assert_se(t = strv_join(sessions, ", "));
        strv_free(sessions);
        printf("n_sessions = %i\n", r);
        printf("sessions = %s\n", t);
        free(t);

        assert_se(sd_get_sessions(NULL) == r);

        r = sd_get_uids(&uids);
        assert_se(r >= 0);

        printf("uids =");
        for (k = 0; k < r; k++)
                printf(" "UID_FMT, uids[k]);
        printf("\n");
        free(uids);

        printf("n_uids = %i\n", r);
        assert_se(sd_get_uids(NULL) == r);

        r = sd_get_machine_names(&machines);
        assert_se(r >= 0);
        assert_se(r == (int) strv_length(machines));
        assert_se(t = strv_join(machines, ", "));
        strv_free(machines);
        printf("n_machines = %i\n", r);
        printf("machines = %s\n", t);
        free(t);

        r = sd_login_monitor_new("session", &m);
        assert_se(r >= 0);

        for (n = 0; n < 5; n++) {
                usec_t timeout, nw;

                zero(pollfd);
                assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0);
                assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0);

                assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0);

                nw = now(CLOCK_MONOTONIC);

                r = poll(&pollfd, 1,
                         timeout == (uint64_t) -1 ? -1 :
                         timeout > nw ? (int) ((timeout - nw) / 1000) :
                         0);

                assert_se(r >= 0);

                sd_login_monitor_flush(m);
                printf("Wake!\n");
        }

        sd_login_monitor_unref(m);
}