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