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