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