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