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