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