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