Re: [systemd-devel] [PATCH v2 0/7] logind: close races on user and session states
On Sat, Feb 08, 2014 at 12:39:25AM +0100, Zbigniew Jędrzejewski-Szmek wrote: On Thu, Feb 06, 2014 at 09:37:13PM +0100, Djalal Harouni wrote: Summary: Currently logind will not clear sessions on logout. The bug is confirmed for getty and ssh logins. This series is preparation for next patches to address that bug, it does not fix it. However, this series also fixe real races on user and session states. This ensures that user_save() and session_save() functions will write the correct user and session state to the state files. The logind bug was already discussed here: http://lists.freedesktop.org/archives/systemd-devel/2014-January/015968.html So, I did some testing with current git (ba978d7). And this bug appears to be only partially gone. After my second user logs out, loginctl stops showing the session. But the manager *remains*. I confirm this, I've identified the problem, please see below. Hm, the manager remains, but /run/user/uid/systemd/ gets nuked. So when the user logins in a second time, communication with user manager is broken. I also confirm, I didn't have time to debug this one. Attaching strace to systemd --user during the orignial session close yields... nothing. Both systemd and (sd-pam) remain undisturbed... Yes sd-pam and the user instance will stay alive for *another* user after logout. In manager_gc() the user_stop() is never called. if (!user_check_gc(user, drop_not_started) user_get_state(user) != USER_CLOSING) user_stop(user); Note: with the recent commits, user_stop() will set user-stopping to say that user_stop() was called. But currently with this logic if the user_check_gc(...) returns false, this means that 'u-sessions' is NULL, so user_get_state(user) will for sure return USER_CLOSING if linger is not set and if it is not open state. I think that we should remove that USER_CLOSING check, will just test it. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] systemd crashes if locale.conf contains invalid utf8 string
On Thu, Feb 06, 2014 at 07:09:59PM +0100, Goffredo Baroncelli wrote: In the parse_env_file_push() and load_env_file_push() functions, there are two assert() call to check if the key or value parameters are utf8 valid. If the strings aren't utf8 valid, assert does abort. These function are used early by systemd to parse some files. For example '/etc/locale.conf'. In my case this file contained a not utf8 sequence, which is bad, but systemd crashed during the boot, which is even worse ! Applied. Your patch motivated me to push a patch I had written previously to avoid invalid utf-8 in log messages. After those two changes systemd should finally behave correctly for invalid utf-8 in config files. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] cryptsetup-generator: auto add deps for device as password
If the password is a device file, we can add Requires/After dependencies on the device rather than requiring the user to do so. --- This is based on a bug filed to Arch: https://bugs.archlinux.org/task/38842 Assuming I'm correct about the race condition, this should be an easy way of closing it without user involvement. src/cryptsetup/cryptsetup-generator.c | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 9c98f0b..4542757 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -130,11 +130,26 @@ static int create_disk( streq(password, /dev/random) || streq(password, /dev/hw_random)) fputs(After=systemd-random-seed.service\n, f); -else if (!streq(password, -) - !streq(password, none)) -fprintf(f, -RequiresMountsFor=%s\n, -password); +else { +_cleanup_free_ char *uu = fstab_node_to_udev_node(password); +if (uu == NULL) +return log_oom(); + +if (is_device_path(uu)) { +_cleanup_free_ char *dd = unit_name_from_path(uu, .device); +if (dd == NULL) +return log_oom(); + +fprintf(f, +After=%s\n +Requires=%s\n, +dd, dd); +} else if (!streq(password, -) + !streq(password, none)) +fprintf(f, +RequiresMountsFor=%s\n, +password); +} } if (is_device_path(u)) -- 1.8.5.4 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] logind: just call user_stop() if user_check_gc() returns false
Currently if the user logs out, the GC may never call user_stop(), this will not terminate the systemd user and (sd-pam) of that user. To fix this, remove the USER_CLOSING state check that is blocking the GC from calling user_stop(). We do not need it since with the current logic we have: 1) if user_check_gc() returns false this means that all the sessions of the user were removed. 2) if all the sessions were removed and if linger is not set and if it is not open state then user_get_state() will return always USER_CLOSING. So that check will never be satisfied for normal cases, and for linger user_check_gc() will return true which prevents the GC from collecting the user. --- src/login/logind.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/login/logind.c b/src/login/logind.c index a6f84e8..84c5b7d 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -889,11 +889,8 @@ void manager_gc(Manager *m, bool drop_not_started) { LIST_REMOVE(gc_queue, m-user_gc_queue, user); user-in_gc_queue = false; -if (!user_check_gc(user, drop_not_started) -user_get_state(user) != USER_CLOSING) -user_stop(user); - if (!user_check_gc(user, drop_not_started)) { +user_stop(user); user_finalize(user); user_free(user); } -- 1.8.3.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup-generator: auto add deps for device as password
On Sat, Feb 08, 2014 at 01:12:14PM -0500, Dave Reisner wrote: If the password is a device file, we can add Requires/After dependencies on the device rather than requiring the user to do so. --- This is based on a bug filed to Arch: https://bugs.archlinux.org/task/38842 Assuming I'm correct about the race condition, this should be an easy way of closing it without user involvement. src/cryptsetup/cryptsetup-generator.c | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 9c98f0b..4542757 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -130,11 +130,26 @@ static int create_disk( streq(password, /dev/random) || streq(password, /dev/hw_random)) fputs(After=systemd-random-seed.service\n, f); -else if (!streq(password, -) - !streq(password, none)) -fprintf(f, -RequiresMountsFor=%s\n, -password); +else { +_cleanup_free_ char *uu = fstab_node_to_udev_node(password); +if (uu == NULL) +return log_oom(); + +if (is_device_path(uu)) { +_cleanup_free_ char *dd = unit_name_from_path(uu, .device); +if (dd == NULL) +return log_oom(); + +fprintf(f, +After=%s\n +Requires=%s\n, +dd, dd); +} else if (!streq(password, -) + !streq(password, none)) +fprintf(f, +RequiresMountsFor=%s\n, +password); +} Patch looks fine, but I don't really understand why you invert the order of conditions. Something like this feels more natural: else if (!streq(password, -) !streq(password, none)) { _cleanup_free_ char *uu = fstab_node_to_udev_node(password); if (uu == NULL) return log_oom(); if (is_device_path(uu)) { _cleanup_free_ char *dd = unit_name_from_path(uu, .device); if (dd == NULL) return log_oom(); fprintf(f, After=%1$s\nRequires=%1$s\n, dd); } else fprintf(f, RequiresMountsFor=%s\n, password); } Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] cryptsetup-generator: auto add deps for device as password
On Sat, Feb 08, 2014 at 07:31:28PM +0100, Zbigniew Jędrzejewski-Szmek wrote: On Sat, Feb 08, 2014 at 01:12:14PM -0500, Dave Reisner wrote: If the password is a device file, we can add Requires/After dependencies on the device rather than requiring the user to do so. --- This is based on a bug filed to Arch: https://bugs.archlinux.org/task/38842 Assuming I'm correct about the race condition, this should be an easy way of closing it without user involvement. src/cryptsetup/cryptsetup-generator.c | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 9c98f0b..4542757 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -130,11 +130,26 @@ static int create_disk( streq(password, /dev/random) || streq(password, /dev/hw_random)) fputs(After=systemd-random-seed.service\n, f); -else if (!streq(password, -) - !streq(password, none)) -fprintf(f, -RequiresMountsFor=%s\n, -password); +else { +_cleanup_free_ char *uu = fstab_node_to_udev_node(password); +if (uu == NULL) +return log_oom(); + +if (is_device_path(uu)) { +_cleanup_free_ char *dd = unit_name_from_path(uu, .device); +if (dd == NULL) +return log_oom(); + +fprintf(f, +After=%s\n +Requires=%s\n, +dd, dd); +} else if (!streq(password, -) + !streq(password, none)) +fprintf(f, +RequiresMountsFor=%s\n, +password); +} Patch looks fine, but I don't really understand why you invert the order of conditions. Something like this feels more natural: Yeah, not sure what I was thinking here. Thanks for the suggestion -- will push with this change. else if (!streq(password, -) !streq(password, none)) { _cleanup_free_ char *uu = fstab_node_to_udev_node(password); if (uu == NULL) return log_oom(); if (is_device_path(uu)) { _cleanup_free_ char *dd = unit_name_from_path(uu, .device); if (dd == NULL) return log_oom(); fprintf(f, After=%1$s\nRequires=%1$s\n, dd); } else fprintf(f, RequiresMountsFor=%s\n, password); } Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] logind: use session_get_state() to get sessions state of the user
In function user_get_state() remove the session_is_active() check, just count on the session_get_state() function to get the correct session state. session_is_active() may return true before starting the session scope and user service, this means it will return true even before the creation of the session fifo_fd which will produce incorrect states. So be consistent and just use session_get_state(). --- src/login/logind-user.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/login/logind-user.c b/src/login/logind-user.c index fdbf6e3..2a11bab 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -648,9 +648,11 @@ UserState user_get_state(User *u) { bool all_closing = true; LIST_FOREACH(sessions_by_user, i, u-sessions) { -if (session_is_active(i)) +SessionState state = session_get_state(i); + +if (state == SESSION_ACTIVE) return USER_ACTIVE; -if (session_get_state(i) != SESSION_CLOSING) +else if (state != SESSION_CLOSING) all_closing = false; } -- 1.8.3.1 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] Debian Bug#618862: systemd: ignores keyscript in crypttab - a possible solution
On Wed, Feb 05, 2014 at 12:16:00AM +0100, Lennart Poettering wrote: On Thu, 30.01.14 10:40, David Härdeman (da...@hardeman.nu) wrote: This issue is fixable with minor upstream changes, e.g. by extending the PasswordAgent protocol to add Subsystem=cryptsetup and Target=diskname entries to the ask. file. I'd be fine with adding a field Id= or so, which then is filled by an identifier of some kind be the cryptsetup tool that is useful to identify the device to query things on. for example: Id=cryptsetup:/dev/sda5 or so could be one way how this could be filled in. We wouldn't enfoce any kind of syntax on this, just suggest some common sense so that people choose identifiers that are unlikely to clash with other subsystems, and somewhat reasonable to read... In the patches I sent I split it into Purpose and Target and my thinking was more or less the same as yours...i.e. that there's no particular syntax and that the meaning of the string is subsystem specific. I'd be happy to change the patch to use Id=subsystem:target if you'd prefer. b) the password agent implementation in systemd doesn't seem to handle binary strings (i.e. strings with '\0'), as can be seen by calls to e.g. strlen()... Whether making it binary safe would be a major change or not is something I haven't researched yet but it seems like a change that should be generally useful upstream... I'd be OK with this, as discussed at FOSDEM, and I see you already posted a ptach for this. Yes. I take it you're pretty busy with the kdbus stuff right now but a review of those patches would be nice when you have the time. -- David Härdeman ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] logind: use session_get_state() to get sessions state of the user
On Sat, Feb 08, 2014 at 08:51:57PM +0100, Djalal Harouni wrote: In function user_get_state() remove the session_is_active() check, just count on the session_get_state() function to get the correct session state. session_is_active() may return true before starting the session scope and user service, this means it will return true even before the creation of the session fifo_fd which will produce incorrect states. So be consistent and just use session_get_state(). Sooo... with your patch applied, I see: sshd[18756]: pam_unix(sshd:session): session closed for user user2 systemd-logind[18687]: Sent message type=method_call sender=n/a destination=org.freedesktop.systemd1 object=/org/freedesktop/systemd1/unit/session_2d10_2escope interface=org.freedesktop.systemd1.Scope member=Abandon cookie=27 reply_cookie=0 error=n/a And nothing afterwards. User manager for user2 is undisturbed. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] logind: use session_get_state() to get sessions state of the user
On Sat, Feb 08, 2014 at 10:01:18PM +0100, Zbigniew Jędrzejewski-Szmek wrote: On Sat, Feb 08, 2014 at 08:51:57PM +0100, Djalal Harouni wrote: In function user_get_state() remove the session_is_active() check, just count on the session_get_state() function to get the correct session state. session_is_active() may return true before starting the session scope and user service, this means it will return true even before the creation of the session fifo_fd which will produce incorrect states. So be consistent and just use session_get_state(). Sooo... with your patch applied, I see: sshd[18756]: pam_unix(sshd:session): session closed for user user2 systemd-logind[18687]: Sent message type=method_call sender=n/a destination=org.freedesktop.systemd1 object=/org/freedesktop/systemd1/unit/session_2d10_2escope interface=org.freedesktop.systemd1.Scope member=Abandon cookie=27 reply_cookie=0 error=n/a And nothing afterwards. User manager for user2 is undisturbed. Ah this patch fixes the user state. The one you should apply is from the other thread: http://lists.freedesktop.org/archives/systemd-devel/2014-February/016754.html It should work, please give it a try! Zbyszek -- Djalal Harouni http://opendz.org ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH v2 0/7] logind: close races on user and session states
On Sat, Feb 08, 2014 at 12:39:25AM +0100, Zbigniew Jędrzejewski-Szmek wrote: systemd-logind[2998]: Failed to process message [type=signal sender=:1.1 path=/org/freedesktop/systemd1/job/3284 interface=org.freedesktop.DBus.Properties member=PropertiesChanged signature=sa{sv}as]: Invalid argument So, this happens because match_properties_changed() expects path=/org/freedesktop/systemd1/unit/... but gets .../job/... I'll push a patch to quietly ignore those. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] systemd crashes if locale.conf contains invalid utf8 string
On 02/08/2014 07:15 PM, Zbigniew Jędrzejewski-Szmek wrote: On Thu, Feb 06, 2014 at 07:09:59PM +0100, Goffredo Baroncelli wrote: [...] Applied. Great ! [...] Zbyszek -- gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5 ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Re: [systemd-devel] [PATCH] logind: use session_get_state() to get sessions state of the user
On Sat, Feb 08, 2014 at 10:20:53PM +0100, Djalal Harouni wrote: On Sat, Feb 08, 2014 at 10:01:18PM +0100, Zbigniew Jędrzejewski-Szmek wrote: On Sat, Feb 08, 2014 at 08:51:57PM +0100, Djalal Harouni wrote: In function user_get_state() remove the session_is_active() check, just count on the session_get_state() function to get the correct session state. session_is_active() may return true before starting the session scope and user service, this means it will return true even before the creation of the session fifo_fd which will produce incorrect states. So be consistent and just use session_get_state(). Sooo... with your patch applied, I see: sshd[18756]: pam_unix(sshd:session): session closed for user user2 systemd-logind[18687]: Sent message type=method_call sender=n/a destination=org.freedesktop.systemd1 object=/org/freedesktop/systemd1/unit/session_2d10_2escope interface=org.freedesktop.systemd1.Scope member=Abandon cookie=27 reply_cookie=0 error=n/a And nothing afterwards. User manager for user2 is undisturbed. Ah this patch fixes the user state. The one you should apply is from the other thread: http://lists.freedesktop.org/archives/systemd-devel/2014-February/016754.html It should work, please give it a try! You're right, I applied the wrong patch. It really seems that with your * logind: use session_get_state() to get sessions state of the user * logind: just call user_stop() if user_check_gc() returns false things actually work. One thing that still does not work is terminate-user, even though kill-session works. method_terminate_user - user_stop -* session_stop - session_stop_scope - manager_abandom_scope - user_stop_service - user_stop_slice manager_stop_scope calls manager_shall_kill which returns false, so it only calls manager_abandon_scope. There seems to be a conflation between explicit termination of users and sessions, and automatic termination when they log out. According to the man page: KillUserProcesses= Takes a boolean argument. Configures whether the processes of a user should be killed when she or he completely logs out (i.e. after her/his last session ended). Defaults to no. KillUserProcesses should not apply to explicit termination. I think session_stop_scope should be changed to unconditionally kill the session when called from method_terminate_user. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] logind: always kill session when termination is requested
KillUserProcesses=yes/no should be ignored when termination is explicitly requested. --- This goes on top of * logind: use session_get_state() to get sessions state of the user * logind: just call user_stop() if user_check_gc() returns false With this patch loginctl terminate-user/session work for me. Zbyszek src/login/logind-dbus.c | 6 +++--- src/login/logind-seat-dbus.c| 2 +- src/login/logind-seat.c | 8 src/login/logind-seat.h | 4 ++-- src/login/logind-session-dbus.c | 2 +- src/login/logind-session.c | 12 ++-- src/login/logind-session.h | 2 +- src/login/logind-user-dbus.c| 2 +- src/login/logind-user.c | 4 ++-- src/login/logind-user.h | 2 +- src/login/logind.c | 6 +++--- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index d671346..bd0de33 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -939,7 +939,7 @@ static int method_terminate_session(sd_bus *bus, sd_bus_message *message, void * if (!session) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, No session '%s' known, name); -r = session_stop(session); +r = session_stop(session, true); if (r 0) return r; @@ -964,7 +964,7 @@ static int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *use if (!user) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, No user '%lu' known or logged in, (unsigned long) uid); -r = user_stop(user); +r = user_stop(user, true); if (r 0) return r; @@ -989,7 +989,7 @@ static int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *use if (!seat) return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, No seat '%s' known, name); -r = seat_stop_sessions(seat); +r = seat_stop_sessions(seat, true); if (r 0) return r; diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 909007c..26cddfe 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -201,7 +201,7 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata assert(message); assert(s); -r = seat_stop_sessions(s); +r = seat_stop_sessions(s, true); if (r 0) return r; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index c7f112a..631be5f 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -418,7 +418,7 @@ int seat_start(Seat *s) { return 0; } -int seat_stop(Seat *s) { +int seat_stop(Seat *s, bool force) { int r = 0; assert(s); @@ -430,7 +430,7 @@ int seat_stop(Seat *s) { MESSAGE=Removed seat %s., s-id, NULL); -seat_stop_sessions(s); +seat_stop_sessions(s, force); unlink(s-state_file); seat_add_to_gc_queue(s); @@ -443,14 +443,14 @@ int seat_stop(Seat *s) { return r; } -int seat_stop_sessions(Seat *s) { +int seat_stop_sessions(Seat *s, bool force) { Session *session; int r = 0, k; assert(s); LIST_FOREACH(sessions_by_seat, session, s-sessions) { -k = session_stop(session); +k = session_stop(session, force); if (k 0) r = k; } diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h index 9e21e3a..9e469d4 100644 --- a/src/login/logind-seat.h +++ b/src/login/logind-seat.h @@ -80,8 +80,8 @@ bool seat_can_graphical(Seat *s); int seat_get_idle_hint(Seat *s, dual_timestamp *t); int seat_start(Seat *s); -int seat_stop(Seat *s); -int seat_stop_sessions(Seat *s); +int seat_stop(Seat *s, bool force); +int seat_stop_sessions(Seat *s, bool force); bool seat_check_gc(Seat *s, bool drop_not_started); void seat_add_to_gc_queue(Seat *s); diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 7ee4956..f9305dd 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -188,7 +188,7 @@ static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata assert(message); assert(s); -r = session_stop(s); +r = session_stop(s, true); if (r 0) return r; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index f661cc8..d4742e1 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -565,7 +565,7 @@ int session_start(Session *s) { return 0; } -static int session_stop_scope(Session *s) { +static int session_stop_scope(Session *s, bool force) {