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