chiark / gitweb /
Prep v238: Do not kill user processes if not forced and the user is lingering.
[elogind.git] / src / login / logind-session.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2011 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <linux/kd.h>
24 #include <linux/vt.h>
25 #include <signal.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <unistd.h>
29
30 #include "sd-messages.h"
31
32 #include "alloc-util.h"
33 #include "audit-util.h"
34 #include "bus-error.h"
35 #include "bus-util.h"
36 #include "escape.h"
37 #include "fd-util.h"
38 #include "fileio.h"
39 #include "format-util.h"
40 #include "io-util.h"
41 #include "logind-session.h"
42 #include "mkdir.h"
43 #include "parse-util.h"
44 #include "path-util.h"
45 #include "string-table.h"
46 #include "terminal-util.h"
47 #include "user-util.h"
48 #include "util.h"
49
50 /// Additional includes needed by elogind
51 #include "extract-word.h"
52 #include "process-util.h"
53
54 #define RELEASE_USEC (20*USEC_PER_SEC)
55
56 static void session_remove_fifo(Session *s);
57
58 Session* session_new(Manager *m, const char *id) {
59         Session *s;
60
61         assert(m);
62         assert(id);
63         assert(session_id_valid(id));
64
65         s = new0(Session, 1);
66         if (!s)
67                 return NULL;
68
69         s->state_file = strappend("/run/systemd/sessions/", id);
70         if (!s->state_file)
71                 return mfree(s);
72
73         s->devices = hashmap_new(&devt_hash_ops);
74         if (!s->devices) {
75                 free(s->state_file);
76                 return mfree(s);
77         }
78
79         s->id = basename(s->state_file);
80
81         if (hashmap_put(m->sessions, s->id, s) < 0) {
82                 hashmap_free(s->devices);
83                 free(s->state_file);
84                 return mfree(s);
85         }
86
87         s->manager = m;
88         s->fifo_fd = -1;
89         s->vtfd = -1;
90         s->audit_id = AUDIT_SESSION_INVALID;
91
92         return s;
93 }
94
95 void session_free(Session *s) {
96         SessionDevice *sd;
97
98         assert(s);
99
100         if (s->in_gc_queue)
101                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
102
103         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
104
105         session_remove_fifo(s);
106
107         session_drop_controller(s);
108
109         while ((sd = hashmap_first(s->devices)))
110                 session_device_free(sd);
111
112         hashmap_free(s->devices);
113
114         if (s->user) {
115                 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
116
117                 if (s->user->display == s)
118                         s->user->display = NULL;
119         }
120
121         if (s->seat) {
122                 if (s->seat->active == s)
123                         s->seat->active = NULL;
124                 if (s->seat->pending_switch == s)
125                         s->seat->pending_switch = NULL;
126
127                 seat_evict_position(s->seat, s);
128                 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
129         }
130
131         if (s->scope) {
132                 hashmap_remove(s->manager->session_units, s->scope);
133                 free(s->scope);
134         }
135
136 #if 0 /// elogind does not support systemd scope_jobs
137         free(s->scope_job);
138 #endif // 0
139
140         sd_bus_message_unref(s->create_message);
141
142         free(s->tty);
143         free(s->display);
144         free(s->remote_host);
145         free(s->remote_user);
146         free(s->service);
147         free(s->desktop);
148
149         hashmap_remove(s->manager->sessions, s->id);
150
151         free(s->state_file);
152         free(s);
153 }
154
155 void session_set_user(Session *s, User *u) {
156         assert(s);
157         assert(!s->user);
158
159         s->user = u;
160         LIST_PREPEND(sessions_by_user, u->sessions, s);
161 }
162
163 static void session_save_devices(Session *s, FILE *f) {
164         SessionDevice *sd;
165         Iterator i;
166
167         if (!hashmap_isempty(s->devices)) {
168                 fprintf(f, "DEVICES=");
169                 HASHMAP_FOREACH(sd, s->devices, i)
170                         fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
171                 fprintf(f, "\n");
172         }
173 }
174
175 int session_save(Session *s) {
176         _cleanup_free_ char *temp_path = NULL;
177         _cleanup_fclose_ FILE *f = NULL;
178         int r = 0;
179
180         assert(s);
181
182         if (!s->user)
183                 return -ESTALE;
184
185         if (!s->started)
186                 return 0;
187
188         r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false);
189         if (r < 0)
190                 goto fail;
191
192         r = fopen_temporary(s->state_file, &f, &temp_path);
193         if (r < 0)
194                 goto fail;
195
196         assert(s->user);
197
198         fchmod(fileno(f), 0644);
199
200         fprintf(f,
201                 "# This is private data. Do not parse.\n"
202                 "UID="UID_FMT"\n"
203                 "USER=%s\n"
204                 "ACTIVE=%i\n"
205                 "STATE=%s\n"
206                 "REMOTE=%i\n",
207                 s->user->uid,
208                 s->user->name,
209                 session_is_active(s),
210                 session_state_to_string(session_get_state(s)),
211                 s->remote);
212
213         if (s->type >= 0)
214                 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
215
216         if (s->class >= 0)
217                 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
218
219         if (s->scope)
220                 fprintf(f, "SCOPE=%s\n", s->scope);
221 #if 0 /// elogind does not support systemd scope_jobs
222         if (s->scope_job)
223                 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
224 #endif // 0
225
226         if (s->fifo_path)
227                 fprintf(f, "FIFO=%s\n", s->fifo_path);
228
229         if (s->seat)
230                 fprintf(f, "SEAT=%s\n", s->seat->id);
231
232         if (s->tty)
233                 fprintf(f, "TTY=%s\n", s->tty);
234
235         if (s->display)
236                 fprintf(f, "DISPLAY=%s\n", s->display);
237
238         if (s->remote_host) {
239                 _cleanup_free_ char *escaped;
240
241                 escaped = cescape(s->remote_host);
242                 if (!escaped) {
243                         r = -ENOMEM;
244                         goto fail;
245                 }
246
247                 fprintf(f, "REMOTE_HOST=%s\n", escaped);
248         }
249
250         if (s->remote_user) {
251                 _cleanup_free_ char *escaped;
252
253                 escaped = cescape(s->remote_user);
254                 if (!escaped) {
255                         r = -ENOMEM;
256                         goto fail;
257                 }
258
259                 fprintf(f, "REMOTE_USER=%s\n", escaped);
260         }
261
262         if (s->service) {
263                 _cleanup_free_ char *escaped;
264
265                 escaped = cescape(s->service);
266                 if (!escaped) {
267                         r = -ENOMEM;
268                         goto fail;
269                 }
270
271                 fprintf(f, "SERVICE=%s\n", escaped);
272         }
273
274         if (s->desktop) {
275                 _cleanup_free_ char *escaped;
276
277
278                 escaped = cescape(s->desktop);
279                 if (!escaped) {
280                         r = -ENOMEM;
281                         goto fail;
282                 }
283
284                 fprintf(f, "DESKTOP=%s\n", escaped);
285         }
286
287         if (s->seat && seat_has_vts(s->seat))
288                 fprintf(f, "VTNR=%u\n", s->vtnr);
289
290         if (!s->vtnr)
291                 fprintf(f, "POSITION=%u\n", s->position);
292
293         if (pid_is_valid(s->leader))
294                 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
295
296         if (audit_session_is_valid(s->audit_id))
297                 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
298
299         if (dual_timestamp_is_set(&s->timestamp))
300                 fprintf(f,
301                         "REALTIME="USEC_FMT"\n"
302                         "MONOTONIC="USEC_FMT"\n",
303                         s->timestamp.realtime,
304                         s->timestamp.monotonic);
305
306         if (s->controller) {
307                 fprintf(f, "CONTROLLER=%s\n", s->controller);
308                 session_save_devices(s, f);
309         }
310
311         r = fflush_and_check(f);
312         if (r < 0)
313                 goto fail;
314
315         if (rename(temp_path, s->state_file) < 0) {
316                 r = -errno;
317                 goto fail;
318         }
319
320         return 0;
321
322 fail:
323         (void) unlink(s->state_file);
324
325         if (temp_path)
326                 (void) unlink(temp_path);
327
328         return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
329 }
330
331 static int session_load_devices(Session *s, const char *devices) {
332         const char *p;
333         int r = 0;
334
335         assert(s);
336
337         for (p = devices;;) {
338                 _cleanup_free_ char *word = NULL;
339                 SessionDevice *sd;
340                 dev_t dev;
341                 int k;
342
343                 k = extract_first_word(&p, &word, NULL, 0);
344                 if (k == 0)
345                         break;
346                 if (k < 0) {
347                         r = k;
348                         break;
349                 }
350
351                 k = parse_dev(word, &dev);
352                 if (k < 0) {
353                         r = k;
354                         continue;
355                 }
356
357                 /* The file descriptors for loaded devices will be reattached later. */
358                 k = session_device_new(s, dev, false, &sd);
359                 if (k < 0)
360                         r = k;
361         }
362
363         if (r < 0)
364                 log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
365
366         return r;
367 }
368
369 int session_load(Session *s) {
370         _cleanup_free_ char *remote = NULL,
371                 *seat = NULL,
372                 *vtnr = NULL,
373                 *state = NULL,
374                 *position = NULL,
375                 *leader = NULL,
376                 *type = NULL,
377                 *class = NULL,
378                 *uid = NULL,
379                 *realtime = NULL,
380                 *monotonic = NULL,
381                 *controller = NULL,
382                 *active = NULL,
383                 *devices = NULL;
384
385         int k, r;
386
387         assert(s);
388
389         r = parse_env_file(s->state_file, NEWLINE,
390                            "REMOTE",         &remote,
391                            "SCOPE",          &s->scope,
392 #if 0 /// elogind does not support systemd scope_jobs
393                            "SCOPE_JOB",      &s->scope_job,
394 #endif // 0
395                            "FIFO",           &s->fifo_path,
396                            "SEAT",           &seat,
397                            "TTY",            &s->tty,
398                            "DISPLAY",        &s->display,
399                            "REMOTE_HOST",    &s->remote_host,
400                            "REMOTE_USER",    &s->remote_user,
401                            "SERVICE",        &s->service,
402                            "DESKTOP",        &s->desktop,
403                            "VTNR",           &vtnr,
404                            "STATE",          &state,
405                            "POSITION",       &position,
406                            "LEADER",         &leader,
407                            "TYPE",           &type,
408                            "CLASS",          &class,
409                            "UID",            &uid,
410                            "REALTIME",       &realtime,
411                            "MONOTONIC",      &monotonic,
412                            "CONTROLLER",     &controller,
413                            "ACTIVE",         &active,
414                            "DEVICES",        &devices,
415                            NULL);
416
417         if (r < 0)
418                 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
419
420         if (!s->user) {
421                 uid_t u;
422                 User *user;
423
424                 if (!uid) {
425                         log_error("UID not specified for session %s", s->id);
426                         return -ENOENT;
427                 }
428
429                 r = parse_uid(uid, &u);
430                 if (r < 0)  {
431                         log_error("Failed to parse UID value %s for session %s.", uid, s->id);
432                         return r;
433                 }
434
435                 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
436                 if (!user) {
437                         log_error("User of session %s not known.", s->id);
438                         return -ENOENT;
439                 }
440
441                 session_set_user(s, user);
442         }
443
444         if (remote) {
445                 k = parse_boolean(remote);
446                 if (k >= 0)
447                         s->remote = k;
448         }
449
450         if (vtnr)
451                 safe_atou(vtnr, &s->vtnr);
452
453         if (seat && !s->seat) {
454                 Seat *o;
455
456                 o = hashmap_get(s->manager->seats, seat);
457                 if (o)
458                         r = seat_attach_session(o, s);
459                 if (!o || r < 0)
460                         log_error("Cannot attach session %s to seat %s", s->id, seat);
461         }
462
463         if (!s->seat || !seat_has_vts(s->seat))
464                 s->vtnr = 0;
465
466         if (position && s->seat) {
467                 unsigned int npos;
468
469                 safe_atou(position, &npos);
470                 seat_claim_position(s->seat, s, npos);
471         }
472
473         if (leader) {
474                 if (parse_pid(leader, &s->leader) >= 0)
475                         (void) audit_session_from_pid(s->leader, &s->audit_id);
476         }
477
478         if (type) {
479                 SessionType t;
480
481                 t = session_type_from_string(type);
482                 if (t >= 0)
483                         s->type = t;
484         }
485
486         if (class) {
487                 SessionClass c;
488
489                 c = session_class_from_string(class);
490                 if (c >= 0)
491                         s->class = c;
492         }
493
494         if (state && streq(state, "closing"))
495                 s->stopping = true;
496
497         if (s->fifo_path) {
498                 int fd;
499
500                 /* If we open an unopened pipe for reading we will not
501                    get an EOF. to trigger an EOF we hence open it for
502                    writing, but close it right away which then will
503                    trigger the EOF. This will happen immediately if no
504                    other process has the FIFO open for writing, i. e.
505                    when the session died before logind (re)started. */
506
507                 fd = session_create_fifo(s);
508                 safe_close(fd);
509         }
510
511         if (realtime)
512                 timestamp_deserialize(realtime, &s->timestamp.realtime);
513         if (monotonic)
514                 timestamp_deserialize(monotonic, &s->timestamp.monotonic);
515
516         if (active) {
517                 k = parse_boolean(active);
518                 if (k >= 0)
519                         s->was_active = k;
520         }
521
522         if (controller) {
523                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
524                         session_set_controller(s, controller, false, false);
525                         session_load_devices(s, devices);
526                 } else
527                         session_restore_vt(s);
528         }
529
530         return r;
531 }
532
533 int session_activate(Session *s) {
534         unsigned int num_pending;
535
536         assert(s);
537         assert(s->user);
538
539         if (!s->seat)
540                 return -EOPNOTSUPP;
541
542         if (s->seat->active == s)
543                 return 0;
544
545         /* on seats with VTs, we let VTs manage session-switching */
546         if (seat_has_vts(s->seat)) {
547                 if (!s->vtnr)
548                         return -EOPNOTSUPP;
549
550                 return chvt(s->vtnr);
551         }
552
553         /* On seats without VTs, we implement session-switching in logind. We
554          * try to pause all session-devices and wait until the session
555          * controller acknowledged them. Once all devices are asleep, we simply
556          * switch the active session and be done.
557          * We save the session we want to switch to in seat->pending_switch and
558          * seat_complete_switch() will perform the final switch. */
559
560         s->seat->pending_switch = s;
561
562         /* if no devices are running, immediately perform the session switch */
563         num_pending = session_device_try_pause_all(s);
564         if (!num_pending)
565                 seat_complete_switch(s->seat);
566
567         return 0;
568 }
569
570 #if 0 /// UNNEEDED by elogind
571 static int session_start_scope(Session *s) {
572         int r;
573
574         assert(s);
575         assert(s->user);
576
577         if (!s->scope) {
578                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
579                 char *scope, *job = NULL;
580                 const char *description;
581
582                 scope = strjoin("session-", s->id, ".scope");
583                 if (!scope)
584                         return log_oom();
585
586                 description = strjoina("Session ", s->id, " of user ", s->user->name);
587
588                 r = manager_start_scope(
589                                 s->manager,
590                                 scope,
591                                 s->leader,
592                                 s->user->slice,
593                                 description,
594                                 "systemd-logind.service",
595                                 "systemd-user-sessions.service",
596                                 (uint64_t) -1, /* disable TasksMax= for the scope, rely on the slice setting for it */
597                                 &error,
598                                 &job);
599                 if (r < 0) {
600                         log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
601                         free(scope);
602                         return r;
603                 } else {
604                         s->scope = scope;
605
606                         free(s->scope_job);
607                         s->scope_job = job;
608                 }
609         }
610
611         if (s->scope)
612                 (void) hashmap_put(s->manager->session_units, s->scope, s);
613
614         return 0;
615 }
616 #else
617 static int session_start_cgroup(Session *s) {
618         int r;
619
620         assert(s);
621         assert(s->user);
622         assert(s->leader > 0);
623
624         /* First, create our own group */
625         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, s->id);
626         if (r < 0)
627                 return log_error_errno(r, "Failed to create cgroup %s: %m", s->id);
628
629         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, s->id, s->leader);
630         if (r < 0)
631                 log_warning_errno(r, "Failed to attach PID %d to cgroup %s: %m", s->leader, s->id);
632
633         return 0;
634 }
635 #endif // 0
636
637 int session_start(Session *s) {
638         int r;
639
640         assert(s);
641
642         if (!s->user)
643                 return -ESTALE;
644
645         if (s->started)
646                 return 0;
647
648         r = user_start(s->user);
649         if (r < 0)
650                 return r;
651
652         /* Create cgroup */
653 #if 0 /// elogind does its own session management
654         r = session_start_scope(s);
655 #else
656         r = session_start_cgroup(s);
657 #endif // 0
658         if (r < 0)
659                 return r;
660
661         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
662                    "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
663                    "SESSION_ID=%s", s->id,
664                    "USER_ID=%s", s->user->name,
665                    "LEADER="PID_FMT, s->leader,
666                    LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name),
667                    NULL);
668
669         if (!dual_timestamp_is_set(&s->timestamp))
670                 dual_timestamp_get(&s->timestamp);
671
672         if (s->seat)
673                 seat_read_active_vt(s->seat);
674
675         s->started = true;
676
677         user_elect_display(s->user);
678
679         /* Save data */
680         session_save(s);
681         user_save(s->user);
682         if (s->seat)
683                 seat_save(s->seat);
684
685         /* Send signals */
686         session_send_signal(s, true);
687         user_send_changed(s->user, "Display", NULL);
688         if (s->seat) {
689                 if (s->seat->active == s)
690                         seat_send_changed(s->seat, "ActiveSession", NULL);
691         }
692
693         return 0;
694 }
695
696 #if 0 /// UNNEEDED by elogind
697 static int session_stop_scope(Session *s, bool force) {
698         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
699         int r;
700
701         assert(s);
702
703         if (!s->scope)
704                 return 0;
705
706         /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
707          * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
708          * when killing any processes left after this point. */
709         r = manager_abandon_scope(s->manager, s->scope, &error);
710         if (r < 0)
711                 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
712
713         /* Optionally, let's kill everything that's left now. */
714         if (force || manager_shall_kill(s->manager, s->user->name)) {
715                 char *job = NULL;
716
717                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
718                 if (r < 0)
719                         return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
720
721                 free(s->scope_job);
722                 s->scope_job = job;
723         } else
724                 s->scope_job = mfree(s->scope_job);
725
726         return 0;
727 }
728 #else
729 static int session_stop_cgroup(Session *s, bool force) {
730         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
731         int r;
732
733         assert(s);
734
735 #if 0 /// elogind must not kill lingering user processes alive
736         if (force || manager_shall_kill(s->manager, s->user->name)) {
737 #else
738         if (force
739           || ( manager_shall_kill(s->manager, s->user->name)
740             && (user_check_linger_file(s->user) < 1) ) ) {
741 #endif // 1
742
743                 r = session_kill(s, KILL_ALL, SIGTERM);
744                 if (r < 0)
745                         return r;
746         }
747
748         return 0;
749 }
750 #endif // 0
751
752 int session_stop(Session *s, bool force) {
753         int r;
754
755         assert(s);
756
757         if (!s->user)
758                 return -ESTALE;
759
760         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
761
762         if (s->seat)
763                 seat_evict_position(s->seat, s);
764
765         /* We are going down, don't care about FIFOs anymore */
766         session_remove_fifo(s);
767
768         /* Kill cgroup */
769 #if 0 /// elogind does not start scopes, but sessions
770         r = session_stop_scope(s, force);
771 #else
772         r = session_stop_cgroup(s, force);
773 #endif // 0
774
775         s->stopping = true;
776
777         user_elect_display(s->user);
778
779         session_save(s);
780         user_save(s->user);
781
782 #if 1 /// elogind must queue this session again
783         session_add_to_gc_queue(s);
784 #endif // 1
785         return r;
786 }
787
788 int session_finalize(Session *s) {
789         SessionDevice *sd;
790
791         assert(s);
792
793         if (!s->user)
794                 return -ESTALE;
795
796         if (s->started)
797                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
798                            "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
799                            "SESSION_ID=%s", s->id,
800                            "USER_ID=%s", s->user->name,
801                            "LEADER="PID_FMT, s->leader,
802                            LOG_MESSAGE("Removed session %s.", s->id),
803                            NULL);
804
805         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
806
807         if (s->seat)
808                 seat_evict_position(s->seat, s);
809
810         /* Kill session devices */
811         while ((sd = hashmap_first(s->devices)))
812                 session_device_free(sd);
813
814         (void) unlink(s->state_file);
815         session_add_to_gc_queue(s);
816         user_add_to_gc_queue(s->user);
817
818         if (s->started) {
819                 session_send_signal(s, false);
820                 s->started = false;
821         }
822
823         if (s->seat) {
824                 if (s->seat->active == s)
825                         seat_set_active(s->seat, NULL);
826
827                 seat_save(s->seat);
828         }
829
830         user_save(s->user);
831         user_send_changed(s->user, "Display", NULL);
832
833         return 0;
834 }
835
836 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
837         Session *s = userdata;
838
839         assert(es);
840         assert(s);
841
842         session_stop(s, false);
843         return 0;
844 }
845
846 int session_release(Session *s) {
847         assert(s);
848
849         if (!s->started || s->stopping)
850                 return 0;
851
852         if (s->timer_event_source)
853                 return 0;
854
855         return sd_event_add_time(s->manager->event,
856                                  &s->timer_event_source,
857                                  CLOCK_MONOTONIC,
858                                  now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
859                                  release_timeout_callback, s);
860 }
861
862 bool session_is_active(Session *s) {
863         assert(s);
864
865         if (!s->seat)
866                 return true;
867
868         return s->seat->active == s;
869 }
870
871 static int get_tty_atime(const char *tty, usec_t *atime) {
872         _cleanup_free_ char *p = NULL;
873         struct stat st;
874
875         assert(tty);
876         assert(atime);
877
878         if (!path_is_absolute(tty)) {
879                 p = strappend("/dev/", tty);
880                 if (!p)
881                         return -ENOMEM;
882
883                 tty = p;
884         } else if (!path_startswith(tty, "/dev/"))
885                 return -ENOENT;
886
887         if (lstat(tty, &st) < 0)
888                 return -errno;
889
890         *atime = timespec_load(&st.st_atim);
891         return 0;
892 }
893
894 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
895         _cleanup_free_ char *p = NULL;
896         int r;
897
898         assert(pid > 0);
899         assert(atime);
900
901         r = get_ctty(pid, NULL, &p);
902         if (r < 0)
903                 return r;
904
905         return get_tty_atime(p, atime);
906 }
907
908 int session_get_idle_hint(Session *s, dual_timestamp *t) {
909         usec_t atime = 0, n;
910         int r;
911
912         assert(s);
913
914         /* Explicit idle hint is set */
915         if (s->idle_hint) {
916                 if (t)
917                         *t = s->idle_hint_timestamp;
918
919                 return s->idle_hint;
920         }
921
922         /* Graphical sessions should really implement a real
923          * idle hint logic */
924         if (SESSION_TYPE_IS_GRAPHICAL(s->type))
925                 goto dont_know;
926
927         /* For sessions with an explicitly configured tty, let's check
928          * its atime */
929         if (s->tty) {
930                 r = get_tty_atime(s->tty, &atime);
931                 if (r >= 0)
932                         goto found_atime;
933         }
934
935         /* For sessions with a leader but no explicitly configured
936          * tty, let's check the controlling tty of the leader */
937         if (s->leader > 0) {
938                 r = get_process_ctty_atime(s->leader, &atime);
939                 if (r >= 0)
940                         goto found_atime;
941         }
942
943 dont_know:
944         if (t)
945                 *t = s->idle_hint_timestamp;
946
947         return 0;
948
949 found_atime:
950         if (t)
951                 dual_timestamp_from_realtime(t, atime);
952
953         n = now(CLOCK_REALTIME);
954
955         if (s->manager->idle_action_usec <= 0)
956                 return 0;
957
958         return atime + s->manager->idle_action_usec <= n;
959 }
960
961 void session_set_idle_hint(Session *s, bool b) {
962         assert(s);
963
964         if (s->idle_hint == b)
965                 return;
966
967         s->idle_hint = b;
968         dual_timestamp_get(&s->idle_hint_timestamp);
969
970         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
971
972         if (s->seat)
973                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
974
975         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
976         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
977 }
978
979 int session_get_locked_hint(Session *s) {
980         assert(s);
981
982         return s->locked_hint;
983 }
984
985 void session_set_locked_hint(Session *s, bool b) {
986         assert(s);
987
988         if (s->locked_hint == b)
989                 return;
990
991         s->locked_hint = b;
992
993         session_send_changed(s, "LockedHint", NULL);
994 }
995
996 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
997         Session *s = userdata;
998
999         assert(s);
1000         assert(s->fifo_fd == fd);
1001
1002         /* EOF on the FIFO means the session died abnormally. */
1003
1004         session_remove_fifo(s);
1005         session_stop(s, false);
1006
1007         return 1;
1008 }
1009
1010 int session_create_fifo(Session *s) {
1011         int r;
1012
1013         assert(s);
1014
1015         /* Create FIFO */
1016         if (!s->fifo_path) {
1017                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false);
1018                 if (r < 0)
1019                         return r;
1020
1021                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
1022                         return -ENOMEM;
1023
1024                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1025                         return -errno;
1026         }
1027
1028         /* Open reading side */
1029         if (s->fifo_fd < 0) {
1030                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1031                 if (s->fifo_fd < 0)
1032                         return -errno;
1033
1034         }
1035
1036         if (!s->fifo_event_source) {
1037                 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
1038                 if (r < 0)
1039                         return r;
1040
1041                 /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
1042                  * sessions). */
1043                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
1044                 if (r < 0)
1045                         return r;
1046         }
1047
1048         /* Open writing side */
1049         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
1050         if (r < 0)
1051                 return -errno;
1052
1053         return r;
1054 }
1055
1056 static void session_remove_fifo(Session *s) {
1057         assert(s);
1058
1059         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1060         s->fifo_fd = safe_close(s->fifo_fd);
1061
1062         if (s->fifo_path) {
1063                 unlink(s->fifo_path);
1064                 s->fifo_path = mfree(s->fifo_path);
1065         }
1066 }
1067
1068 bool session_may_gc(Session *s, bool drop_not_started) {
1069         assert(s);
1070
1071         if (drop_not_started && !s->started)
1072                 return true;
1073
1074         if (!s->user)
1075                 return true;
1076
1077         if (s->fifo_fd >= 0) {
1078                 if (pipe_eof(s->fifo_fd) <= 0)
1079                         return false;
1080         }
1081
1082 #if 0 /// elogind supports neither scopes nor jobs
1083         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
1084                 return false;
1085
1086         if (s->scope && manager_unit_is_active(s->manager, s->scope))
1087 #endif // 0
1088                 return false;
1089
1090         return true;
1091 }
1092
1093 void session_add_to_gc_queue(Session *s) {
1094         assert(s);
1095
1096         if (s->in_gc_queue)
1097                 return;
1098
1099         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1100         s->in_gc_queue = true;
1101 }
1102
1103 SessionState session_get_state(Session *s) {
1104         assert(s);
1105
1106         /* always check closing first */
1107         if (s->stopping || s->timer_event_source)
1108                 return SESSION_CLOSING;
1109
1110 #if 0 /// elogind does not support systemd scope_jobs
1111         if (s->scope_job || s->fifo_fd < 0)
1112 #else
1113         if (s->fifo_fd < 0)
1114 #endif // 0
1115                 return SESSION_OPENING;
1116
1117         if (session_is_active(s))
1118                 return SESSION_ACTIVE;
1119
1120         return SESSION_ONLINE;
1121 }
1122
1123 int session_kill(Session *s, KillWho who, int signo) {
1124         assert(s);
1125
1126 #if 0 /// Without direct cgroup support, elogind can not kill sessions
1127         if (!s->scope)
1128                 return -ESRCH;
1129
1130         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
1131 #else
1132         if (who == KILL_LEADER) {
1133                 if (s->leader <= 0)
1134                         return -ESRCH;
1135
1136                 /* FIXME: verify that leader is in cgroup?  */
1137
1138                 if (kill(s->leader, signo) < 0) {
1139                         return log_error_errno(errno, "Failed to kill process leader %d for session %s: %m", s->leader, s->id);
1140                 }
1141                 return 0;
1142         } else
1143                 return cg_kill_recursive (SYSTEMD_CGROUP_CONTROLLER, s->id, signo,
1144                                           CGROUP_IGNORE_SELF | CGROUP_REMOVE,
1145                                           NULL, NULL, NULL);
1146 #endif // 0
1147 }
1148
1149 static int session_open_vt(Session *s) {
1150         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1151
1152         if (s->vtnr < 1)
1153                 return -ENODEV;
1154
1155         if (s->vtfd >= 0)
1156                 return s->vtfd;
1157
1158         sprintf(path, "/dev/tty%u", s->vtnr);
1159         s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1160         if (s->vtfd < 0)
1161                 return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id);
1162
1163         return s->vtfd;
1164 }
1165
1166 int session_prepare_vt(Session *s) {
1167         int vt, r;
1168         struct vt_mode mode = { 0 };
1169
1170         if (s->vtnr < 1)
1171                 return 0;
1172
1173         vt = session_open_vt(s);
1174         if (vt < 0)
1175                 return vt;
1176
1177         r = fchown(vt, s->user->uid, -1);
1178         if (r < 0) {
1179                 r = log_error_errno(errno,
1180                                     "Cannot change owner of /dev/tty%u: %m",
1181                                     s->vtnr);
1182                 goto error;
1183         }
1184
1185         r = ioctl(vt, KDSKBMODE, K_OFF);
1186         if (r < 0) {
1187                 r = log_error_errno(errno,
1188                                     "Cannot set K_OFF on /dev/tty%u: %m",
1189                                     s->vtnr);
1190                 goto error;
1191         }
1192
1193         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1194         if (r < 0) {
1195                 r = log_error_errno(errno,
1196                                     "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1197                                     s->vtnr);
1198                 goto error;
1199         }
1200
1201         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1202          * So we need a dummy handler here which just acknowledges *all* VT
1203          * switch requests. */
1204         mode.mode = VT_PROCESS;
1205         mode.relsig = SIGRTMIN;
1206         mode.acqsig = SIGRTMIN + 1;
1207         r = ioctl(vt, VT_SETMODE, &mode);
1208         if (r < 0) {
1209                 r = log_error_errno(errno,
1210                                     "Cannot set VT_PROCESS on /dev/tty%u: %m",
1211                                     s->vtnr);
1212                 goto error;
1213         }
1214
1215         return 0;
1216
1217 error:
1218         session_restore_vt(s);
1219         return r;
1220 }
1221
1222 void session_restore_vt(Session *s) {
1223
1224         static const struct vt_mode mode = {
1225                 .mode = VT_AUTO,
1226         };
1227
1228         int vt, old_fd;
1229
1230         /* We need to get a fresh handle to the virtual terminal,
1231          * since the old file-descriptor is potentially in a hung-up
1232          * state after the controlling process exited; we do a
1233          * little dance to avoid having the terminal be available
1234          * for reuse before we've cleaned it up.
1235          */
1236         old_fd = s->vtfd;
1237         s->vtfd = -1;
1238
1239         vt = session_open_vt(s);
1240         safe_close(old_fd);
1241
1242         if (vt < 0)
1243                 return;
1244
1245         (void) ioctl(vt, KDSETMODE, KD_TEXT);
1246
1247         (void) vt_reset_keyboard(vt);
1248
1249         (void) ioctl(vt, VT_SETMODE, &mode);
1250         (void) fchown(vt, 0, (gid_t) -1);
1251
1252         s->vtfd = safe_close(s->vtfd);
1253 }
1254
1255 void session_leave_vt(Session *s) {
1256         int r;
1257
1258         assert(s);
1259
1260         /* This is called whenever we get a VT-switch signal from the kernel.
1261          * We acknowledge all of them unconditionally. Note that session are
1262          * free to overwrite those handlers and we only register them for
1263          * sessions with controllers. Legacy sessions are not affected.
1264          * However, if we switch from a non-legacy to a legacy session, we must
1265          * make sure to pause all device before acknowledging the switch. We
1266          * process the real switch only after we are notified via sysfs, so the
1267          * legacy session might have already started using the devices. If we
1268          * don't pause the devices before the switch, we might confuse the
1269          * session we switch to. */
1270
1271         if (s->vtfd < 0)
1272                 return;
1273
1274         session_device_pause_all(s);
1275         r = ioctl(s->vtfd, VT_RELDISP, 1);
1276         if (r < 0)
1277                 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
1278 }
1279
1280 bool session_is_controller(Session *s, const char *sender) {
1281         assert(s);
1282
1283         return streq_ptr(s->controller, sender);
1284 }
1285
1286 static void session_release_controller(Session *s, bool notify) {
1287         _cleanup_free_ char *name = NULL;
1288         SessionDevice *sd;
1289
1290         if (!s->controller)
1291                 return;
1292
1293         name = s->controller;
1294
1295         /* By resetting the controller before releasing the devices, we won't
1296          * send notification signals. This avoids sending useless notifications
1297          * if the controller is released on disconnects. */
1298         if (!notify)
1299                 s->controller = NULL;
1300
1301         while ((sd = hashmap_first(s->devices)))
1302                 session_device_free(sd);
1303
1304         s->controller = NULL;
1305         s->track = sd_bus_track_unref(s->track);
1306 }
1307
1308 static int on_bus_track(sd_bus_track *track, void *userdata) {
1309         Session *s = userdata;
1310
1311         assert(track);
1312         assert(s);
1313
1314         session_drop_controller(s);
1315
1316         return 0;
1317 }
1318
1319 int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1320         _cleanup_free_ char *name = NULL;
1321         int r;
1322
1323         assert(s);
1324         assert(sender);
1325
1326         if (session_is_controller(s, sender))
1327                 return 0;
1328         if (s->controller && !force)
1329                 return -EBUSY;
1330
1331         name = strdup(sender);
1332         if (!name)
1333                 return -ENOMEM;
1334
1335         s->track = sd_bus_track_unref(s->track);
1336         r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1337         if (r < 0)
1338                 return r;
1339
1340         r = sd_bus_track_add_name(s->track, name);
1341         if (r < 0)
1342                 return r;
1343
1344         /* When setting a session controller, we forcibly mute the VT and set
1345          * it into graphics-mode. Applications can override that by changing
1346          * VT state after calling TakeControl(). However, this serves as a good
1347          * default and well-behaving controllers can now ignore VTs entirely.
1348          * Note that we reset the VT on ReleaseControl() and if the controller
1349          * exits.
1350          * If logind crashes/restarts, we restore the controller during restart
1351          * (without preparing the VT since the controller has probably overridden
1352          * VT state by now) or reset the VT in case it crashed/exited, too. */
1353         if (prepare) {
1354                 r = session_prepare_vt(s);
1355                 if (r < 0) {
1356                         s->track = sd_bus_track_unref(s->track);
1357                         return r;
1358                 }
1359         }
1360
1361         session_release_controller(s, true);
1362         s->controller = name;
1363         name = NULL;
1364         session_save(s);
1365
1366         return 0;
1367 }
1368
1369 void session_drop_controller(Session *s) {
1370         assert(s);
1371
1372         if (!s->controller)
1373                 return;
1374
1375         s->track = sd_bus_track_unref(s->track);
1376         session_release_controller(s, false);
1377         session_save(s);
1378         session_restore_vt(s);
1379 }
1380
1381 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1382         [SESSION_OPENING] = "opening",
1383         [SESSION_ONLINE] = "online",
1384         [SESSION_ACTIVE] = "active",
1385         [SESSION_CLOSING] = "closing"
1386 };
1387
1388 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1389
1390 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1391         [SESSION_UNSPECIFIED] = "unspecified",
1392         [SESSION_TTY] = "tty",
1393         [SESSION_X11] = "x11",
1394         [SESSION_WAYLAND] = "wayland",
1395         [SESSION_MIR] = "mir",
1396         [SESSION_WEB] = "web",
1397 };
1398
1399 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1400
1401 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1402         [SESSION_USER] = "user",
1403         [SESSION_GREETER] = "greeter",
1404         [SESSION_LOCK_SCREEN] = "lock-screen",
1405         [SESSION_BACKGROUND] = "background"
1406 };
1407
1408 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1409
1410 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1411         [KILL_LEADER] = "leader",
1412         [KILL_ALL] = "all"
1413 };
1414
1415 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);