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