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=44fe5e507937acb72c11ed6309267ab66b6faf72;hp=64e67409e18429284838a7723a00a2c27dac5c5c;hb=8331cb6e143dc261fd22af9a2a679196822326a9;hpb=d3ec6a978b077ed6ba154fe802703445ba51b64e diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 64e67409e..44fe5e507 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -43,7 +41,7 @@ #include "path-util.h" #include "process-util.h" #include "selinux-util.h" -#include "sleep-config.h" +//#include "sleep-config.h" //#include "special.h" #include "strv.h" #include "terminal-util.h" @@ -53,7 +51,7 @@ //#include "utmp-wtmp.h" int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Session *session; int r; @@ -88,7 +86,7 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, assert(ret); if (uid == UID_INVALID) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); @@ -124,7 +122,6 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char return r; seat = session->seat; - if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat."); } else { @@ -268,6 +265,42 @@ static int property_get_docked( return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m)); } +static int property_get_current_sessions( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions)); +} + +static int property_get_current_inhibitors( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors)); +} + static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *p = NULL; Manager *m = userdata; @@ -419,7 +452,7 @@ static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error } static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Session *session; Iterator i; @@ -461,7 +494,7 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_ } static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; User *user; Iterator i; @@ -501,7 +534,7 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err } static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Seat *seat; Iterator i; @@ -538,7 +571,7 @@ static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_err } static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; Manager *m = userdata; Inhibitor *inhibitor; Iterator i; @@ -696,7 +729,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus } if (leader == 0) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); if (r < 0) @@ -728,6 +761,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus m->seat0->positions[vtnr]->class != SESSION_GREETER) return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session"); + if (hashmap_size(m->sessions) >= m->sessions_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max); + audit_session_from_pid(leader, &audit_id); if (audit_id > 0) { /* Keep our session IDs and the audit session IDs in sync */ @@ -834,13 +870,17 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus session->create_message = sd_bus_message_ref(message); - /* Here upstream systemd starts cgroups and the user systemd, - and arranges to reply asynchronously. We reply - directly. */ +#if 0 /// UNNEEDED by elogind + /* Now, let's wait until the slice unit and stuff got + * created. We send the reply back from + * session_send_create_reply(). */ +#else + /* We reply directly. */ r = session_send_create_reply(session, NULL); if (r < 0) goto fail; +#endif // 0 return 1; @@ -1086,11 +1126,11 @@ static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *cc = NULL; Manager *m = userdata; - int b, r; + int r, b, interactive; struct passwd *pw; const char *path; uint32_t uid; - int interactive; + bool self = false; assert(message); assert(m); @@ -1100,7 +1140,7 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu return r; if (uid == UID_INVALID) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; /* Note that we get the owner UID of the session, not the actual client UID here! */ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); @@ -1111,18 +1151,20 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu if (r < 0) return r; + self = true; + } else if (!uid_is_valid(uid)) return -EINVAL; errno = 0; pw = getpwuid(uid); if (!pw) - return errno ? -errno : -ENOENT; + return errno > 0 ? -errno : -ENOENT; r = bus_verify_polkit_async( message, CAP_SYS_ADMIN, - "org.freedesktop.login1.set-user-linger", + self ? "org.freedesktop.login1.set-self-linger" : "org.freedesktop.login1.set-user-linger", NULL, interactive, UID_INVALID, @@ -1235,7 +1277,6 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) { return -ENOMEM; mkdir_p_label("/etc/udev/rules.d", 0755); - mac_selinux_init("/etc"); r = write_string_file_atomic_label(file, rule); if (r < 0) return r; @@ -1504,7 +1545,7 @@ static int execute_shutdown_or_sleep( sd_bus_error *error) { #if 0 /// elogind does not need these, we do it ourselves - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; char *c = NULL; const char *p; #endif // 0 @@ -1521,39 +1562,39 @@ static int execute_shutdown_or_sleep( log_info("Running in dry run, suppressing action."); reset_scheduled_shutdown(m); } else { - r = sd_bus_call_method( - m->bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "StartUnit", - error, - &reply, - "ss", NULL, "replace-irreversibly"); + r = sd_bus_call_method( + m->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + error, + &reply, + "ss", unit_name, "replace-irreversibly"); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &p); + if (r < 0) + return r; + + c = strdup(p); + if (!c) + return -ENOMEM; + + m->action_unit = unit_name; + free(m->action_job); + m->action_job = c; + m->action_what = w; + } #else r = shutdown_or_sleep(m, action); /* no more pending actions, whether this failed or not */ m->pending_action = HANDLE_IGNORE; m->action_what = 0; -#endif // 0 if (r < 0) return r; - -#if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs - r = sd_bus_message_read(reply, "o", &p); - if (r < 0) - return r; - - c = strdup(p); - if (!c) - return -ENOMEM; - } - - m->action_unit = unit_name; - free(m->action_job); - m->action_job = c; - m->action_what = w; #endif // 0 /* Make sure the lid switch is ignored for a while */ @@ -1564,7 +1605,7 @@ static int execute_shutdown_or_sleep( int manager_dispatch_delayed(Manager *manager, bool timeout) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Inhibitor *offending = NULL; int r; @@ -1714,7 +1755,7 @@ static int verify_shutdown_creds( const char *action_ignore_inhibit, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, blocked; uid_t uid; int r; @@ -1793,7 +1834,7 @@ static int method_do_shutdown_or_sleep( return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress"); if (sleep_verb) { - r = can_sleep(sleep_verb); + r = can_sleep(m, sleep_verb); if (r < 0) return r; @@ -1923,8 +1964,8 @@ static int update_schedule_file(Manager *m) { return 0; fail: - (void) unlink(temp_path); - (void) unlink("/run/systemd/shutdown/scheduled"); + (void) unlink(temp_path); + (void) unlink("/run/systemd/shutdown/scheduled"); return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m"); } @@ -1934,7 +1975,7 @@ static int manager_scheduled_shutdown_handler( uint64_t usec, void *userdata) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Manager *m = userdata; HandleAction action; int r; @@ -1960,7 +2001,7 @@ static int manager_scheduled_shutdown_handler( static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *action_multiple_sessions = NULL; const char *action_ignore_inhibit = NULL; const char *action = NULL; @@ -2080,7 +2121,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd #if 0 /// elogind does not support utmp-wtmp if (cancelled) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *tty = NULL; uid_t uid = 0; int r; @@ -2137,7 +2178,7 @@ static int method_can_shutdown_or_sleep( const char *sleep_verb, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; bool multiple_sessions, challenge, blocked; const char *result = NULL; uid_t uid; @@ -2152,7 +2193,7 @@ static int method_can_shutdown_or_sleep( assert(action_ignore_inhibit); if (sleep_verb) { - r = can_sleep(sleep_verb); + r = can_sleep(m, sleep_verb); if (r < 0) return r; if (r == 0) @@ -2433,7 +2474,7 @@ static int method_set_wall_message( } static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; const char *who, *why, *what, *mode; _cleanup_free_ char *id = NULL; _cleanup_close_ int fifo_fd = -1; @@ -2503,6 +2544,9 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error if (r < 0) return r; + if (hashmap_size(m->inhibitors) >= m->inhibitors_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max); + do { id = mfree(id); @@ -2573,6 +2617,13 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), + SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0), + SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0), + SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2641,7 +2692,7 @@ static int session_jobs_reply(Session *s, const char *unit, const char *result) if (streq(result, "done")) r = session_send_create_reply(s, NULL); else { - _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result); r = session_send_create_reply(s, &e); @@ -2814,6 +2865,23 @@ int manager_send_changed(Manager *manager, const char *property, ...) { } #if 0 /// UNNEEDED by elogind +static int strdup_job(sd_bus_message *reply, char **job) { + const char *j; + char *copy; + int r; + + r = sd_bus_message_read(reply, "o", &j); + if (r < 0) + return r; + + copy = strdup(j); + if (!copy) + return -ENOMEM; + + *job = copy; + return 1; +} + int manager_start_slice( Manager *manager, const char *slice, @@ -2824,7 +2892,7 @@ int manager_start_slice( sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); @@ -2882,21 +2950,8 @@ int manager_start_slice( if (r < 0) return r; - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } @@ -2912,7 +2967,7 @@ int manager_start_scope( sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; int r; assert(manager); @@ -2992,26 +3047,13 @@ int manager_start_scope( if (r < 0) return r; - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -3029,26 +3071,13 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, if (r < 0) return r; - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -3077,21 +3106,8 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c return r; } - if (job) { - const char *j; - char *copy; - - r = sd_bus_message_read(reply, "o", &j); - if (r < 0) - return r; - - copy = strdup(j); - if (!copy) - return -ENOMEM; - - *job = copy; - } - + if (job) + return strdup_job(reply, job); return 1; } @@ -3145,8 +3161,8 @@ int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo } int manager_unit_is_active(Manager *manager, const char *unit) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *state; int r; @@ -3191,8 +3207,8 @@ int manager_unit_is_active(Manager *manager, const char *unit) { } int manager_job_is_active(Manager *manager, const char *path) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int r; assert(manager); @@ -3223,4 +3239,4 @@ int manager_job_is_active(Manager *manager, const char *path) { return true; } -#endif // +#endif // 0