chiark / gitweb /
d5f88dbb47560499e0009234843113b4daebf675
[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
654         if (!dual_timestamp_is_set(&s->timestamp))
655                 dual_timestamp_get(&s->timestamp);
656
657         if (s->seat)
658                 seat_read_active_vt(s->seat);
659
660         s->started = true;
661
662         user_elect_display(s->user);
663
664         /* Save data */
665         session_save(s);
666         user_save(s->user);
667         if (s->seat)
668                 seat_save(s->seat);
669
670         /* Send signals */
671         session_send_signal(s, true);
672         user_send_changed(s->user, "Display", NULL);
673         if (s->seat) {
674                 if (s->seat->active == s)
675                         seat_send_changed(s->seat, "ActiveSession", NULL);
676         }
677
678         return 0;
679 }
680
681 #if 0 /// UNNEEDED by elogind
682 static int session_stop_scope(Session *s, bool force) {
683         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
684         int r;
685
686         assert(s);
687
688         if (!s->scope)
689                 return 0;
690
691         /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
692          * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
693          * when killing any processes left after this point. */
694         r = manager_abandon_scope(s->manager, s->scope, &error);
695         if (r < 0)
696                 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
697
698         /* Optionally, let's kill everything that's left now. */
699         if (force || manager_shall_kill(s->manager, s->user->name)) {
700                 char *job = NULL;
701
702                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
703                 if (r < 0)
704                         return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
705
706                 free(s->scope_job);
707                 s->scope_job = job;
708         } else {
709                 s->scope_job = mfree(s->scope_job);
710
711                 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
712                  * Therefore session stop and session removal may be two distinct events.
713                  * Session stop is quite significant on its own, let's log it. */
714                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
715                            "SESSION_ID=%s", s->id,
716                            "USER_ID=%s", s->user->name,
717                            "LEADER="PID_FMT, s->leader,
718                            LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
719         }
720
721         return 0;
722 }
723 #else
724 static int session_stop_cgroup(Session *s, bool force) {
725         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
726         int r;
727
728         assert(s);
729
730
731 int session_stop(Session *s, bool force) {
732         int r;
733
734         assert(s);
735
736         if (!s->user)
737                 return -ESTALE;
738
739         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
740
741         if (s->seat)
742                 seat_evict_position(s->seat, s);
743
744         /* We are going down, don't care about FIFOs anymore */
745         session_remove_fifo(s);
746
747         /* Kill cgroup */
748         r = session_stop_scope(s, force);
749
750         s->stopping = true;
751
752         user_elect_display(s->user);
753
754         session_save(s);
755         user_save(s->user);
756
757         return r;
758 }
759
760 int session_finalize(Session *s) {
761         SessionDevice *sd;
762
763         assert(s);
764
765         if (!s->user)
766                 return -ESTALE;
767
768         if (s->started)
769                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
770                            "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
771                            "SESSION_ID=%s", s->id,
772                            "USER_ID=%s", s->user->name,
773                            "LEADER="PID_FMT, s->leader,
774                            LOG_MESSAGE("Removed session %s.", s->id),
775                            NULL);
776                            LOG_MESSAGE("Removed session %s.", s->id));
777
778         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
779
780         if (s->seat)
781                 seat_evict_position(s->seat, s);
782
783         /* Kill session devices */
784         while ((sd = hashmap_first(s->devices)))
785                 session_device_free(sd);
786
787         (void) unlink(s->state_file);
788         session_add_to_gc_queue(s);
789         user_add_to_gc_queue(s->user);
790
791         if (s->started) {
792                 session_send_signal(s, false);
793                 s->started = false;
794         }
795
796         if (s->seat) {
797                 if (s->seat->active == s)
798                         seat_set_active(s->seat, NULL);
799
800                 seat_save(s->seat);
801         }
802
803         user_save(s->user);
804         user_send_changed(s->user, "Display", NULL);
805
806         return 0;
807 }
808
809 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
810         Session *s = userdata;
811
812         assert(es);
813         assert(s);
814
815         session_stop(s, false);
816         return 0;
817 }
818
819 int session_release(Session *s) {
820         assert(s);
821
822         if (!s->started || s->stopping)
823                 return 0;
824
825         if (s->timer_event_source)
826                 return 0;
827
828         return sd_event_add_time(s->manager->event,
829                                  &s->timer_event_source,
830                                  CLOCK_MONOTONIC,
831                                  now(CLOCK_MONOTONIC) + RELEASE_USEC, 0,
832                                  release_timeout_callback, s);
833 }
834
835 bool session_is_active(Session *s) {
836         assert(s);
837
838         if (!s->seat)
839                 return true;
840
841         return s->seat->active == s;
842 }
843
844 static int get_tty_atime(const char *tty, usec_t *atime) {
845         _cleanup_free_ char *p = NULL;
846         struct stat st;
847
848         assert(tty);
849         assert(atime);
850
851         if (!path_is_absolute(tty)) {
852                 p = strappend("/dev/", tty);
853                 if (!p)
854                         return -ENOMEM;
855
856                 tty = p;
857         } else if (!path_startswith(tty, "/dev/"))
858                 return -ENOENT;
859
860         if (lstat(tty, &st) < 0)
861                 return -errno;
862
863         *atime = timespec_load(&st.st_atim);
864         return 0;
865 }
866
867 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
868         _cleanup_free_ char *p = NULL;
869         int r;
870
871         assert(pid > 0);
872         assert(atime);
873
874         r = get_ctty(pid, NULL, &p);
875         if (r < 0)
876                 return r;
877
878         return get_tty_atime(p, atime);
879 }
880
881 int session_get_idle_hint(Session *s, dual_timestamp *t) {
882         usec_t atime = 0, n;
883         int r;
884
885         assert(s);
886
887         /* Explicit idle hint is set */
888         if (s->idle_hint) {
889                 if (t)
890                         *t = s->idle_hint_timestamp;
891
892                 return s->idle_hint;
893         }
894
895         /* Graphical sessions should really implement a real
896          * idle hint logic */
897         if (SESSION_TYPE_IS_GRAPHICAL(s->type))
898                 goto dont_know;
899
900         /* For sessions with an explicitly configured tty, let's check
901          * its atime */
902         if (s->tty) {
903                 r = get_tty_atime(s->tty, &atime);
904                 if (r >= 0)
905                         goto found_atime;
906         }
907
908         /* For sessions with a leader but no explicitly configured
909          * tty, let's check the controlling tty of the leader */
910         if (s->leader > 0) {
911                 r = get_process_ctty_atime(s->leader, &atime);
912                 if (r >= 0)
913                         goto found_atime;
914         }
915
916 dont_know:
917         if (t)
918                 *t = s->idle_hint_timestamp;
919
920         return 0;
921
922 found_atime:
923         if (t)
924                 dual_timestamp_from_realtime(t, atime);
925
926         n = now(CLOCK_REALTIME);
927
928         if (s->manager->idle_action_usec <= 0)
929                 return 0;
930
931         return atime + s->manager->idle_action_usec <= n;
932 }
933
934 void session_set_idle_hint(Session *s, bool b) {
935         assert(s);
936
937         if (s->idle_hint == b)
938                 return;
939
940         s->idle_hint = b;
941         dual_timestamp_get(&s->idle_hint_timestamp);
942
943         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
944
945         if (s->seat)
946                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
947
948         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
949         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
950 }
951
952 int session_get_locked_hint(Session *s) {
953         assert(s);
954
955         return s->locked_hint;
956 }
957
958 void session_set_locked_hint(Session *s, bool b) {
959         assert(s);
960
961         if (s->locked_hint == b)
962                 return;
963
964         s->locked_hint = b;
965
966         session_send_changed(s, "LockedHint", NULL);
967 }
968
969 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
970         Session *s = userdata;
971
972         assert(s);
973         assert(s->fifo_fd == fd);
974
975         /* EOF on the FIFO means the session died abnormally. */
976
977         session_remove_fifo(s);
978         session_stop(s, false);
979
980         return 1;
981 }
982
983 int session_create_fifo(Session *s) {
984         int r;
985
986         assert(s);
987
988         /* Create FIFO */
989         if (!s->fifo_path) {
990                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, false);
991                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, 0);
992                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
993                 if (r < 0)
994                         return r;
995
996                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
997                         return -ENOMEM;
998
999                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1000                         return -errno;
1001         }
1002
1003         /* Open reading side */
1004         if (s->fifo_fd < 0) {
1005                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
1006                 if (s->fifo_fd < 0)
1007                         return -errno;
1008
1009         }
1010
1011         if (!s->fifo_event_source) {
1012                 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
1013                 if (r < 0)
1014                         return r;
1015
1016                 /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new
1017                  * sessions). */
1018                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
1019                 if (r < 0)
1020                         return r;
1021         }
1022
1023         /* Open writing side */
1024         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK);
1025         if (r < 0)
1026                 return -errno;
1027
1028         return r;
1029 }
1030
1031 static void session_remove_fifo(Session *s) {
1032         assert(s);
1033
1034         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1035         s->fifo_fd = safe_close(s->fifo_fd);
1036
1037         if (s->fifo_path) {
1038                 unlink(s->fifo_path);
1039                 s->fifo_path = mfree(s->fifo_path);
1040         }
1041 }
1042
1043 bool session_may_gc(Session *s, bool drop_not_started) {
1044         assert(s);
1045
1046         if (drop_not_started && !s->started)
1047                 return true;
1048
1049         if (!s->user)
1050                 return true;
1051
1052         if (s->fifo_fd >= 0) {
1053                 if (pipe_eof(s->fifo_fd) <= 0)
1054                         return false;
1055         }
1056
1057         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
1058                 return false;
1059
1060         if (s->scope && manager_unit_is_active(s->manager, s->scope))
1061                 return false;
1062
1063         return true;
1064 }
1065
1066 void session_add_to_gc_queue(Session *s) {
1067         assert(s);
1068
1069         if (s->in_gc_queue)
1070                 return;
1071
1072         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
1073         s->in_gc_queue = true;
1074 }
1075
1076 SessionState session_get_state(Session *s) {
1077         assert(s);
1078
1079         /* always check closing first */
1080         if (s->stopping || s->timer_event_source)
1081                 return SESSION_CLOSING;
1082
1083         if (s->scope_job || s->fifo_fd < 0)
1084                 return SESSION_OPENING;
1085
1086         if (session_is_active(s))
1087                 return SESSION_ACTIVE;
1088
1089         return SESSION_ONLINE;
1090 }
1091
1092 int session_kill(Session *s, KillWho who, int signo) {
1093         assert(s);
1094
1095         if (!s->scope)
1096                 return -ESRCH;
1097
1098         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
1099 }
1100
1101 static int session_open_vt(Session *s) {
1102         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
1103
1104         if (s->vtnr < 1)
1105                 return -ENODEV;
1106
1107         if (s->vtfd >= 0)
1108                 return s->vtfd;
1109
1110         sprintf(path, "/dev/tty%u", s->vtnr);
1111         s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1112         if (s->vtfd < 0)
1113                 return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id);
1114
1115         return s->vtfd;
1116 }
1117
1118 int session_prepare_vt(Session *s) {
1119         int vt, r;
1120         struct vt_mode mode = { 0 };
1121
1122         if (s->vtnr < 1)
1123                 return 0;
1124
1125         vt = session_open_vt(s);
1126         if (vt < 0)
1127                 return vt;
1128
1129         r = fchown(vt, s->user->uid, -1);
1130         if (r < 0) {
1131                 r = log_error_errno(errno,
1132                                     "Cannot change owner of /dev/tty%u: %m",
1133                                     s->vtnr);
1134                 goto error;
1135         }
1136
1137         r = ioctl(vt, KDSKBMODE, K_OFF);
1138         if (r < 0) {
1139                 r = log_error_errno(errno,
1140                                     "Cannot set K_OFF on /dev/tty%u: %m",
1141                                     s->vtnr);
1142                 goto error;
1143         }
1144
1145         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
1146         if (r < 0) {
1147                 r = log_error_errno(errno,
1148                                     "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1149                                     s->vtnr);
1150                 goto error;
1151         }
1152
1153         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1154          * So we need a dummy handler here which just acknowledges *all* VT
1155          * switch requests. */
1156         mode.mode = VT_PROCESS;
1157         mode.relsig = SIGRTMIN;
1158         mode.acqsig = SIGRTMIN + 1;
1159         r = ioctl(vt, VT_SETMODE, &mode);
1160         if (r < 0) {
1161                 r = log_error_errno(errno,
1162                                     "Cannot set VT_PROCESS on /dev/tty%u: %m",
1163                                     s->vtnr);
1164                 goto error;
1165         }
1166
1167         return 0;
1168
1169 error:
1170         session_restore_vt(s);
1171         return r;
1172 }
1173
1174 void session_restore_vt(Session *s) {
1175
1176         static const struct vt_mode mode = {
1177                 .mode = VT_AUTO,
1178         };
1179
1180         int vt, old_fd;
1181
1182         /* We need to get a fresh handle to the virtual terminal,
1183          * since the old file-descriptor is potentially in a hung-up
1184          * state after the controlling process exited; we do a
1185          * little dance to avoid having the terminal be available
1186          * for reuse before we've cleaned it up.
1187          */
1188         old_fd = s->vtfd;
1189         s->vtfd = -1;
1190         old_fd = TAKE_FD(s->vtfd);
1191
1192         vt = session_open_vt(s);
1193         safe_close(old_fd);
1194
1195         if (vt < 0)
1196                 return;
1197
1198         (void) ioctl(vt, KDSETMODE, KD_TEXT);
1199
1200         (void) vt_reset_keyboard(vt);
1201
1202         (void) ioctl(vt, VT_SETMODE, &mode);
1203         (void) fchown(vt, 0, (gid_t) -1);
1204
1205         s->vtfd = safe_close(s->vtfd);
1206 }
1207
1208 void session_leave_vt(Session *s) {
1209         int r;
1210
1211         assert(s);
1212
1213         /* This is called whenever we get a VT-switch signal from the kernel.
1214          * We acknowledge all of them unconditionally. Note that session are
1215          * free to overwrite those handlers and we only register them for
1216          * sessions with controllers. Legacy sessions are not affected.
1217          * However, if we switch from a non-legacy to a legacy session, we must
1218          * make sure to pause all device before acknowledging the switch. We
1219          * process the real switch only after we are notified via sysfs, so the
1220          * legacy session might have already started using the devices. If we
1221          * don't pause the devices before the switch, we might confuse the
1222          * session we switch to. */
1223
1224         if (s->vtfd < 0)
1225                 return;
1226
1227         session_device_pause_all(s);
1228         r = ioctl(s->vtfd, VT_RELDISP, 1);
1229         if (r < 0)
1230                 log_debug_errno(errno, "Cannot release VT of session %s: %m", s->id);
1231 }
1232
1233 bool session_is_controller(Session *s, const char *sender) {
1234         assert(s);
1235
1236         return streq_ptr(s->controller, sender);
1237 }
1238
1239 static void session_release_controller(Session *s, bool notify) {
1240         _cleanup_free_ char *name = NULL;
1241         SessionDevice *sd;
1242
1243         if (!s->controller)
1244                 return;
1245
1246         name = s->controller;
1247
1248         /* By resetting the controller before releasing the devices, we won't
1249          * send notification signals. This avoids sending useless notifications
1250          * if the controller is released on disconnects. */
1251         if (!notify)
1252                 s->controller = NULL;
1253
1254         while ((sd = hashmap_first(s->devices)))
1255                 session_device_free(sd);
1256
1257         s->controller = NULL;
1258         s->track = sd_bus_track_unref(s->track);
1259 }
1260
1261 static int on_bus_track(sd_bus_track *track, void *userdata) {
1262         Session *s = userdata;
1263
1264         assert(track);
1265         assert(s);
1266
1267         session_drop_controller(s);
1268
1269         return 0;
1270 }
1271
1272 int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
1273         _cleanup_free_ char *name = NULL;
1274         int r;
1275
1276         assert(s);
1277         assert(sender);
1278
1279         if (session_is_controller(s, sender))
1280                 return 0;
1281         if (s->controller && !force)
1282                 return -EBUSY;
1283
1284         name = strdup(sender);
1285         if (!name)
1286                 return -ENOMEM;
1287
1288         s->track = sd_bus_track_unref(s->track);
1289         r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1290         if (r < 0)
1291                 return r;
1292
1293         r = sd_bus_track_add_name(s->track, name);
1294         if (r < 0)
1295                 return r;
1296
1297         /* When setting a session controller, we forcibly mute the VT and set
1298          * it into graphics-mode. Applications can override that by changing
1299          * VT state after calling TakeControl(). However, this serves as a good
1300          * default and well-behaving controllers can now ignore VTs entirely.
1301          * Note that we reset the VT on ReleaseControl() and if the controller
1302          * exits.
1303          * If logind crashes/restarts, we restore the controller during restart
1304          * (without preparing the VT since the controller has probably overridden
1305          * VT state by now) or reset the VT in case it crashed/exited, too. */
1306         if (prepare) {
1307                 r = session_prepare_vt(s);
1308                 if (r < 0) {
1309                         s->track = sd_bus_track_unref(s->track);
1310                         return r;
1311                 }
1312         }
1313
1314         session_release_controller(s, true);
1315         s->controller = name;
1316         name = NULL;
1317         s->controller = TAKE_PTR(name);
1318         session_save(s);
1319
1320         return 0;
1321 }
1322
1323 void session_drop_controller(Session *s) {
1324         assert(s);
1325
1326         if (!s->controller)
1327                 return;
1328
1329         s->track = sd_bus_track_unref(s->track);
1330         session_release_controller(s, false);
1331         session_save(s);
1332         session_restore_vt(s);
1333 }
1334
1335 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1336         [SESSION_OPENING] = "opening",
1337         [SESSION_ONLINE] = "online",
1338         [SESSION_ACTIVE] = "active",
1339         [SESSION_CLOSING] = "closing"
1340 };
1341
1342 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1343
1344 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1345         [SESSION_UNSPECIFIED] = "unspecified",
1346         [SESSION_TTY] = "tty",
1347         [SESSION_X11] = "x11",
1348         [SESSION_WAYLAND] = "wayland",
1349         [SESSION_MIR] = "mir",
1350         [SESSION_WEB] = "web",
1351 };
1352
1353 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1354
1355 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1356         [SESSION_USER] = "user",
1357         [SESSION_GREETER] = "greeter",
1358         [SESSION_LOCK_SCREEN] = "lock-screen",
1359         [SESSION_BACKGROUND] = "background"
1360 };
1361
1362 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1363
1364 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1365         [KILL_LEADER] = "leader",
1366         [KILL_ALL] = "all"
1367 };
1368
1369 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);