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