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