X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogin%2Flogind-dbus.c;h=230dd2b4b5e9ac2f329a0de281cb30f1d439a214;hp=d235474a23555f9ceeb0cffa1910487f5ea80307;hb=50fb97935d689a520251b2d543599be14bdfd0ed;hpb=a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7 diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index d235474a2..230dd2b4b 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -308,21 +308,21 @@ static int bus_manager_append_preparing(DBusMessageIter *i, const char *property } static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) { - Session *session = NULL; - User *user = NULL; - const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service; + const char *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *service; uint32_t uid, leader, audit_id = 0; dbus_bool_t remote, kill_processes, exists; - char **controllers = NULL, **reset_controllers = NULL; + _cleanup_strv_free_ char **controllers = NULL, **reset_controllers = NULL; + _cleanup_free_ char *cgroup = NULL, *id = NULL, *p = NULL; SessionType t; SessionClass c; - Seat *s; DBusMessageIter iter; int r; - char *id = NULL, *p; uint32_t vtnr = 0; - int fifo_fd = -1; - DBusMessage *reply = NULL; + _cleanup_close_ int fifo_fd = -1; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; + Session *session = NULL; + User *user = NULL; + Seat *seat = NULL; bool b; assert(m); @@ -353,31 +353,38 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess return -EINVAL; dbus_message_iter_get_basic(&iter, &type); - t = session_type_from_string(type); + if (isempty(type)) + t = _SESSION_TYPE_INVALID; + else { + t = session_type_from_string(type); + if (t < 0) + return -EINVAL; + } - if (t < 0 || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return -EINVAL; dbus_message_iter_get_basic(&iter, &class); if (isempty(class)) - c = SESSION_USER; - else + c = _SESSION_CLASS_INVALID; + else { c = session_class_from_string(class); + if (c < 0) + return -EINVAL; + } - if (c < 0 || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return -EINVAL; - dbus_message_iter_get_basic(&iter, &seat); + dbus_message_iter_get_basic(&iter, &cseat); - if (isempty(seat)) - s = NULL; + if (isempty(cseat)) + seat = NULL; else { - s = hashmap_get(m->seats, seat); - if (!s) + seat = hashmap_get(m->seats, cseat); + if (!seat) return -ENOENT; } @@ -396,9 +403,9 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess if (tty_is_vc(tty)) { int v; - if (!s) - s = m->vtconsole; - else if (s != m->vtconsole) + if (!seat) + seat = m->vtconsole; + else if (seat != m->vtconsole) return -EINVAL; v = vtnr_from_tty(tty); @@ -412,18 +419,17 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess return -EINVAL; } else if (tty_is_console(tty)) { - if (!s) - s = m->vtconsole; - else if (s != m->vtconsole) + if (!seat) + seat = m->vtconsole; + else if (seat != m->vtconsole) return -EINVAL; if (vtnr != 0) return -EINVAL; - } - if (s) { - if (seat_can_multi_session(s)) { + if (seat) { + if (seat_can_multi_session(seat)) { if (vtnr > 63) return -EINVAL; } else { @@ -442,6 +448,22 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) return -EINVAL; + if (t == _SESSION_TYPE_INVALID) { + if (!isempty(display)) + t = SESSION_X11; + else if (!isempty(tty)) + t = SESSION_TTY; + else + t = SESSION_UNSPECIFIED; + } + + if (c == _SESSION_CLASS_INVALID) { + if (!isempty(display) || !isempty(tty)) + c = SESSION_USER; + else + c = SESSION_BACKGROUND; + } + dbus_message_iter_get_basic(&iter, &remote); if (!dbus_message_iter_next(&iter) || @@ -486,78 +508,84 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess dbus_message_iter_get_basic(&iter, &kill_processes); - r = manager_add_user_by_uid(m, uid, &user); + r = cg_pid_get_cgroup(leader, NULL, &cgroup); if (r < 0) goto fail; - audit_session_from_pid(leader, &audit_id); + r = manager_get_session_by_cgroup(m, cgroup, &session); + if (r < 0) + goto fail; - if (audit_id > 0) { - asprintf(&id, "%lu", (unsigned long) audit_id); + if (session) { + fifo_fd = session_create_fifo(session); + if (fifo_fd < 0) { + r = fifo_fd; + goto fail; + } + + /* Session already exists, client is probably + * something like "su" which changes uid but + * is still the same audit session */ - if (!id) { + reply = dbus_message_new_method_return(message); + if (!reply) { r = -ENOMEM; goto fail; } - session = hashmap_get(m->sessions, id); + p = session_bus_path(session); + if (!p) { + r = -ENOMEM; + goto fail; + } - if (session) { - free(id); + cseat = session->seat ? session->seat->id : ""; + vtnr = session->vtnr; + exists = true; - fifo_fd = session_create_fifo(session); - if (fifo_fd < 0) { - r = fifo_fd; - goto fail; - } - - /* Session already exists, client is probably - * something like "su" which changes uid but - * is still the same audit session */ + b = dbus_message_append_args( + reply, + DBUS_TYPE_STRING, &session->id, + DBUS_TYPE_OBJECT_PATH, &p, + DBUS_TYPE_STRING, &session->user->runtime_path, + DBUS_TYPE_UNIX_FD, &fifo_fd, + DBUS_TYPE_STRING, &cseat, + DBUS_TYPE_UINT32, &vtnr, + DBUS_TYPE_BOOLEAN, &exists, + DBUS_TYPE_INVALID); + if (!b) { + r = -ENOMEM; + goto fail; + } - reply = dbus_message_new_method_return(message); - if (!reply) { - r = -ENOMEM; - goto fail; - } + *_reply = reply; + reply = NULL; - p = session_bus_path(session); - if (!p) { - r = -ENOMEM; - goto fail; - } - - seat = session->seat ? session->seat->id : ""; - vtnr = session->vtnr; - exists = true; - - b = dbus_message_append_args( - reply, - DBUS_TYPE_STRING, &session->id, - DBUS_TYPE_OBJECT_PATH, &p, - DBUS_TYPE_STRING, &session->user->runtime_path, - DBUS_TYPE_UNIX_FD, &fifo_fd, - DBUS_TYPE_STRING, &seat, - DBUS_TYPE_UINT32, &vtnr, - DBUS_TYPE_BOOLEAN, &exists, - DBUS_TYPE_INVALID); - free(p); + return 0; + } - if (!b) { - r = -ENOMEM; - goto fail; - } + audit_session_from_pid(leader, &audit_id); + if (audit_id > 0) { + /* Keep our session IDs and the audit session IDs in sync */ - close_nointr_nofail(fifo_fd); - *_reply = reply; + if (asprintf(&id, "%lu", (unsigned long) audit_id) < 0) { + r = -ENOMEM; + goto fail; + } - strv_free(controllers); - strv_free(reset_controllers); + /* Wut? There's already a session by this name and we + * didn't find it above? Weird, then let's not trust + * the audit data and let's better register a new + * ID */ + if (hashmap_get(m->sessions, id)) { + audit_id = 0; - return 0; + free(id); + id = NULL; } + } - } else { + if (!id) { do { free(id); id = NULL; @@ -570,8 +598,11 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess } while (hashmap_get(m->sessions, id)); } + r = manager_add_user_by_uid(m, uid, &user); + if (r < 0) + goto fail; + r = manager_add_session(m, user, id, &session); - free(id); if (r < 0) goto fail; @@ -633,8 +664,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess goto fail; } - if (s) { - r = seat_attach_session(s, session); + if (seat) { + r = seat_attach_session(seat, session); if (r < 0) goto fail; } @@ -655,7 +686,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess goto fail; } - seat = s ? s->id : ""; + cseat = seat ? seat->id : ""; exists = false; b = dbus_message_append_args( reply, @@ -663,38 +694,28 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_STRING, &session->user->runtime_path, DBUS_TYPE_UNIX_FD, &fifo_fd, - DBUS_TYPE_STRING, &seat, + DBUS_TYPE_STRING, &cseat, DBUS_TYPE_UINT32, &vtnr, DBUS_TYPE_BOOLEAN, &exists, DBUS_TYPE_INVALID); - free(p); if (!b) { r = -ENOMEM; goto fail; } - close_nointr_nofail(fifo_fd); *_reply = reply; + reply = NULL; return 0; fail: - strv_free(controllers); - strv_free(reset_controllers); - if (session) session_add_to_gc_queue(session); if (user) user_add_to_gc_queue(user); - if (fifo_fd >= 0) - close_nointr_nofail(fifo_fd); - - if (reply) - dbus_message_unref(reply); - return r; } @@ -713,7 +734,7 @@ static int bus_manager_inhibit( InhibitMode mm; unsigned long ul; int r, fifo_fd = -1; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; assert(m); assert(connection); @@ -834,6 +855,7 @@ static int bus_manager_inhibit( close_nointr_nofail(fifo_fd); *_reply = reply; + reply = NULL; inhibitor_start(i); @@ -846,9 +868,6 @@ fail: if (fifo_fd >= 0) close_nointr_nofail(fifo_fd); - if (reply) - dbus_message_unref(reply); - return r; } @@ -890,7 +909,7 @@ static int trigger_device(Manager *m, struct udev_device *d) { goto finish; } - write_one_line_file(t, "change"); + write_string_file(t, "change"); free(t); } @@ -905,7 +924,7 @@ finish: static int attach_device(Manager *m, const char *seat, const char *sysfs) { struct udev_device *d; - char *rule = NULL, *file = NULL; + char _cleanup_free_ *rule = NULL, *file = NULL; const char *id_for_seat; int r; @@ -940,16 +959,13 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) { mkdir_p_label("/etc/udev/rules.d", 0755); label_init("/etc"); - r = write_one_line_file_atomic_label(file, rule); + r = write_string_file_atomic_label(file, rule); if (r < 0) goto finish; r = trigger_device(m, d); finish: - free(rule); - free(file); - if (d) udev_device_unref(d); @@ -957,7 +973,7 @@ finish: } static int flush_devices(Manager *m) { - DIR *d; + DIR _cleanup_closedir_ *d; assert(m); @@ -982,8 +998,6 @@ static int flush_devices(Manager *m) { if (unlinkat(dirfd(d), de->d_name, 0) < 0) log_warning("Failed to unlink %s: %m", de->d_name); } - - closedir(d); } return trigger_device(m, NULL); @@ -1002,7 +1016,6 @@ static int have_multiple_sessions( * count, and non-login sessions do not count either. */ HASHMAP_FOREACH(session, m->sessions, i) if (session->class == SESSION_USER && - (session->type == SESSION_TTY || session->type == SESSION_X11) && session->user->uid != uid) return true; @@ -1051,7 +1064,7 @@ static int execute_shutdown_or_sleep( DBusError *error) { _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; - const char *mode = "replace", *p; + const char *mode = "replace-irreversibly", *p; int r; char *c; @@ -1127,7 +1140,7 @@ static int bus_manager_can_shutdown_or_sleep( bool multiple_sessions, challenge, blocked, b; const char *result; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; unsigned long ul; @@ -1226,12 +1239,11 @@ finish: reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID); - if (!b) { - dbus_message_unref(reply); + if (!b) return -ENOMEM; - } *_reply = reply; + reply = NULL; return 0; } @@ -1431,7 +1443,7 @@ static DBusHandlerResult manager_message_handler( Manager *m = userdata; DBusError error; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; assert(connection); @@ -2339,16 +2351,11 @@ static DBusHandlerResult manager_message_handler( if (reply) { if (!bus_maybe_send_reply(connection, message, reply)) goto oom; - - dbus_message_unref(reply); } return DBUS_HANDLER_RESULT_HANDLED; oom: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -2414,25 +2421,20 @@ DBusHandlerResult bus_message_filter( } int manager_send_changed(Manager *manager, const char *properties) { - DBusMessage *m; - int r = -ENOMEM; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; assert(manager); - m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties); + m = bus_properties_changed_new("/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + properties); if (!m) - goto finish; + return -ENOMEM; if (!dbus_connection_send(manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - if (m) - dbus_message_unref(m); + return -ENOMEM; - return r; + return 0; } int manager_dispatch_delayed(Manager *manager) {