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