]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session.c
audit: introduce audit_session_is_valid() and make use of it everywhere
[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 s->audit_id = AUDIT_SESSION_INVALID;
86
87 return s;
88 }
89
90 void session_free(Session *s) {
91 SessionDevice *sd;
92
93 assert(s);
94
95 if (s->in_gc_queue)
96 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
97
98 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
99
100 session_remove_fifo(s);
101
102 session_drop_controller(s);
103
104 while ((sd = hashmap_first(s->devices)))
105 session_device_free(sd);
106
107 hashmap_free(s->devices);
108
109 if (s->user) {
110 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
111
112 if (s->user->display == s)
113 s->user->display = NULL;
114 }
115
116 if (s->seat) {
117 if (s->seat->active == s)
118 s->seat->active = NULL;
119 if (s->seat->pending_switch == s)
120 s->seat->pending_switch = NULL;
121
122 seat_evict_position(s->seat, s);
123 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
124 }
125
126 if (s->scope) {
127 hashmap_remove(s->manager->session_units, s->scope);
128 free(s->scope);
129 }
130
131 free(s->scope_job);
132
133 sd_bus_message_unref(s->create_message);
134
135 free(s->tty);
136 free(s->display);
137 free(s->remote_host);
138 free(s->remote_user);
139 free(s->service);
140 free(s->desktop);
141
142 hashmap_remove(s->manager->sessions, s->id);
143
144 free(s->state_file);
145 free(s);
146 }
147
148 void session_set_user(Session *s, User *u) {
149 assert(s);
150 assert(!s->user);
151
152 s->user = u;
153 LIST_PREPEND(sessions_by_user, u->sessions, s);
154 }
155
156 static void session_save_devices(Session *s, FILE *f) {
157 SessionDevice *sd;
158 Iterator i;
159
160 if (!hashmap_isempty(s->devices)) {
161 fprintf(f, "DEVICES=");
162 HASHMAP_FOREACH(sd, s->devices, i)
163 fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev));
164 fprintf(f, "\n");
165 }
166 }
167
168 int session_save(Session *s) {
169 _cleanup_free_ char *temp_path = NULL;
170 _cleanup_fclose_ FILE *f = NULL;
171 int r = 0;
172
173 assert(s);
174
175 if (!s->user)
176 return -ESTALE;
177
178 if (!s->started)
179 return 0;
180
181 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
182 if (r < 0)
183 goto fail;
184
185 r = fopen_temporary(s->state_file, &f, &temp_path);
186 if (r < 0)
187 goto fail;
188
189 assert(s->user);
190
191 fchmod(fileno(f), 0644);
192
193 fprintf(f,
194 "# This is private data. Do not parse.\n"
195 "UID="UID_FMT"\n"
196 "USER=%s\n"
197 "ACTIVE=%i\n"
198 "STATE=%s\n"
199 "REMOTE=%i\n",
200 s->user->uid,
201 s->user->name,
202 session_is_active(s),
203 session_state_to_string(session_get_state(s)),
204 s->remote);
205
206 if (s->type >= 0)
207 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
208
209 if (s->class >= 0)
210 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
211
212 if (s->scope)
213 fprintf(f, "SCOPE=%s\n", s->scope);
214 if (s->scope_job)
215 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
216
217 if (s->fifo_path)
218 fprintf(f, "FIFO=%s\n", s->fifo_path);
219
220 if (s->seat)
221 fprintf(f, "SEAT=%s\n", s->seat->id);
222
223 if (s->tty)
224 fprintf(f, "TTY=%s\n", s->tty);
225
226 if (s->display)
227 fprintf(f, "DISPLAY=%s\n", s->display);
228
229 if (s->remote_host) {
230 _cleanup_free_ char *escaped;
231
232 escaped = cescape(s->remote_host);
233 if (!escaped) {
234 r = -ENOMEM;
235 goto fail;
236 }
237
238 fprintf(f, "REMOTE_HOST=%s\n", escaped);
239 }
240
241 if (s->remote_user) {
242 _cleanup_free_ char *escaped;
243
244 escaped = cescape(s->remote_user);
245 if (!escaped) {
246 r = -ENOMEM;
247 goto fail;
248 }
249
250 fprintf(f, "REMOTE_USER=%s\n", escaped);
251 }
252
253 if (s->service) {
254 _cleanup_free_ char *escaped;
255
256 escaped = cescape(s->service);
257 if (!escaped) {
258 r = -ENOMEM;
259 goto fail;
260 }
261
262 fprintf(f, "SERVICE=%s\n", escaped);
263 }
264
265 if (s->desktop) {
266 _cleanup_free_ char *escaped;
267
268
269 escaped = cescape(s->desktop);
270 if (!escaped) {
271 r = -ENOMEM;
272 goto fail;
273 }
274
275 fprintf(f, "DESKTOP=%s\n", escaped);
276 }
277
278 if (s->seat && seat_has_vts(s->seat))
279 fprintf(f, "VTNR=%u\n", s->vtnr);
280
281 if (!s->vtnr)
282 fprintf(f, "POSITION=%u\n", s->position);
283
284 if (s->leader > 0)
285 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
286
287 if (audit_session_is_valid(s->audit_id))
288 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
289
290 if (dual_timestamp_is_set(&s->timestamp))
291 fprintf(f,
292 "REALTIME="USEC_FMT"\n"
293 "MONOTONIC="USEC_FMT"\n",
294 s->timestamp.realtime,
295 s->timestamp.monotonic);
296
297 if (s->controller) {
298 fprintf(f, "CONTROLLER=%s\n", s->controller);
299 session_save_devices(s, f);
300 }
301
302 r = fflush_and_check(f);
303 if (r < 0)
304 goto fail;
305
306 if (rename(temp_path, s->state_file) < 0) {
307 r = -errno;
308 goto fail;
309 }
310
311 return 0;
312
313 fail:
314 (void) unlink(s->state_file);
315
316 if (temp_path)
317 (void) unlink(temp_path);
318
319 return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
320 }
321
322 static int session_load_devices(Session *s, const char *devices) {
323 const char *p;
324 int r = 0;
325
326 assert(s);
327
328 for (p = devices;;) {
329 _cleanup_free_ char *word = NULL;
330 SessionDevice *sd;
331 dev_t dev;
332 int k;
333
334 k = extract_first_word(&p, &word, NULL, 0);
335 if (k == 0)
336 break;
337 if (k < 0) {
338 r = k;
339 break;
340 }
341
342 k = parse_dev(word, &dev);
343 if (k < 0) {
344 r = k;
345 continue;
346 }
347
348 /* The file descriptors for loaded devices will be reattached later. */
349 k = session_device_new(s, dev, false, &sd);
350 if (k < 0)
351 r = k;
352 }
353
354 if (r < 0)
355 log_error_errno(r, "Loading session devices for session %s failed: %m", s->id);
356
357 return r;
358 }
359
360 int session_load(Session *s) {
361 _cleanup_free_ char *remote = NULL,
362 *seat = NULL,
363 *vtnr = NULL,
364 *state = NULL,
365 *position = NULL,
366 *leader = NULL,
367 *type = NULL,
368 *class = NULL,
369 *uid = NULL,
370 *realtime = NULL,
371 *monotonic = NULL,
372 *controller = NULL,
373 *active = NULL,
374 *devices = NULL;
375
376 int k, r;
377
378 assert(s);
379
380 r = parse_env_file(s->state_file, NEWLINE,
381 "REMOTE", &remote,
382 "SCOPE", &s->scope,
383 "SCOPE_JOB", &s->scope_job,
384 "FIFO", &s->fifo_path,
385 "SEAT", &seat,
386 "TTY", &s->tty,
387 "DISPLAY", &s->display,
388 "REMOTE_HOST", &s->remote_host,
389 "REMOTE_USER", &s->remote_user,
390 "SERVICE", &s->service,
391 "DESKTOP", &s->desktop,
392 "VTNR", &vtnr,
393 "STATE", &state,
394 "POSITION", &position,
395 "LEADER", &leader,
396 "TYPE", &type,
397 "CLASS", &class,
398 "UID", &uid,
399 "REALTIME", &realtime,
400 "MONOTONIC", &monotonic,
401 "CONTROLLER", &controller,
402 "ACTIVE", &active,
403 "DEVICES", &devices,
404 NULL);
405
406 if (r < 0)
407 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
408
409 if (!s->user) {
410 uid_t u;
411 User *user;
412
413 if (!uid) {
414 log_error("UID not specified for session %s", s->id);
415 return -ENOENT;
416 }
417
418 r = parse_uid(uid, &u);
419 if (r < 0) {
420 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
421 return r;
422 }
423
424 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
425 if (!user) {
426 log_error("User of session %s not known.", s->id);
427 return -ENOENT;
428 }
429
430 session_set_user(s, user);
431 }
432
433 if (remote) {
434 k = parse_boolean(remote);
435 if (k >= 0)
436 s->remote = k;
437 }
438
439 if (vtnr)
440 safe_atou(vtnr, &s->vtnr);
441
442 if (seat && !s->seat) {
443 Seat *o;
444
445 o = hashmap_get(s->manager->seats, seat);
446 if (o)
447 r = seat_attach_session(o, s);
448 if (!o || r < 0)
449 log_error("Cannot attach session %s to seat %s", s->id, seat);
450 }
451
452 if (!s->seat || !seat_has_vts(s->seat))
453 s->vtnr = 0;
454
455 if (position && s->seat) {
456 unsigned int npos;
457
458 safe_atou(position, &npos);
459 seat_claim_position(s->seat, s, npos);
460 }
461
462 if (leader) {
463 if (parse_pid(leader, &s->leader) >= 0)
464 (void) 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);