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