chiark / gitweb /
sd-rtnl: fix self-reference leaks
[elogind.git] / src / login / logind-session.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <linux/vt.h>
25 #include <linux/kd.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <sys/ioctl.h>
29 #include <unistd.h>
30
31 #include "sd-id128.h"
32 #include "sd-messages.h"
33 #include "strv.h"
34 #include "util.h"
35 #include "mkdir.h"
36 #include "path-util.h"
37 #include "fileio.h"
38 #include "audit.h"
39 #include "bus-util.h"
40 #include "bus-error.h"
41 #include "logind-session.h"
42
43 #define RELEASE_USEC (20*USEC_PER_SEC)
44
45 static void session_remove_fifo(Session *s);
46
47 static unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
48         uint64_t u = *(const dev_t*)p;
49
50         return uint64_hash_func(&u, hash_key);
51 }
52
53 static int devt_compare_func(const void *_a, const void *_b) {
54         dev_t a, b;
55
56         a = *(const dev_t*) _a;
57         b = *(const dev_t*) _b;
58
59         return a < b ? -1 : (a > b ? 1 : 0);
60 }
61
62 Session* session_new(Manager *m, const char *id) {
63         Session *s;
64
65         assert(m);
66         assert(id);
67         assert(session_id_valid(id));
68
69         s = new0(Session, 1);
70         if (!s)
71                 return NULL;
72
73         s->state_file = strappend("/run/systemd/sessions/", id);
74         if (!s->state_file) {
75                 free(s);
76                 return NULL;
77         }
78
79         s->devices = hashmap_new(devt_hash_func, devt_compare_func);
80         if (!s->devices) {
81                 free(s->state_file);
82                 free(s);
83                 return NULL;
84         }
85
86         s->id = basename(s->state_file);
87
88         if (hashmap_put(m->sessions, s->id, s) < 0) {
89                 hashmap_free(s->devices);
90                 free(s->state_file);
91                 free(s);
92                 return NULL;
93         }
94
95         s->manager = m;
96         s->fifo_fd = -1;
97         s->vtfd = -1;
98
99         return s;
100 }
101
102 void session_free(Session *s) {
103         SessionDevice *sd;
104
105         assert(s);
106
107         if (s->in_gc_queue)
108                 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
109
110         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
111
112         session_remove_fifo(s);
113
114         session_drop_controller(s);
115
116         while ((sd = hashmap_first(s->devices)))
117                 session_device_free(sd);
118
119         hashmap_free(s->devices);
120
121         if (s->user) {
122                 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
123
124                 if (s->user->display == s)
125                         s->user->display = NULL;
126         }
127
128         if (s->seat) {
129                 if (s->seat->active == s)
130                         s->seat->active = NULL;
131                 if (s->seat->pending_switch == s)
132                         s->seat->pending_switch = NULL;
133
134                 seat_evict_position(s->seat, s);
135                 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
136         }
137
138         if (s->scope) {
139                 hashmap_remove(s->manager->session_units, s->scope);
140                 free(s->scope);
141         }
142
143         free(s->scope_job);
144
145         sd_bus_message_unref(s->create_message);
146
147         free(s->tty);
148         free(s->display);
149         free(s->remote_host);
150         free(s->remote_user);
151         free(s->service);
152         free(s->desktop);
153
154         hashmap_remove(s->manager->sessions, s->id);
155
156         s->vt_source = sd_event_source_unref(s->vt_source);
157
158         free(s->state_file);
159         free(s);
160 }
161
162 void session_set_user(Session *s, User *u) {
163         assert(s);
164         assert(!s->user);
165
166         s->user = u;
167         LIST_PREPEND(sessions_by_user, u->sessions, s);
168 }
169
170 int session_save(Session *s) {
171         _cleanup_free_ char *temp_path = NULL;
172         _cleanup_fclose_ FILE *f = NULL;
173         int r = 0;
174
175         assert(s);
176
177         if (!s->user)
178                 return -ESTALE;
179
180         if (!s->started)
181                 return 0;
182
183         r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
184         if (r < 0)
185                 goto finish;
186
187         r = fopen_temporary(s->state_file, &f, &temp_path);
188         if (r < 0)
189                 goto finish;
190
191         assert(s->user);
192
193         fchmod(fileno(f), 0644);
194
195         fprintf(f,
196                 "# This is private data. Do not parse.\n"
197                 "UID="UID_FMT"\n"
198                 "USER=%s\n"
199                 "ACTIVE=%i\n"
200                 "STATE=%s\n"
201                 "REMOTE=%i\n",
202                 s->user->uid,
203                 s->user->name,
204                 session_is_active(s),
205                 session_state_to_string(session_get_state(s)),
206                 s->remote);
207
208         if (s->type >= 0)
209                 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
210
211         if (s->class >= 0)
212                 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
213
214         if (s->scope)
215                 fprintf(f, "SCOPE=%s\n", s->scope);
216
217         if (s->scope_job)
218                 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
219
220         if (s->fifo_path)
221                 fprintf(f, "FIFO=%s\n", s->fifo_path);
222
223         if (s->seat)
224                 fprintf(f, "SEAT=%s\n", s->seat->id);
225
226         if (s->tty)
227                 fprintf(f, "TTY=%s\n", s->tty);
228
229         if (s->display)
230                 fprintf(f, "DISPLAY=%s\n", s->display);
231
232         if (s->remote_host)
233                 fprintf(f, "REMOTE_HOST=%s\n", s->remote_host);
234
235         if (s->remote_user)
236                 fprintf(f, "REMOTE_USER=%s\n", s->remote_user);
237
238         if (s->service)
239                 fprintf(f, "SERVICE=%s\n", s->service);
240
241         if (s->desktop)
242                 fprintf(f, "DESKTOP=%s\n", s->desktop);
243
244         if (s->seat && seat_has_vts(s->seat))
245                 fprintf(f, "VTNR=%u\n", s->vtnr);
246
247         if (!s->vtnr)
248                 fprintf(f, "POS=%u\n", s->pos);
249
250         if (s->leader > 0)
251                 fprintf(f, "LEADER="PID_FMT"\n", s->leader);
252
253         if (s->audit_id > 0)
254                 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
255
256         if (dual_timestamp_is_set(&s->timestamp))
257                 fprintf(f,
258                         "REALTIME="USEC_FMT"\n"
259                         "MONOTONIC="USEC_FMT"\n",
260                         s->timestamp.realtime,
261                         s->timestamp.monotonic);
262
263         if (s->controller)
264                 fprintf(f, "CONTROLLER=%s\n", s->controller);
265
266         fflush(f);
267
268         if (ferror(f) || rename(temp_path, s->state_file) < 0) {
269                 r = -errno;
270                 unlink(s->state_file);
271                 unlink(temp_path);
272         }
273
274 finish:
275         if (r < 0)
276                 log_error("Failed to save session data %s: %s", s->state_file, strerror(-r));
277
278         return r;
279 }
280
281 int session_load(Session *s) {
282         _cleanup_free_ char *remote = NULL,
283                 *seat = NULL,
284                 *vtnr = NULL,
285                 *pos = NULL,
286                 *leader = NULL,
287                 *type = NULL,
288                 *class = NULL,
289                 *uid = NULL,
290                 *realtime = NULL,
291                 *monotonic = NULL,
292                 *controller = NULL;
293
294         int k, r;
295
296         assert(s);
297
298         r = parse_env_file(s->state_file, NEWLINE,
299                            "REMOTE",         &remote,
300                            "SCOPE",          &s->scope,
301                            "SCOPE_JOB",      &s->scope_job,
302                            "FIFO",           &s->fifo_path,
303                            "SEAT",           &seat,
304                            "TTY",            &s->tty,
305                            "DISPLAY",        &s->display,
306                            "REMOTE_HOST",    &s->remote_host,
307                            "REMOTE_USER",    &s->remote_user,
308                            "SERVICE",        &s->service,
309                            "DESKTOP",        &s->desktop,
310                            "VTNR",           &vtnr,
311                            "POS",            &pos,
312                            "LEADER",         &leader,
313                            "TYPE",           &type,
314                            "CLASS",          &class,
315                            "UID",            &uid,
316                            "REALTIME",       &realtime,
317                            "MONOTONIC",      &monotonic,
318                            "CONTROLLER",     &controller,
319                            NULL);
320
321         if (r < 0) {
322                 log_error("Failed to read %s: %s", s->state_file, strerror(-r));
323                 return r;
324         }
325
326         if (!s->user) {
327                 uid_t u;
328                 User *user;
329
330                 if (!uid) {
331                         log_error("UID not specified for session %s", s->id);
332                         return -ENOENT;
333                 }
334
335                 r = parse_uid(uid, &u);
336                 if (r < 0)  {
337                         log_error("Failed to parse UID value %s for session %s.", uid, s->id);
338                         return r;
339                 }
340
341                 user = hashmap_get(s->manager->users, ULONG_TO_PTR((unsigned long) u));
342                 if (!user) {
343                         log_error("User of session %s not known.", s->id);
344                         return -ENOENT;
345                 }
346
347                 session_set_user(s, user);
348         }
349
350         if (remote) {
351                 k = parse_boolean(remote);
352                 if (k >= 0)
353                         s->remote = k;
354         }
355
356         if (vtnr)
357                 safe_atou(vtnr, &s->vtnr);
358
359         if (seat && !s->seat) {
360                 Seat *o;
361
362                 o = hashmap_get(s->manager->seats, seat);
363                 if (o)
364                         r = seat_attach_session(o, s);
365                 if (!o || r < 0)
366                         log_error("Cannot attach session %s to seat %s", s->id, seat);
367         }
368
369         if (!s->seat || !seat_has_vts(s->seat))
370                 s->vtnr = 0;
371
372         if (pos && s->seat) {
373                 unsigned int npos;
374
375                 safe_atou(pos, &npos);
376                 seat_claim_position(s->seat, s, npos);
377         }
378
379         if (leader) {
380                 k = parse_pid(leader, &s->leader);
381                 if (k >= 0)
382                         audit_session_from_pid(s->leader, &s->audit_id);
383         }
384
385         if (type) {
386                 SessionType t;
387
388                 t = session_type_from_string(type);
389                 if (t >= 0)
390                         s->type = t;
391         }
392
393         if (class) {
394                 SessionClass c;
395
396                 c = session_class_from_string(class);
397                 if (c >= 0)
398                         s->class = c;
399         }
400
401         if (s->fifo_path) {
402                 int fd;
403
404                 /* If we open an unopened pipe for reading we will not
405                    get an EOF. to trigger an EOF we hence open it for
406                    reading, but close it right-away which then will
407                    trigger the EOF. */
408
409                 fd = session_create_fifo(s);
410                 safe_close(fd);
411         }
412
413         if (realtime) {
414                 unsigned long long l;
415                 if (sscanf(realtime, "%llu", &l) > 0)
416                         s->timestamp.realtime = l;
417         }
418
419         if (monotonic) {
420                 unsigned long long l;
421                 if (sscanf(monotonic, "%llu", &l) > 0)
422                         s->timestamp.monotonic = l;
423         }
424
425         if (controller) {
426                 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0)
427                         session_set_controller(s, controller, false);
428                 else
429                         session_restore_vt(s);
430         }
431
432         return r;
433 }
434
435 int session_activate(Session *s) {
436         unsigned int num_pending;
437
438         assert(s);
439         assert(s->user);
440
441         if (!s->seat)
442                 return -ENOTSUP;
443
444         if (s->seat->active == s)
445                 return 0;
446
447         /* on seats with VTs, we let VTs manage session-switching */
448         if (seat_has_vts(s->seat)) {
449                 if (!s->vtnr)
450                         return -ENOTSUP;
451
452                 return chvt(s->vtnr);
453         }
454
455         /* On seats without VTs, we implement session-switching in logind. We
456          * try to pause all session-devices and wait until the session
457          * controller acknowledged them. Once all devices are asleep, we simply
458          * switch the active session and be done.
459          * We save the session we want to switch to in seat->pending_switch and
460          * seat_complete_switch() will perform the final switch. */
461
462         s->seat->pending_switch = s;
463
464         /* if no devices are running, immediately perform the session switch */
465         num_pending = session_device_try_pause_all(s);
466         if (!num_pending)
467                 seat_complete_switch(s->seat);
468
469         return 0;
470 }
471
472 static int session_start_scope(Session *s) {
473         int r;
474
475         assert(s);
476         assert(s->user);
477         assert(s->user->slice);
478
479         if (!s->scope) {
480                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
481                 _cleanup_free_ char *description = NULL;
482                 char *scope, *job = NULL;
483
484                 description = strjoin("Session ", s->id, " of user ", s->user->name, NULL);
485                 if (!description)
486                         return log_oom();
487
488                 scope = strjoin("session-", s->id, ".scope", NULL);
489                 if (!scope)
490                         return log_oom();
491
492                 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "systemd-logind.service", "systemd-user-sessions.service", &error, &job);
493                 if (r < 0) {
494                         log_error("Failed to start session scope %s: %s %s",
495                                   scope, bus_error_message(&error, r), error.name);
496                         free(scope);
497                         return r;
498                 } else {
499                         s->scope = scope;
500
501                         free(s->scope_job);
502                         s->scope_job = job;
503                 }
504         }
505
506         if (s->scope)
507                 hashmap_put(s->manager->session_units, s->scope, s);
508
509         return 0;
510 }
511
512 int session_start(Session *s) {
513         int r;
514
515         assert(s);
516
517         if (!s->user)
518                 return -ESTALE;
519
520         if (s->started)
521                 return 0;
522
523         r = user_start(s->user);
524         if (r < 0)
525                 return r;
526
527         /* Create cgroup */
528         r = session_start_scope(s);
529         if (r < 0)
530                 return r;
531
532         log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
533                    MESSAGE_ID(SD_MESSAGE_SESSION_START),
534                    "SESSION_ID=%s", s->id,
535                    "USER_ID=%s", s->user->name,
536                    "LEADER=%lu", (unsigned long) s->leader,
537                    "MESSAGE=New session %s of user %s.", s->id, s->user->name,
538                    NULL);
539
540         if (!dual_timestamp_is_set(&s->timestamp))
541                 dual_timestamp_get(&s->timestamp);
542
543         if (s->seat)
544                 seat_read_active_vt(s->seat);
545
546         s->started = true;
547
548         /* Save data */
549         session_save(s);
550         user_save(s->user);
551         if (s->seat)
552                 seat_save(s->seat);
553
554         /* Send signals */
555         session_send_signal(s, true);
556         user_send_changed(s->user, "Sessions", NULL);
557         if (s->seat) {
558                 if (s->seat->active == s)
559                         seat_send_changed(s->seat, "Sessions", "ActiveSession", NULL);
560                 else
561                         seat_send_changed(s->seat, "Sessions", NULL);
562         }
563
564         return 0;
565 }
566
567 static int session_stop_scope(Session *s, bool force) {
568         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
569         char *job = NULL;
570         int r;
571
572         assert(s);
573
574         if (!s->scope)
575                 return 0;
576
577         if (force || manager_shall_kill(s->manager, s->user->name)) {
578                 r = manager_stop_unit(s->manager, s->scope, &error, &job);
579                 if (r < 0) {
580                         log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
581                         return r;
582                 }
583
584                 free(s->scope_job);
585                 s->scope_job = job;
586         } else {
587                 r = manager_abandon_scope(s->manager, s->scope, &error);
588                 if (r < 0) {
589                         log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
590                         return r;
591                 }
592         }
593
594         return 0;
595 }
596
597 int session_stop(Session *s, bool force) {
598         int r;
599
600         assert(s);
601
602         if (!s->user)
603                 return -ESTALE;
604
605         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
606
607         /* We are going down, don't care about FIFOs anymore */
608         session_remove_fifo(s);
609
610         /* Kill cgroup */
611         r = session_stop_scope(s, force);
612
613         s->stopping = true;
614
615         session_save(s);
616         user_save(s->user);
617
618         return r;
619 }
620
621 int session_finalize(Session *s) {
622         int r = 0;
623         SessionDevice *sd;
624
625         assert(s);
626
627         if (!s->user)
628                 return -ESTALE;
629
630         if (s->started)
631                 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
632                            MESSAGE_ID(SD_MESSAGE_SESSION_STOP),
633                            "SESSION_ID=%s", s->id,
634                            "USER_ID=%s", s->user->name,
635                            "LEADER=%lu", (unsigned long) s->leader,
636                            "MESSAGE=Removed session %s.", s->id,
637                            NULL);
638
639         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
640
641         /* Kill session devices */
642         while ((sd = hashmap_first(s->devices)))
643                 session_device_free(sd);
644
645         unlink(s->state_file);
646         session_add_to_gc_queue(s);
647         user_add_to_gc_queue(s->user);
648
649         if (s->started) {
650                 session_send_signal(s, false);
651                 s->started = false;
652         }
653
654         if (s->seat) {
655                 if (s->seat->active == s)
656                         seat_set_active(s->seat, NULL);
657
658                 seat_save(s->seat);
659                 seat_send_changed(s->seat, "Sessions", NULL);
660         }
661
662         user_save(s->user);
663         user_send_changed(s->user, "Sessions", NULL);
664
665         return r;
666 }
667
668 static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
669         Session *s = userdata;
670
671         assert(es);
672         assert(s);
673
674         session_stop(s, false);
675         return 0;
676 }
677
678 void session_release(Session *s) {
679         assert(s);
680
681         if (!s->started || s->stopping)
682                 return;
683
684         if (!s->timer_event_source)
685                 sd_event_add_monotonic(s->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s);
686 }
687
688 bool session_is_active(Session *s) {
689         assert(s);
690
691         if (!s->seat)
692                 return true;
693
694         return s->seat->active == s;
695 }
696
697 static int get_tty_atime(const char *tty, usec_t *atime) {
698         _cleanup_free_ char *p = NULL;
699         struct stat st;
700
701         assert(tty);
702         assert(atime);
703
704         if (!path_is_absolute(tty)) {
705                 p = strappend("/dev/", tty);
706                 if (!p)
707                         return -ENOMEM;
708
709                 tty = p;
710         } else if (!path_startswith(tty, "/dev/"))
711                 return -ENOENT;
712
713         if (lstat(tty, &st) < 0)
714                 return -errno;
715
716         *atime = timespec_load(&st.st_atim);
717         return 0;
718 }
719
720 static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
721         _cleanup_free_ char *p = NULL;
722         int r;
723
724         assert(pid > 0);
725         assert(atime);
726
727         r = get_ctty(pid, NULL, &p);
728         if (r < 0)
729                 return r;
730
731         return get_tty_atime(p, atime);
732 }
733
734 int session_get_idle_hint(Session *s, dual_timestamp *t) {
735         usec_t atime = 0, n;
736         int r;
737
738         assert(s);
739
740         /* Explicit idle hint is set */
741         if (s->idle_hint) {
742                 if (t)
743                         *t = s->idle_hint_timestamp;
744
745                 return s->idle_hint;
746         }
747
748         /* Graphical sessions should really implement a real
749          * idle hint logic */
750         if (s->display)
751                 goto dont_know;
752
753         /* For sessions with an explicitly configured tty, let's check
754          * its atime */
755         if (s->tty) {
756                 r = get_tty_atime(s->tty, &atime);
757                 if (r >= 0)
758                         goto found_atime;
759         }
760
761         /* For sessions with a leader but no explicitly configured
762          * tty, let's check the controlling tty of the leader */
763         if (s->leader > 0) {
764                 r = get_process_ctty_atime(s->leader, &atime);
765                 if (r >= 0)
766                         goto found_atime;
767         }
768
769 dont_know:
770         if (t)
771                 *t = s->idle_hint_timestamp;
772
773         return 0;
774
775 found_atime:
776         if (t)
777                 dual_timestamp_from_realtime(t, atime);
778
779         n = now(CLOCK_REALTIME);
780
781         if (s->manager->idle_action_usec <= 0)
782                 return 0;
783
784         return atime + s->manager->idle_action_usec <= n;
785 }
786
787 void session_set_idle_hint(Session *s, bool b) {
788         assert(s);
789
790         if (s->idle_hint == b)
791                 return;
792
793         s->idle_hint = b;
794         dual_timestamp_get(&s->idle_hint_timestamp);
795
796         session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
797
798         if (s->seat)
799                 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
800
801         user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
802         manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
803 }
804
805 static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
806         Session *s = userdata;
807
808         assert(s);
809         assert(s->fifo_fd == fd);
810
811         /* EOF on the FIFO means the session died abnormally. */
812
813         session_remove_fifo(s);
814         session_stop(s, false);
815
816         return 1;
817 }
818
819 int session_create_fifo(Session *s) {
820         int r;
821
822         assert(s);
823
824         /* Create FIFO */
825         if (!s->fifo_path) {
826                 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0);
827                 if (r < 0)
828                         return r;
829
830                 if (asprintf(&s->fifo_path, "/run/systemd/sessions/%s.ref", s->id) < 0)
831                         return -ENOMEM;
832
833                 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
834                         return -errno;
835         }
836
837         /* Open reading side */
838         if (s->fifo_fd < 0) {
839                 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY);
840                 if (s->fifo_fd < 0)
841                         return -errno;
842
843         }
844
845         if (!s->fifo_event_source) {
846                 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
847                 if (r < 0)
848                         return r;
849
850                 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
851                 if (r < 0)
852                         return r;
853         }
854
855         /* Open writing side */
856         r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NDELAY);
857         if (r < 0)
858                 return -errno;
859
860         return r;
861 }
862
863 static void session_remove_fifo(Session *s) {
864         assert(s);
865
866         s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
867         s->fifo_fd = safe_close(s->fifo_fd);
868
869         if (s->fifo_path) {
870                 unlink(s->fifo_path);
871                 free(s->fifo_path);
872                 s->fifo_path = NULL;
873         }
874 }
875
876 bool session_check_gc(Session *s, bool drop_not_started) {
877         assert(s);
878
879         if (drop_not_started && !s->started)
880                 return false;
881
882         if (!s->user)
883                 return false;
884
885         if (s->fifo_fd >= 0) {
886                 if (pipe_eof(s->fifo_fd) <= 0)
887                         return true;
888         }
889
890         if (s->scope_job && manager_job_is_active(s->manager, s->scope_job))
891                 return true;
892
893         if (s->scope && manager_unit_is_active(s->manager, s->scope))
894                 return true;
895
896         return false;
897 }
898
899 void session_add_to_gc_queue(Session *s) {
900         assert(s);
901
902         if (s->in_gc_queue)
903                 return;
904
905         LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
906         s->in_gc_queue = true;
907 }
908
909 SessionState session_get_state(Session *s) {
910         assert(s);
911
912         /* always check closing first */
913         if (s->stopping || s->timer_event_source)
914                 return SESSION_CLOSING;
915
916         if (s->scope_job || s->fifo_fd < 0)
917                 return SESSION_OPENING;
918
919         if (session_is_active(s))
920                 return SESSION_ACTIVE;
921
922         return SESSION_ONLINE;
923 }
924
925 int session_kill(Session *s, KillWho who, int signo) {
926         assert(s);
927
928         if (!s->scope)
929                 return -ESRCH;
930
931         return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
932 }
933
934 static int session_open_vt(Session *s) {
935         char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
936
937         if (!s->vtnr)
938                 return -1;
939
940         if (s->vtfd >= 0)
941                 return s->vtfd;
942
943         sprintf(path, "/dev/tty%u", s->vtnr);
944         s->vtfd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
945         if (s->vtfd < 0) {
946                 log_error("cannot open VT %s of session %s: %m", path, s->id);
947                 return -errno;
948         }
949
950         return s->vtfd;
951 }
952
953 static int session_vt_fn(sd_event_source *source, const struct signalfd_siginfo *si, void *data) {
954         Session *s = data;
955
956         if (s->vtfd >= 0)
957                 ioctl(s->vtfd, VT_RELDISP, 1);
958
959         return 0;
960 }
961
962 void session_mute_vt(Session *s) {
963         int vt, r;
964         struct vt_mode mode = { 0 };
965         sigset_t mask;
966
967         vt = session_open_vt(s);
968         if (vt < 0)
969                 return;
970
971         r = ioctl(vt, KDSKBMODE, K_OFF);
972         if (r < 0)
973                 goto error;
974
975         r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
976         if (r < 0)
977                 goto error;
978
979         sigemptyset(&mask);
980         sigaddset(&mask, SIGUSR1);
981         sigprocmask(SIG_BLOCK, &mask, NULL);
982
983         r = sd_event_add_signal(s->manager->event, &s->vt_source, SIGUSR1, session_vt_fn, s);
984         if (r < 0)
985                 goto error;
986
987         /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
988          * So we need a dummy handler here which just acknowledges *all* VT
989          * switch requests. */
990         mode.mode = VT_PROCESS;
991         mode.relsig = SIGUSR1;
992         mode.acqsig = SIGUSR1;
993         r = ioctl(vt, VT_SETMODE, &mode);
994         if (r < 0)
995                 goto error;
996
997         return;
998
999 error:
1000         log_error("cannot mute VT %u for session %s (%d/%d)", s->vtnr, s->id, r, errno);
1001         session_restore_vt(s);
1002 }
1003
1004 void session_restore_vt(Session *s) {
1005         _cleanup_free_ char *utf8 = NULL;
1006         int vt, kb = K_XLATE;
1007         struct vt_mode mode = { 0 };
1008
1009         vt = session_open_vt(s);
1010         if (vt < 0)
1011                 return;
1012
1013         s->vt_source = sd_event_source_unref(s->vt_source);
1014
1015         ioctl(vt, KDSETMODE, KD_TEXT);
1016
1017         if (read_one_line_file("/sys/module/vt/parameters/default_utf8", &utf8) >= 0 && *utf8 == '1')
1018                 kb = K_UNICODE;
1019
1020         ioctl(vt, KDSKBMODE, kb);
1021
1022         mode.mode = VT_AUTO;
1023         ioctl(vt, VT_SETMODE, &mode);
1024
1025         s->vtfd = safe_close(s->vtfd);
1026 }
1027
1028 bool session_is_controller(Session *s, const char *sender) {
1029         assert(s);
1030
1031         return streq_ptr(s->controller, sender);
1032 }
1033
1034 static void session_swap_controller(Session *s, char *name) {
1035         SessionDevice *sd;
1036
1037         if (s->controller) {
1038                 manager_drop_busname(s->manager, s->controller);
1039                 free(s->controller);
1040                 s->controller = NULL;
1041
1042                 /* Drop all devices as they're now unused. Do that after the
1043                  * controller is released to avoid sending out useles
1044                  * dbus signals. */
1045                 while ((sd = hashmap_first(s->devices)))
1046                         session_device_free(sd);
1047
1048                 if (!name)
1049                         session_restore_vt(s);
1050         }
1051
1052         s->controller = name;
1053         session_save(s);
1054 }
1055
1056 int session_set_controller(Session *s, const char *sender, bool force) {
1057         char *t;
1058         int r;
1059
1060         assert(s);
1061         assert(sender);
1062
1063         if (session_is_controller(s, sender))
1064                 return 0;
1065         if (s->controller && !force)
1066                 return -EBUSY;
1067
1068         t = strdup(sender);
1069         if (!t)
1070                 return -ENOMEM;
1071
1072         r = manager_watch_busname(s->manager, sender);
1073         if (r) {
1074                 free(t);
1075                 return r;
1076         }
1077
1078         session_swap_controller(s, t);
1079
1080         /* When setting a session controller, we forcibly mute the VT and set
1081          * it into graphics-mode. Applications can override that by changing
1082          * VT state after calling TakeControl(). However, this serves as a good
1083          * default and well-behaving controllers can now ignore VTs entirely.
1084          * Note that we reset the VT on ReleaseControl() and if the controller
1085          * exits.
1086          * If logind crashes/restarts, we restore the controller during restart
1087          * or reset the VT in case it crashed/exited, too. */
1088         session_mute_vt(s);
1089
1090         return 0;
1091 }
1092
1093 void session_drop_controller(Session *s) {
1094         assert(s);
1095
1096         if (!s->controller)
1097                 return;
1098
1099         session_swap_controller(s, NULL);
1100 }
1101
1102 static const char* const session_state_table[_SESSION_STATE_MAX] = {
1103         [SESSION_OPENING] = "opening",
1104         [SESSION_ONLINE] = "online",
1105         [SESSION_ACTIVE] = "active",
1106         [SESSION_CLOSING] = "closing"
1107 };
1108
1109 DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1110
1111 static const char* const session_type_table[_SESSION_TYPE_MAX] = {
1112         [SESSION_UNSPECIFIED] = "unspecified",
1113         [SESSION_TTY] = "tty",
1114         [SESSION_X11] = "x11",
1115         [SESSION_WAYLAND] = "wayland",
1116 };
1117
1118 DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
1119
1120 static const char* const session_class_table[_SESSION_CLASS_MAX] = {
1121         [SESSION_USER] = "user",
1122         [SESSION_GREETER] = "greeter",
1123         [SESSION_LOCK_SCREEN] = "lock-screen",
1124         [SESSION_BACKGROUND] = "background"
1125 };
1126
1127 DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1128
1129 static const char* const kill_who_table[_KILL_WHO_MAX] = {
1130         [KILL_LEADER] = "leader",
1131         [KILL_ALL] = "all"
1132 };
1133
1134 DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);