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