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