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