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