]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-session.c
json: drop redundant check
[thirdparty/systemd.git] / src / login / logind-session.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
20263082
LP
2
3#include <errno.h>
90a18413 4#include <fcntl.h>
90a18413 5#include <linux/kd.h>
4f5dd394 6#include <linux/vt.h>
90a18413 7#include <signal.h>
90a18413 8#include <sys/ioctl.h>
ca78ad1d 9#include <sys/stat.h>
20263082
LP
10#include <unistd.h>
11
cc377381 12#include "sd-messages.h"
4f5dd394 13
b5efdb8a 14#include "alloc-util.h"
430f0182 15#include "audit-util.h"
cc377381 16#include "bus-error.h"
4f5dd394 17#include "bus-util.h"
9d5b6901 18#include "daemon-util.h"
7176f06c 19#include "devnum-util.h"
686d13b9 20#include "env-file.h"
4f5dd394 21#include "escape.h"
3ffd4af2 22#include "fd-util.h"
4f5dd394 23#include "fileio.h"
f97b34a6 24#include "format-util.h"
70f1280c 25#include "fs-util.h"
c004493c 26#include "io-util.h"
6ecda0fb
LP
27#include "logind-dbus.h"
28#include "logind-seat-dbus.h"
29#include "logind-session-dbus.h"
3ffd4af2 30#include "logind-session.h"
6ecda0fb 31#include "logind-user-dbus.h"
35cd0ba5 32#include "mkdir-label.h"
6bedfcbb 33#include "parse-util.h"
4f5dd394 34#include "path-util.h"
8c29a457 35#include "process-util.h"
d68c645b 36#include "serialize.h"
8b43440b 37#include "string-table.h"
25a1ab4e 38#include "strv.h"
288a74cc 39#include "terminal-util.h"
e4de7287 40#include "tmpfile-util.h"
278e815b 41#include "uid-alloc-range.h"
b1d4f8e1 42#include "user-util.h"
20263082 43
5f41d1f1
LP
44#define RELEASE_USEC (20*USEC_PER_SEC)
45
46static void session_remove_fifo(Session *s);
0212126c 47static void session_restore_vt(Session *s);
5f41d1f1 48
8c29a457
LP
49int session_new(Session **ret, Manager *m, const char *id) {
50 _cleanup_(session_freep) Session *s = NULL;
51 int r;
20263082 52
8c29a457 53 assert(ret);
20263082
LP
54 assert(m);
55 assert(id);
56
8c29a457
LP
57 if (!session_id_valid(id))
58 return -EINVAL;
59
60 s = new(Session, 1);
20263082 61 if (!s)
8c29a457
LP
62 return -ENOMEM;
63
64 *s = (Session) {
65 .manager = m,
254d1313
ZJS
66 .fifo_fd = -EBADF,
67 .vtfd = -EBADF,
8c29a457 68 .audit_id = AUDIT_SESSION_INVALID,
3d0ef5c7 69 .tty_validity = _TTY_VALIDITY_INVALID,
89bad70f 70 .leader = PIDREF_NULL,
8c29a457 71 };
20263082 72
b910cc72 73 s->state_file = path_join("/run/systemd/sessions", id);
6b430fdb 74 if (!s->state_file)
8c29a457 75 return -ENOMEM;
118ecf32 76
2b6bf07d 77 s->id = basename(s->state_file);
20263082 78
8c29a457
LP
79 s->devices = hashmap_new(&devt_hash_ops);
80 if (!s->devices)
81 return -ENOMEM;
20263082 82
8c29a457
LP
83 r = hashmap_put(m->sessions, s->id, s);
84 if (r < 0)
85 return r;
20263082 86
8c29a457
LP
87 *ret = TAKE_PTR(s);
88 return 0;
20263082
LP
89}
90
0ae9073f
MY
91static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
92 Session *s = ASSERT_PTR(userdata);
93
94 assert(s->leader.fd == fd);
95 session_stop(s, /* force= */ false);
96
97 return 1;
98}
99
100static int session_watch_pidfd(Session *s) {
101 int r;
102
103 assert(s);
104 assert(s->manager);
105 assert(pidref_is_set(&s->leader));
106
107 if (s->leader.fd < 0)
108 return 0;
109
110 r = sd_event_add_io(s->manager->event, &s->leader_pidfd_event_source, s->leader.fd, EPOLLIN, session_dispatch_leader_pidfd, s);
111 if (r < 0)
112 return r;
113
114 r = sd_event_source_set_priority(s->leader_pidfd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
115 if (r < 0)
116 return r;
117
118 (void) sd_event_source_set_description(s->leader_pidfd_event_source, "session-pidfd");
119
120 return 0;
121}
122
9d5b6901 123static void session_reset_leader(Session *s, bool keep_fdstore) {
8494f562
MY
124 assert(s);
125
9d5b6901
MY
126 if (!keep_fdstore) {
127 /* Clear fdstore if we're asked to, no matter if s->leader is set or not, so that when
128 * initially deserializing leader fd we clear the old fd too. */
129 (void) notify_remove_fd_warnf("session-%s-leader-fd", s->id);
130 s->leader_fd_saved = false;
131 }
132
8494f562
MY
133 if (!pidref_is_set(&s->leader))
134 return;
135
0ae9073f
MY
136 s->leader_pidfd_event_source = sd_event_source_disable_unref(s->leader_pidfd_event_source);
137
889975bb 138 (void) hashmap_remove_value(s->manager->sessions_by_leader, &s->leader, s);
8494f562
MY
139
140 return pidref_done(&s->leader);
141}
142
8c29a457 143Session* session_free(Session *s) {
118ecf32
DH
144 SessionDevice *sd;
145
8c29a457
LP
146 if (!s)
147 return NULL;
20263082 148
14c3baca 149 if (s->in_gc_queue)
71fda00f 150 LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
14c3baca 151
5f41d1f1
LP
152 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
153
ae5e06bd
DH
154 session_drop_controller(s);
155
118ecf32
DH
156 while ((sd = hashmap_first(s->devices)))
157 session_device_free(sd);
158
159 hashmap_free(s->devices);
160
20263082 161 if (s->user) {
71fda00f 162 LIST_REMOVE(sessions_by_user, s->user->sessions, s);
20263082
LP
163
164 if (s->user->display == s)
165 s->user->display = NULL;
9afe9efb
LP
166
167 user_update_last_session_timer(s->user);
20263082
LP
168 }
169
9418f147
LP
170 if (s->seat) {
171 if (s->seat->active == s)
172 s->seat->active = NULL;
d7bd01b5
DH
173 if (s->seat->pending_switch == s)
174 s->seat->pending_switch = NULL;
9418f147 175
49e6fdbf 176 seat_evict_position(s->seat, s);
71fda00f 177 LIST_REMOVE(sessions_by_seat, s->seat->sessions, s);
9418f147 178 }
20263082 179
fb6becb4
LP
180 if (s->scope) {
181 hashmap_remove(s->manager->session_units, s->scope);
182 free(s->scope);
183 }
184
185 free(s->scope_job);
1713813d 186
9d5b6901 187 session_reset_leader(s, /* keep_fdstore = */ true);
8494f562 188
cc377381 189 sd_bus_message_unref(s->create_message);
20263082
LP
190
191 free(s->tty);
192 free(s->display);
193 free(s->remote_host);
3f49d45a 194 free(s->remote_user);
98a28fef 195 free(s->service);
a4cd87e9 196 free(s->desktop);
20263082
LP
197
198 hashmap_remove(s->manager->sessions, s->id);
98a28fef 199
c20b8dad
LP
200 sd_event_source_unref(s->fifo_event_source);
201 safe_close(s->fifo_fd);
202
203 /* Note that we remove neither the state file nor the fifo path here, since we want both to survive
204 * daemon restarts */
d2f92cdf 205 free(s->state_file);
c20b8dad 206 free(s->fifo_path);
8c29a457 207
82325af3
MS
208 sd_event_source_unref(s->stop_on_idle_event_source);
209
8c29a457 210 return mfree(s);
20263082
LP
211}
212
9444b1f2
LP
213void session_set_user(Session *s, User *u) {
214 assert(s);
215 assert(!s->user);
216
217 s->user = u;
71fda00f 218 LIST_PREPEND(sessions_by_user, u->sessions, s);
9afe9efb
LP
219
220 user_update_last_session_timer(u);
9444b1f2
LP
221}
222
76f2191d
MS
223int session_set_leader_consume(Session *s, PidRef _leader) {
224 _cleanup_(pidref_done) PidRef pidref = _leader;
238794b1
LP
225 int r;
226
227 assert(s);
76f2191d 228 assert(pidref_is_set(&pidref));
238794b1 229
76f2191d 230 if (pidref_equal(&s->leader, &pidref))
238794b1
LP
231 return 0;
232
9d5b6901 233 session_reset_leader(s, /* keep_fdstore = */ false);
8494f562
MY
234
235 s->leader = TAKE_PIDREF(pidref);
236
0ae9073f
MY
237 r = session_watch_pidfd(s);
238 if (r < 0)
239 return log_error_errno(r, "Failed to watch leader pidfd for session '%s': %m", s->id);
240
8494f562 241 r = hashmap_ensure_put(&s->manager->sessions_by_leader, &pidref_hash_ops, &s->leader, s);
89bad70f
LP
242 if (r < 0)
243 return r;
8494f562 244 assert(r > 0);
89bad70f 245
9d5b6901
MY
246 if (s->leader.fd >= 0) {
247 r = notify_push_fdf(s->leader.fd, "session-%s-leader-fd", s->id);
248 if (r < 0)
249 log_warning_errno(r, "Failed to push leader pidfd for session '%s', ignoring: %m", s->id);
250 else
251 s->leader_fd_saved = true;
252 }
253
89bad70f 254 (void) audit_session_from_pid(s->leader.pid, &s->audit_id);
238794b1
LP
255
256 return 1;
257}
258
aed24c4c
FB
259static void session_save_devices(Session *s, FILE *f) {
260 SessionDevice *sd;
aed24c4c
FB
261
262 if (!hashmap_isempty(s->devices)) {
263 fprintf(f, "DEVICES=");
90e74a66 264 HASHMAP_FOREACH(sd, s->devices)
67458536 265 fprintf(f, DEVNUM_FORMAT_STR " ", DEVNUM_FORMAT_VAL(sd->dev));
aed24c4c
FB
266 fprintf(f, "\n");
267 }
268}
269
20263082 270int session_save(Session *s) {
70f1280c 271 _cleanup_(unlink_and_freep) char *temp_path = NULL;
cc377381 272 _cleanup_fclose_ FILE *f = NULL;
6d95e7d9 273 int r;
20263082
LP
274
275 assert(s);
276
9444b1f2
LP
277 if (!s->user)
278 return -ESTALE;
279
accaeded
LP
280 if (!s->started)
281 return 0;
282
37c1d5e9 283 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
20263082 284 if (r < 0)
dacd6cee 285 goto fail;
20263082 286
14c3baca
LP
287 r = fopen_temporary(s->state_file, &f, &temp_path);
288 if (r < 0)
dacd6cee 289 goto fail;
20263082 290
44176400 291 (void) fchmod(fileno(f), 0644);
14c3baca 292
20263082
LP
293 fprintf(f,
294 "# This is private data. Do not parse.\n"
90b2de37 295 "UID="UID_FMT"\n"
20263082 296 "USER=%s\n"
fdbb56dc
MY
297 "ACTIVE=%s\n"
298 "IS_DISPLAY=%s\n"
0604381b 299 "STATE=%s\n"
9d5b6901
MY
300 "REMOTE=%s\n"
301 "LEADER_FD_SAVED=%s\n",
22c902fa
LP
302 s->user->user_record->uid,
303 s->user->user_record->user_name,
fdbb56dc
MY
304 one_zero(session_is_active(s)),
305 one_zero(s->user->display == s),
0604381b 306 session_state_to_string(session_get_state(s)),
9d5b6901
MY
307 one_zero(s->remote),
308 one_zero(s->leader_fd_saved));
20263082 309
a91e4e53 310 if (s->type >= 0)
507f22bd 311 fprintf(f, "TYPE=%s\n", session_type_to_string(s->type));
a91e4e53 312
db72aea4
CH
313 if (s->original_type >= 0)
314 fprintf(f, "ORIGINAL_TYPE=%s\n", session_type_to_string(s->original_type));
315
55efac6c 316 if (s->class >= 0)
507f22bd 317 fprintf(f, "CLASS=%s\n", session_class_to_string(s->class));
55efac6c 318
fb6becb4
LP
319 if (s->scope)
320 fprintf(f, "SCOPE=%s\n", s->scope);
fb6becb4
LP
321 if (s->scope_job)
322 fprintf(f, "SCOPE_JOB=%s\n", s->scope_job);
20263082 323
932e3ee7 324 if (s->fifo_path)
507f22bd 325 fprintf(f, "FIFO=%s\n", s->fifo_path);
932e3ee7 326
20263082 327 if (s->seat)
507f22bd 328 fprintf(f, "SEAT=%s\n", s->seat->id);
20263082
LP
329
330 if (s->tty)
507f22bd 331 fprintf(f, "TTY=%s\n", s->tty);
20263082 332
3d0ef5c7
LP
333 if (s->tty_validity >= 0)
334 fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity));
335
20263082 336 if (s->display)
507f22bd 337 fprintf(f, "DISPLAY=%s\n", s->display);
20263082 338
558c6490 339 if (s->remote_host) {
c2b2df60 340 _cleanup_free_ char *escaped = NULL;
558c6490
LP
341
342 escaped = cescape(s->remote_host);
343 if (!escaped) {
344 r = -ENOMEM;
dacd6cee 345 goto fail;
558c6490
LP
346 }
347
348 fprintf(f, "REMOTE_HOST=%s\n", escaped);
349 }
350
351 if (s->remote_user) {
c2b2df60 352 _cleanup_free_ char *escaped = NULL;
558c6490
LP
353
354 escaped = cescape(s->remote_user);
355 if (!escaped) {
356 r = -ENOMEM;
dacd6cee 357 goto fail;
558c6490
LP
358 }
359
360 fprintf(f, "REMOTE_USER=%s\n", escaped);
361 }
362
363 if (s->service) {
c2b2df60 364 _cleanup_free_ char *escaped = NULL;
20263082 365
558c6490
LP
366 escaped = cescape(s->service);
367 if (!escaped) {
368 r = -ENOMEM;
dacd6cee 369 goto fail;
558c6490
LP
370 }
371
372 fprintf(f, "SERVICE=%s\n", escaped);
373 }
3f49d45a 374
558c6490 375 if (s->desktop) {
c2b2df60 376 _cleanup_free_ char *escaped = NULL;
98a28fef 377
558c6490
LP
378 escaped = cescape(s->desktop);
379 if (!escaped) {
380 r = -ENOMEM;
dacd6cee 381 goto fail;
558c6490
LP
382 }
383
384 fprintf(f, "DESKTOP=%s\n", escaped);
385 }
a4cd87e9 386
bf7825ae 387 if (s->seat && seat_has_vts(s->seat))
92bd5ff3 388 fprintf(f, "VTNR=%u\n", s->vtnr);
20263082 389
49e6fdbf 390 if (!s->vtnr)
e6494a07 391 fprintf(f, "POSITION=%u\n", s->position);
49e6fdbf 392
89bad70f
LP
393 if (pidref_is_set(&s->leader))
394 fprintf(f, "LEADER="PID_FMT"\n", s->leader.pid);
20263082 395
3a87a86e 396 if (audit_session_is_valid(s->audit_id))
507f22bd 397 fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id);
20263082 398
9444b1f2
LP
399 if (dual_timestamp_is_set(&s->timestamp))
400 fprintf(f,
90b2de37
ZJS
401 "REALTIME="USEC_FMT"\n"
402 "MONOTONIC="USEC_FMT"\n",
403 s->timestamp.realtime,
404 s->timestamp.monotonic);
9444b1f2 405
aed24c4c 406 if (s->controller) {
6d33772f 407 fprintf(f, "CONTROLLER=%s\n", s->controller);
aed24c4c
FB
408 session_save_devices(s, f);
409 }
6d33772f 410
dacd6cee
LP
411 r = fflush_and_check(f);
412 if (r < 0)
413 goto fail;
14c3baca 414
dacd6cee 415 if (rename(temp_path, s->state_file) < 0) {
20263082 416 r = -errno;
dacd6cee 417 goto fail;
20263082
LP
418 }
419
70f1280c 420 temp_path = mfree(temp_path);
dacd6cee
LP
421 return 0;
422
423fail:
424 (void) unlink(s->state_file);
14c3baca 425
dacd6cee 426 return log_error_errno(r, "Failed to save session data %s: %m", s->state_file);
20263082
LP
427}
428
aed24c4c 429static int session_load_devices(Session *s, const char *devices) {
aed24c4c
FB
430 int r = 0;
431
432 assert(s);
433
e5c09aad 434 for (const char *p = devices;;) {
aed24c4c 435 _cleanup_free_ char *word = NULL;
aed24c4c
FB
436 dev_t dev;
437 int k;
438
439 k = extract_first_word(&p, &word, NULL, 0);
41935c0c
MY
440 if (k <= 0) {
441 RET_GATHER(r, k);
aed24c4c
FB
442 break;
443 }
444
7176f06c 445 k = parse_devnum(word, &dev);
aed24c4c 446 if (k < 0) {
41935c0c 447 RET_GATHER(r, k);
aed24c4c
FB
448 continue;
449 }
450
451 /* The file descriptors for loaded devices will be reattached later. */
41935c0c 452 RET_GATHER(r, session_device_new(s, dev, /* open_device = */ false, /* ret = */ NULL));
aed24c4c
FB
453 }
454
455 if (r < 0)
41935c0c 456 log_error_errno(r, "Failed to load some session devices for session '%s': %m", s->id);
aed24c4c
FB
457 return r;
458}
dacd6cee 459
20263082 460int session_load(Session *s) {
9444b1f2 461 _cleanup_free_ char *remote = NULL,
a185c5aa 462 *seat = NULL,
3d0ef5c7 463 *tty_validity = NULL,
a185c5aa 464 *vtnr = NULL,
be94d954 465 *state = NULL,
e6494a07 466 *position = NULL,
9d5b6901
MY
467 *leader_pid = NULL,
468 *leader_fd_saved = NULL,
55efac6c 469 *type = NULL,
db72aea4 470 *original_type = NULL,
9444b1f2
LP
471 *class = NULL,
472 *uid = NULL,
473 *realtime = NULL,
6d33772f 474 *monotonic = NULL,
aed24c4c
FB
475 *controller = NULL,
476 *active = NULL,
1c8280fd
LP
477 *devices = NULL,
478 *is_display = NULL;
a185c5aa
LP
479
480 int k, r;
481
20263082
LP
482 assert(s);
483
aa8fbc74 484 r = parse_env_file(NULL, s->state_file,
9d5b6901
MY
485 "REMOTE", &remote,
486 "SCOPE", &s->scope,
487 "SCOPE_JOB", &s->scope_job,
488 "FIFO", &s->fifo_path,
489 "SEAT", &seat,
490 "TTY", &s->tty,
491 "TTY_VALIDITY", &tty_validity,
492 "DISPLAY", &s->display,
493 "REMOTE_HOST", &s->remote_host,
494 "REMOTE_USER", &s->remote_user,
495 "SERVICE", &s->service,
496 "DESKTOP", &s->desktop,
497 "VTNR", &vtnr,
498 "STATE", &state,
499 "POSITION", &position,
500 "LEADER", &leader_pid,
501 "LEADER_FD_SAVED", &leader_fd_saved,
502 "TYPE", &type,
503 "ORIGINAL_TYPE", &original_type,
504 "CLASS", &class,
505 "UID", &uid,
506 "REALTIME", &realtime,
507 "MONOTONIC", &monotonic,
508 "CONTROLLER", &controller,
509 "ACTIVE", &active,
510 "DEVICES", &devices,
511 "IS_DISPLAY", &is_display);
f647962d
MS
512 if (r < 0)
513 return log_error_errno(r, "Failed to read %s: %m", s->state_file);
9444b1f2
LP
514
515 if (!s->user) {
516 uid_t u;
517 User *user;
518
baaa35ad
ZJS
519 if (!uid)
520 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
521 "UID not specified for session %s",
522 s->id);
9444b1f2
LP
523
524 r = parse_uid(uid, &u);
525 if (r < 0) {
526 log_error("Failed to parse UID value %s for session %s.", uid, s->id);
527 return r;
528 }
529
8cb4ab00 530 user = hashmap_get(s->manager->users, UID_TO_PTR(u));
baaa35ad
ZJS
531 if (!user)
532 return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
533 "User of session %s not known.",
534 s->id);
9444b1f2
LP
535
536 session_set_user(s, user);
537 }
a185c5aa
LP
538
539 if (remote) {
540 k = parse_boolean(remote);
541 if (k >= 0)
542 s->remote = k;
543 }
544
c506027a
DH
545 if (vtnr)
546 safe_atou(vtnr, &s->vtnr);
547
9418f147 548 if (seat && !s->seat) {
a185c5aa
LP
549 Seat *o;
550
551 o = hashmap_get(s->manager->seats, seat);
552 if (o)
c506027a
DH
553 r = seat_attach_session(o, s);
554 if (!o || r < 0)
555 log_error("Cannot attach session %s to seat %s", s->id, seat);
a185c5aa
LP
556 }
557
c506027a
DH
558 if (!s->seat || !seat_has_vts(s->seat))
559 s->vtnr = 0;
a185c5aa 560
e6494a07 561 if (position && s->seat) {
14cb109d 562 unsigned npos;
49e6fdbf 563
e6494a07 564 safe_atou(position, &npos);
49e6fdbf
DH
565 seat_claim_position(s->seat, s, npos);
566 }
567
3d0ef5c7
LP
568 if (tty_validity) {
569 TTYValidity v;
570
571 v = tty_validity_from_string(tty_validity);
572 if (v < 0)
573 log_debug("Failed to parse TTY validity: %s", tty_validity);
574 else
575 s->tty_validity = v;
576 }
577
a91e4e53
LP
578 if (type) {
579 SessionType t;
580
581 t = session_type_from_string(type);
582 if (t >= 0)
583 s->type = t;
584 }
585
db72aea4
CH
586 if (original_type) {
587 SessionType ot;
588
589 ot = session_type_from_string(original_type);
590 if (ot >= 0)
591 s->original_type = ot;
592 } else
593 /* Pre-v246 compat: initialize original_type if not set in the state file */
594 s->original_type = s->type;
595
55efac6c
LP
596 if (class) {
597 SessionClass c;
598
599 c = session_class_from_string(class);
600 if (c >= 0)
601 s->class = c;
602 }
603
e5c09aad 604 if (streq_ptr(state, "closing"))
be94d954
MP
605 s->stopping = true;
606
b4f78aea
LP
607 if (s->fifo_path) {
608 int fd;
609
610 /* If we open an unopened pipe for reading we will not
611 get an EOF. to trigger an EOF we hence open it for
be94d954
MP
612 writing, but close it right away which then will
613 trigger the EOF. This will happen immediately if no
614 other process has the FIFO open for writing, i. e.
615 when the session died before logind (re)started. */
b4f78aea
LP
616
617 fd = session_create_fifo(s);
03e334a1 618 safe_close(fd);
b4f78aea
LP
619 }
620
b895a735 621 if (realtime)
d68c645b 622 (void) deserialize_usec(realtime, &s->timestamp.realtime);
b895a735 623 if (monotonic)
d68c645b 624 (void) deserialize_usec(monotonic, &s->timestamp.monotonic);
a185c5aa 625
aed24c4c
FB
626 if (active) {
627 k = parse_boolean(active);
628 if (k >= 0)
629 s->was_active = k;
630 }
631
1c8280fd
LP
632 if (is_display) {
633 /* Note that when enumerating users are loaded before sessions, hence the display session to use is
634 * something we have to store along with the session and not the user, as in that case we couldn't
635 * apply it at the time we load the user. */
636
637 k = parse_boolean(is_display);
638 if (k < 0)
639 log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
640 else if (k > 0)
641 s->user->display = s;
642 }
643
6d33772f 644 if (controller) {
aed24c4c 645 if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
dc6284e9 646 session_set_controller(s, controller, false, false);
aed24c4c
FB
647 session_load_devices(s, devices);
648 } else
90a18413 649 session_restore_vt(s);
6d33772f
DH
650 }
651
9d5b6901
MY
652 if (leader_pid) {
653 assert(!pidref_is_set(&s->leader));
654
655 r = parse_pid(leader_pid, &s->deserialized_pid);
656 if (r < 0)
657 return log_error_errno(r, "Failed to parse LEADER=%s: %m", leader_pid);
658
659 if (leader_fd_saved) {
660 r = parse_boolean(leader_fd_saved);
661 if (r < 0)
662 return log_error_errno(r, "Failed to parse LEADER_FD_SAVED=%s: %m", leader_fd_saved);
663 s->leader_fd_saved = r > 0;
664
665 if (s->leader_fd_saved)
666 /* The leader fd will be acquired from fdstore later */
667 return 0;
668 }
669
670 _cleanup_(pidref_done) PidRef p = PIDREF_NULL;
671
672 r = pidref_set_pid(&p, s->deserialized_pid);
673 if (r >= 0)
674 r = session_set_leader_consume(s, TAKE_PIDREF(p));
675 if (r < 0)
676 log_warning_errno(r, "Failed to set leader PID for session '%s': %m", s->id);
677 }
678
a185c5aa 679 return r;
20263082
LP
680}
681
682int session_activate(Session *s) {
14cb109d 683 unsigned num_pending;
d7bd01b5 684
20263082 685 assert(s);
9444b1f2 686 assert(s->user);
20263082 687
20263082 688 if (!s->seat)
15411c0c 689 return -EOPNOTSUPP;
20263082
LP
690
691 if (s->seat->active == s)
692 return 0;
693
d7bd01b5
DH
694 /* on seats with VTs, we let VTs manage session-switching */
695 if (seat_has_vts(s->seat)) {
709d0587 696 if (s->vtnr == 0)
15411c0c 697 return -EOPNOTSUPP;
d7bd01b5
DH
698
699 return chvt(s->vtnr);
700 }
701
702 /* On seats without VTs, we implement session-switching in logind. We
703 * try to pause all session-devices and wait until the session
704 * controller acknowledged them. Once all devices are asleep, we simply
705 * switch the active session and be done.
706 * We save the session we want to switch to in seat->pending_switch and
707 * seat_complete_switch() will perform the final switch. */
708
709 s->seat->pending_switch = s;
710
711 /* if no devices are running, immediately perform the session switch */
712 num_pending = session_device_try_pause_all(s);
713 if (!num_pending)
714 seat_complete_switch(s->seat);
20263082 715
d7bd01b5 716 return 0;
20263082
LP
717}
718
25a1ab4e 719static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
98a28fef
LP
720 int r;
721
722 assert(s);
9444b1f2 723 assert(s->user);
98a28fef 724
fb6becb4 725 if (!s->scope) {
278e815b 726 _cleanup_strv_free_ char **after = NULL;
fb2367ed 727 _cleanup_free_ char *scope = NULL;
90558f31 728 const char *description;
405e0255 729
25a1ab4e
LP
730 s->scope_job = mfree(s->scope_job);
731
605405c6 732 scope = strjoin("session-", s->id, ".scope");
d0af76e6 733 if (!scope)
ae018d9b
LP
734 return log_oom();
735
0a59216c 736 description = strjoina("Session ", s->id, " of User ", s->user->user_record->user_name);
90558f31 737
278e815b
FB
738 /* We usually want to order session scopes after systemd-user-sessions.service since the
739 * latter unit is used as login session barrier for unprivileged users. However the barrier
740 * doesn't apply for root as sysadmin should always be able to log in (and without waiting
741 * for any timeout to expire) in case something goes wrong during the boot process. Since
742 * ordering after systemd-user-sessions.service and the user instance is optional we make use
743 * of STRV_IGNORE with strv_new() to skip these order constraints when needed. */
744 after = strv_new("systemd-logind.service",
745 s->user->runtime_dir_service,
746 !uid_is_system(s->user->user_record->uid) ? "systemd-user-sessions.service" : STRV_IGNORE,
513cf7da 747 s->user->service);
278e815b
FB
748 if (!after)
749 return log_oom();
750
90558f31
LP
751 r = manager_start_scope(
752 s->manager,
753 scope,
7eda208f 754 &s->leader,
90558f31
LP
755 s->user->slice,
756 description,
124d7cb2
ZJS
757 /* These two have StopWhenUnneeded= set, hence add a dep towards them */
758 STRV_MAKE(s->user->runtime_dir_service,
513cf7da 759 s->user->service),
278e815b 760 after,
22c902fa 761 user_record_home_directory(s->user->user_record),
22f93314 762 properties,
25a1ab4e
LP
763 error,
764 &s->scope_job);
fb2367ed 765 if (r < 0)
124d7cb2
ZJS
766 return log_error_errno(r, "Failed to start session scope %s: %s",
767 scope, bus_error_message(error, r));
fb2367ed
YW
768
769 s->scope = TAKE_PTR(scope);
20263082
LP
770 }
771
124d7cb2 772 (void) hashmap_put(s->manager->session_units, s->scope, s);
d0af76e6 773
20263082
LP
774 return 0;
775}
776
82325af3
MS
777static int session_dispatch_stop_on_idle(sd_event_source *source, uint64_t t, void *userdata) {
778 Session *s = userdata;
779 dual_timestamp ts;
780 int r, idle;
781
782 assert(s);
783
784 if (s->stopping)
785 return 0;
786
787 idle = session_get_idle_hint(s, &ts);
788 if (idle) {
6269ffe7 789 log_info("Session \"%s\" of user \"%s\" is idle, stopping.", s->id, s->user->user_record->user_name);
82325af3
MS
790
791 return session_stop(s, /* force */ true);
792 }
793
ab7ae746
MS
794 r = sd_event_source_set_time(
795 source,
796 usec_add(dual_timestamp_is_set(&ts) ? ts.monotonic : now(CLOCK_MONOTONIC),
797 s->manager->stop_idle_session_usec));
82325af3
MS
798 if (r < 0)
799 return log_error_errno(r, "Failed to configure stop on idle session event source: %m");
800
801 r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
802 if (r < 0)
803 return log_error_errno(r, "Failed to enable stop on idle session event source: %m");
804
805 return 1;
806}
807
808static int session_setup_stop_on_idle_timer(Session *s) {
809 int r;
810
811 assert(s);
812
508b4786 813 if (s->manager->stop_idle_session_usec == USEC_INFINITY || IN_SET(s->class, SESSION_GREETER, SESSION_LOCK_SCREEN))
82325af3
MS
814 return 0;
815
816 r = sd_event_add_time_relative(
817 s->manager->event,
818 &s->stop_on_idle_event_source,
819 CLOCK_MONOTONIC,
820 s->manager->stop_idle_session_usec,
821 0,
822 session_dispatch_stop_on_idle, s);
823 if (r < 0)
824 return log_error_errno(r, "Failed to add stop on idle session event source: %m");
825
826 return 0;
827}
828
25a1ab4e 829int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
20263082
LP
830 int r;
831
832 assert(s);
9444b1f2
LP
833
834 if (!s->user)
835 return -ESTALE;
20263082 836
25a1ab4e
LP
837 if (s->stopping)
838 return -EINVAL;
839
9418f147
LP
840 if (s->started)
841 return 0;
842
513cf7da 843 r = user_start(s->user);
ed18b08b
LP
844 if (r < 0)
845 return r;
846
25a1ab4e 847 r = session_start_scope(s, properties, error);
fb6becb4
LP
848 if (r < 0)
849 return r;
850
82325af3
MS
851 r = session_setup_stop_on_idle_timer(s);
852 if (r < 0)
853 return r;
854
d9eb81f9 855 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
2b044526 856 "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR,
877d54e9 857 "SESSION_ID=%s", s->id,
22c902fa 858 "USER_ID=%s", s->user->user_record->user_name,
89bad70f 859 "LEADER="PID_FMT, s->leader.pid,
22c902fa 860 LOG_MESSAGE("New session %s of user %s.", s->id, s->user->user_record->user_name));
98a28fef 861
9444b1f2 862 if (!dual_timestamp_is_set(&s->timestamp))
fa5a0251 863 dual_timestamp_now(&s->timestamp);
14c3baca 864
e9816c48
LP
865 if (s->seat)
866 seat_read_active_vt(s->seat);
867
9418f147
LP
868 s->started = true;
869
952d3260
LP
870 user_elect_display(s->user);
871
5f41d1f1 872 /* Save data */
5157b0d8
LP
873 (void) session_save(s);
874 (void) user_save(s->user);
5f41d1f1 875 if (s->seat)
5157b0d8 876 (void) seat_save(s->seat);
e9816c48 877
5f41d1f1 878 /* Send signals */
da119395 879 session_send_signal(s, true);
7d049e30 880 user_send_changed(s->user, "Display", NULL);
40771cf5
LP
881
882 if (s->seat && s->seat->active == s)
5157b0d8 883 (void) seat_send_changed(s->seat, "ActiveSession", NULL);
9418f147 884
20263082
LP
885 return 0;
886}
887
9bb69af4 888static int session_stop_scope(Session *s, bool force) {
4afd3348 889 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
20263082 890 int r;
20263082
LP
891
892 assert(s);
893
fb6becb4
LP
894 if (!s->scope)
895 return 0;
9b221b63 896
756ed0e2 897 /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
629ff674 898 * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
756ed0e2
LP
899 * when killing any processes left after this point. */
900 r = manager_abandon_scope(s->manager, s->scope, &error);
25a1ab4e 901 if (r < 0) {
756ed0e2 902 log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
25a1ab4e
LP
903 sd_bus_error_free(&error);
904 }
905
906 s->scope_job = mfree(s->scope_job);
756ed0e2
LP
907
908 /* Optionally, let's kill everything that's left now. */
156a3637
LP
909 if (force ||
910 (s->user->user_record->kill_processes != 0 &&
911 (s->user->user_record->kill_processes > 0 ||
912 manager_shall_kill(s->manager, s->user->user_record->user_name)))) {
801a884d 913
1a42ce09 914 r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job);
25a1ab4e
LP
915 if (r < 0) {
916 if (force)
917 return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
20263082 918
25a1ab4e
LP
919 log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
920 }
8150acb1 921 } else {
20263082 922
8150acb1
AJ
923 /* With no killing, this session is allowed to persist in "closing" state indefinitely.
924 * Therefore session stop and session removal may be two distinct events.
925 * Session stop is quite significant on its own, let's log it. */
926 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
927 "SESSION_ID=%s", s->id,
22c902fa 928 "USER_ID=%s", s->user->user_record->user_name,
89bad70f 929 "LEADER="PID_FMT, s->leader.pid,
f4cf1d66 930 LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id));
8150acb1
AJ
931 }
932
9b221b63 933 return 0;
20263082
LP
934}
935
9bb69af4 936int session_stop(Session *s, bool force) {
405e0255
LP
937 int r;
938
939 assert(s);
940
25a1ab4e
LP
941 /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
942 * request via the bus (either directly for the session object or for the seat or user object this session
943 * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
944 * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
945
405e0255
LP
946 if (!s->user)
947 return -ESTALE;
25a1ab4e
LP
948 if (!s->started)
949 return 0;
950 if (s->stopping)
951 return 0;
405e0255 952
5f41d1f1 953 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
76f2191d 954 s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
5f41d1f1 955
10189fd6
DH
956 if (s->seat)
957 seat_evict_position(s->seat, s);
958
5f41d1f1
LP
959 /* We are going down, don't care about FIFOs anymore */
960 session_remove_fifo(s);
961
405e0255 962 /* Kill cgroup */
9bb69af4 963 r = session_stop_scope(s, force);
405e0255 964
5f41d1f1
LP
965 s->stopping = true;
966
952d3260
LP
967 user_elect_display(s->user);
968
5157b0d8
LP
969 (void) session_save(s);
970 (void) user_save(s->user);
405e0255
LP
971
972 return r;
973}
974
975int session_finalize(Session *s) {
118ecf32 976 SessionDevice *sd;
20263082
LP
977
978 assert(s);
979
9444b1f2
LP
980 if (!s->user)
981 return -ESTALE;
982
ed18b08b 983 if (s->started)
d9eb81f9 984 log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO,
2b044526 985 "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR,
877d54e9 986 "SESSION_ID=%s", s->id,
22c902fa 987 "USER_ID=%s", s->user->user_record->user_name,
89bad70f 988 "LEADER="PID_FMT, s->leader.pid,
a1230ff9 989 LOG_MESSAGE("Removed session %s.", s->id));
98a28fef 990
5f41d1f1
LP
991 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
992
10189fd6
DH
993 if (s->seat)
994 seat_evict_position(s->seat, s);
995
118ecf32
DH
996 /* Kill session devices */
997 while ((sd = hashmap_first(s->devices)))
998 session_device_free(sd);
999
491ac9f2 1000 (void) unlink(s->state_file);
d2f92cdf 1001 session_add_to_gc_queue(s);
ed18b08b 1002 user_add_to_gc_queue(s->user);
14c3baca 1003
405e0255 1004 if (s->started) {
ed18b08b 1005 session_send_signal(s, false);
405e0255
LP
1006 s->started = false;
1007 }
50fb9793 1008
9418f147
LP
1009 if (s->seat) {
1010 if (s->seat->active == s)
1011 seat_set_active(s->seat, NULL);
1012
23bd3b62 1013 seat_save(s->seat);
9418f147
LP
1014 }
1015
9d5b6901 1016 session_reset_leader(s, /* keep_fdstore = */ false);
76f2191d 1017
5157b0d8
LP
1018 (void) user_save(s->user);
1019 (void) user_send_changed(s->user, "Display", NULL);
9418f147 1020
491ac9f2 1021 return 0;
20263082
LP
1022}
1023
5f41d1f1 1024static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
99534007 1025 Session *s = ASSERT_PTR(userdata);
5f41d1f1
LP
1026
1027 assert(es);
5f41d1f1 1028
bda62573 1029 session_stop(s, /* force = */ false);
5f41d1f1
LP
1030 return 0;
1031}
1032
ad8780c9 1033int session_release(Session *s) {
5f41d1f1
LP
1034 assert(s);
1035
1036 if (!s->started || s->stopping)
ad8780c9
ZJS
1037 return 0;
1038
1039 if (s->timer_event_source)
1040 return 0;
1041
39cf0351
LP
1042 return sd_event_add_time_relative(
1043 s->manager->event,
1044 &s->timer_event_source,
1045 CLOCK_MONOTONIC,
1046 RELEASE_USEC, 0,
1047 release_timeout_callback, s);
5f41d1f1
LP
1048}
1049
20263082
LP
1050bool session_is_active(Session *s) {
1051 assert(s);
1052
1053 if (!s->seat)
1054 return true;
1055
1056 return s->seat->active == s;
1057}
1058
23406ce5
LP
1059static int get_tty_atime(const char *tty, usec_t *atime) {
1060 _cleanup_free_ char *p = NULL;
a185c5aa 1061 struct stat st;
23406ce5
LP
1062
1063 assert(tty);
1064 assert(atime);
1065
1066 if (!path_is_absolute(tty)) {
b910cc72 1067 p = path_join("/dev", tty);
23406ce5
LP
1068 if (!p)
1069 return -ENOMEM;
1070
1071 tty = p;
1072 } else if (!path_startswith(tty, "/dev/"))
1073 return -ENOENT;
1074
1075 if (lstat(tty, &st) < 0)
1076 return -errno;
1077
1078 *atime = timespec_load(&st.st_atim);
1079 return 0;
1080}
1081
1082static int get_process_ctty_atime(pid_t pid, usec_t *atime) {
1083 _cleanup_free_ char *p = NULL;
1084 int r;
1085
1086 assert(pid > 0);
1087 assert(atime);
1088
1089 r = get_ctty(pid, NULL, &p);
1090 if (r < 0)
1091 return r;
1092
1093 return get_tty_atime(p, atime);
1094}
1095
1096int session_get_idle_hint(Session *s, dual_timestamp *t) {
82325af3 1097 usec_t atime = 0, dtime = 0;
23406ce5 1098 int r;
a185c5aa
LP
1099
1100 assert(s);
1101
be2bb14f
LP
1102 /* Graphical sessions have an explicit idle hint */
1103 if (SESSION_TYPE_IS_GRAPHICAL(s->type)) {
a185c5aa
LP
1104 if (t)
1105 *t = s->idle_hint_timestamp;
1106
1107 return s->idle_hint;
1108 }
1109
20604ff2
LP
1110 if (s->type == SESSION_TTY) {
1111 /* For sessions with an explicitly configured tty, let's check its atime */
1112 if (s->tty) {
1113 r = get_tty_atime(s->tty, &atime);
1114 if (r >= 0)
1115 goto found_atime;
1116 }
a185c5aa 1117
20604ff2
LP
1118 /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of
1119 * the leader */
1120 if (pidref_is_set(&s->leader)) {
1121 r = get_process_ctty_atime(s->leader.pid, &atime);
1122 if (r >= 0)
1123 goto found_atime;
1124 }
a185c5aa
LP
1125 }
1126
a185c5aa 1127 if (t)
be2bb14f 1128 *t = DUAL_TIMESTAMP_NULL;
a185c5aa 1129
be2bb14f 1130 return false;
23406ce5
LP
1131
1132found_atime:
1133 if (t)
1134 dual_timestamp_from_realtime(t, atime);
1135
82325af3
MS
1136 if (s->manager->idle_action_usec > 0 && s->manager->stop_idle_session_usec != USEC_INFINITY)
1137 dtime = MIN(s->manager->idle_action_usec, s->manager->stop_idle_session_usec);
1138 else if (s->manager->idle_action_usec > 0)
1139 dtime = s->manager->idle_action_usec;
1140 else if (s->manager->stop_idle_session_usec != USEC_INFINITY)
1141 dtime = s->manager->stop_idle_session_usec;
1142 else
be2bb14f 1143 return false;
23406ce5 1144
82325af3 1145 return usec_add(atime, dtime) <= now(CLOCK_REALTIME);
a185c5aa
LP
1146}
1147
be2bb14f 1148int session_set_idle_hint(Session *s, bool b) {
bef422ae
LP
1149 assert(s);
1150
be2bb14f
LP
1151 if (!SESSION_TYPE_IS_GRAPHICAL(s->type))
1152 return -ENOTTY;
1153
bef422ae 1154 if (s->idle_hint == b)
be2bb14f 1155 return 0;
bef422ae
LP
1156
1157 s->idle_hint = b;
fa5a0251 1158 dual_timestamp_now(&s->idle_hint_timestamp);
9418f147 1159
cc377381 1160 session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
9418f147
LP
1161
1162 if (s->seat)
cc377381
LP
1163 seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1164
1165 user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
1166 manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL);
be2bb14f
LP
1167
1168 return 1;
cc377381
LP
1169}
1170
42d35e13
VT
1171int session_get_locked_hint(Session *s) {
1172 assert(s);
1173
1174 return s->locked_hint;
1175}
1176
1177void session_set_locked_hint(Session *s, bool b) {
1178 assert(s);
1179
1180 if (s->locked_hint == b)
1181 return;
1182
1183 s->locked_hint = b;
1184
1185 session_send_changed(s, "LockedHint", NULL);
1186}
1187
db72aea4
CH
1188void session_set_type(Session *s, SessionType t) {
1189 assert(s);
1190
1191 if (s->type == t)
1192 return;
1193
1194 s->type = t;
5157b0d8
LP
1195 (void) session_save(s);
1196 (void) session_send_changed(s, "Type", NULL);
db72aea4
CH
1197}
1198
4885d749
DT
1199int session_set_display(Session *s, const char *display) {
1200 int r;
1201
1202 assert(s);
1203 assert(display);
1204
4885d749 1205 r = free_and_strdup(&s->display, display);
e5c09aad 1206 if (r <= 0) /* 0 means the strings were equal */
4885d749
DT
1207 return r;
1208
5157b0d8
LP
1209 (void) session_save(s);
1210 (void) session_send_changed(s, "Display", NULL);
4885d749
DT
1211
1212 return 1;
1213}
1214
092e6cd1
TK
1215int session_set_tty(Session *s, const char *tty) {
1216 int r;
1217
1218 assert(s);
1219 assert(tty);
1220
1221 r = free_and_strdup(&s->tty, tty);
1222 if (r <= 0) /* 0 means the strings were equal */
1223 return r;
1224
5157b0d8
LP
1225 (void) session_save(s);
1226 (void) session_send_changed(s, "TTY", NULL);
092e6cd1
TK
1227
1228 return 1;
1229}
1230
cc377381 1231static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
99534007 1232 Session *s = ASSERT_PTR(userdata);
cc377381 1233
cc377381
LP
1234 assert(s->fifo_fd == fd);
1235
1236 /* EOF on the FIFO means the session died abnormally. */
1237
1238 session_remove_fifo(s);
bda62573 1239 session_stop(s, /* force = */ false);
cc377381
LP
1240
1241 return 1;
bef422ae
LP
1242}
1243
932e3ee7
LP
1244int session_create_fifo(Session *s) {
1245 int r;
1246
31b79c2b
LP
1247 assert(s);
1248
b4f78aea 1249 /* Create FIFO */
932e3ee7 1250 if (!s->fifo_path) {
37c1d5e9 1251 r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE);
e6061ab2
LP
1252 if (r < 0)
1253 return r;
1254
d5ddc930
LP
1255 s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref");
1256 if (!s->fifo_path)
932e3ee7 1257 return -ENOMEM;
31b79c2b 1258
932e3ee7
LP
1259 if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST)
1260 return -errno;
1261 }
31b79c2b 1262
932e3ee7 1263 /* Open reading side */
b4f78aea 1264 if (s->fifo_fd < 0) {
db4a47e9 1265 s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
b4f78aea
LP
1266 if (s->fifo_fd < 0)
1267 return -errno;
cc377381
LP
1268 }
1269
1270 if (!s->fifo_event_source) {
151b9b96 1271 r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s);
b4f78aea
LP
1272 if (r < 0)
1273 return r;
1274
6c75e317
ZJS
1275 /* Let's make sure we noticed dead sessions before we process new bus requests (which might
1276 * create new sessions). */
e11544a8 1277 r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10);
cc377381
LP
1278 if (r < 0)
1279 return r;
b4f78aea 1280 }
932e3ee7
LP
1281
1282 /* Open writing side */
7c248223 1283 return RET_NERRNO(open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK));
932e3ee7
LP
1284}
1285
5f41d1f1 1286static void session_remove_fifo(Session *s) {
932e3ee7
LP
1287 assert(s);
1288
03e334a1
LP
1289 s->fifo_event_source = sd_event_source_unref(s->fifo_event_source);
1290 s->fifo_fd = safe_close(s->fifo_fd);
932e3ee7
LP
1291
1292 if (s->fifo_path) {
75bbdf47 1293 (void) unlink(s->fifo_path);
a1e58e8e 1294 s->fifo_path = mfree(s->fifo_path);
932e3ee7 1295 }
31b79c2b
LP
1296}
1297
5c093a23 1298bool session_may_gc(Session *s, bool drop_not_started) {
bd26aee1
LP
1299 int r;
1300
20263082
LP
1301 assert(s);
1302
4a4b033f 1303 if (drop_not_started && !s->started)
5c093a23 1304 return true;
932e3ee7 1305
9444b1f2 1306 if (!s->user)
5c093a23 1307 return true;
9444b1f2 1308
76f2191d 1309 r = pidref_is_alive(&s->leader);
9d5b6901
MY
1310 if (r == -ESRCH)
1311 /* Session has no leader. This is probably because the leader vanished before deserializing
1312 * pidfd from FD store. */
1313 return true;
76f2191d 1314 if (r < 0)
9d5b6901 1315 log_debug_errno(r, "Unable to determine if leader PID " PID_FMT " is still alive, assuming not: %m", s->leader.pid);
76f2191d
MS
1316 if (r > 0)
1317 return false;
1318
9d5b6901
MY
1319 if (s->fifo_fd >= 0 && pipe_eof(s->fifo_fd) <= 0)
1320 return false;
20263082 1321
bd26aee1
LP
1322 if (s->scope_job) {
1323 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1324
1325 r = manager_job_is_active(s->manager, s->scope_job, &error);
1326 if (r < 0)
1327 log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r));
1328 if (r != 0)
1329 return false;
1330 }
20263082 1331
bd26aee1
LP
1332 if (s->scope) {
1333 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1334
1335 r = manager_unit_is_active(s->manager, s->scope, &error);
1336 if (r < 0)
1337 log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r));
1338 if (r != 0)
1339 return false;
1340 }
20263082 1341
5c093a23 1342 return true;
20263082
LP
1343}
1344
14c3baca
LP
1345void session_add_to_gc_queue(Session *s) {
1346 assert(s);
1347
1348 if (s->in_gc_queue)
1349 return;
1350
71fda00f 1351 LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s);
14c3baca
LP
1352 s->in_gc_queue = true;
1353}
1354
0604381b
LP
1355SessionState session_get_state(Session *s) {
1356 assert(s);
1357
8fe63cd4 1358 /* always check closing first */
5f41d1f1
LP
1359 if (s->stopping || s->timer_event_source)
1360 return SESSION_CLOSING;
1361
76f2191d 1362 if (s->scope_job || (!pidref_is_set(&s->leader) && s->fifo_fd < 0))
405e0255 1363 return SESSION_OPENING;
fb6becb4 1364
0604381b
LP
1365 if (session_is_active(s))
1366 return SESSION_ACTIVE;
1367
1368 return SESSION_ONLINE;
1369}
1370
de07ab16 1371int session_kill(Session *s, KillWho who, int signo) {
de07ab16
LP
1372 assert(s);
1373
fb6becb4 1374 if (!s->scope)
de07ab16
LP
1375 return -ESRCH;
1376
fb6becb4 1377 return manager_kill_unit(s->manager, s->scope, who, signo, NULL);
de07ab16
LP
1378}
1379
93041c60
MY
1380static int session_open_vt(Session *s, bool reopen) {
1381 _cleanup_close_ int fd = -EBADF;
5f41d1f1 1382 char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)];
90a18413 1383
a8d5378a
MY
1384 assert(s);
1385
baccf3e4
OB
1386 if (s->vtnr < 1)
1387 return -ENODEV;
90a18413 1388
93041c60 1389 if (!reopen && s->vtfd >= 0)
90a18413
DH
1390 return s->vtfd;
1391
92bd5ff3 1392 sprintf(path, "/dev/tty%u", s->vtnr);
90a18413 1393
93041c60
MY
1394 fd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
1395 if (fd < 0)
1396 return log_error_errno(fd, "Cannot open VT %s of session %s: %m", path, s->id);
1397
1398 close_and_replace(s->vtfd, fd);
90a18413
DH
1399 return s->vtfd;
1400}
1401
a03cdb17 1402static int session_prepare_vt(Session *s) {
90a18413 1403 int vt, r;
9fb2c8b8 1404 struct vt_mode mode = {};
90a18413 1405
a8d5378a
MY
1406 assert(s);
1407
baccf3e4
OB
1408 if (s->vtnr < 1)
1409 return 0;
1410
93041c60 1411 vt = session_open_vt(s, /* reopen = */ false);
90a18413 1412 if (vt < 0)
baccf3e4 1413 return vt;
90a18413 1414
22c902fa 1415 r = fchown(vt, s->user->user_record->uid, -1);
baccf3e4 1416 if (r < 0) {
94c156cd
LP
1417 r = log_error_errno(errno,
1418 "Cannot change owner of /dev/tty%u: %m",
1419 s->vtnr);
d6176c6c 1420 goto error;
baccf3e4 1421 }
d6176c6c 1422
90a18413 1423 r = ioctl(vt, KDSKBMODE, K_OFF);
baccf3e4 1424 if (r < 0) {
94c156cd
LP
1425 r = log_error_errno(errno,
1426 "Cannot set K_OFF on /dev/tty%u: %m",
1427 s->vtnr);
90a18413 1428 goto error;
baccf3e4 1429 }
90a18413
DH
1430
1431 r = ioctl(vt, KDSETMODE, KD_GRAPHICS);
baccf3e4 1432 if (r < 0) {
94c156cd
LP
1433 r = log_error_errno(errno,
1434 "Cannot set KD_GRAPHICS on /dev/tty%u: %m",
1435 s->vtnr);
90a18413 1436 goto error;
baccf3e4 1437 }
90a18413 1438
90a18413
DH
1439 /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS.
1440 * So we need a dummy handler here which just acknowledges *all* VT
1441 * switch requests. */
1442 mode.mode = VT_PROCESS;
92683ad2
DH
1443 mode.relsig = SIGRTMIN;
1444 mode.acqsig = SIGRTMIN + 1;
90a18413 1445 r = ioctl(vt, VT_SETMODE, &mode);
baccf3e4 1446 if (r < 0) {
94c156cd
LP
1447 r = log_error_errno(errno,
1448 "Cannot set VT_PROCESS on /dev/tty%u: %m",
1449 s->vtnr);
90a18413 1450 goto error;
baccf3e4 1451 }
90a18413 1452
baccf3e4 1453 return 0;
90a18413
DH
1454
1455error:
90a18413 1456 session_restore_vt(s);
baccf3e4 1457 return r;
90a18413
DH
1458}
1459
0212126c 1460static void session_restore_vt(Session *s) {
8246905a 1461 int r;
128df4cf 1462
a8d5378a
MY
1463 assert(s);
1464
092e6cd1
TK
1465 if (s->vtfd < 0)
1466 return;
1467
8246905a
FB
1468 r = vt_restore(s->vtfd);
1469 if (r == -EIO) {
8246905a
FB
1470 /* It might happen if the controlling process exited before or while we were
1471 * restoring the VT as it would leave the old file-descriptor in a hung-up
1472 * state. In this case let's retry with a fresh handle to the virtual terminal. */
ad96887a 1473
8246905a
FB
1474 /* We do a little dance to avoid having the terminal be available
1475 * for reuse before we've cleaned it up. */
8246905a 1476
93041c60
MY
1477 int fd = session_open_vt(s, /* reopen = */ true);
1478 if (fd >= 0)
1479 r = vt_restore(fd);
8246905a 1480 }
c0f34168
FB
1481 if (r < 0)
1482 log_warning_errno(r, "Failed to restore VT, ignoring: %m");
d6176c6c 1483
03e334a1 1484 s->vtfd = safe_close(s->vtfd);
90a18413
DH
1485}
1486
2ec3ff66 1487void session_leave_vt(Session *s) {
ce540a24
DH
1488 int r;
1489
2ec3ff66
DH
1490 assert(s);
1491
1492 /* This is called whenever we get a VT-switch signal from the kernel.
1493 * We acknowledge all of them unconditionally. Note that session are
1494 * free to overwrite those handlers and we only register them for
1495 * sessions with controllers. Legacy sessions are not affected.
1496 * However, if we switch from a non-legacy to a legacy session, we must
1497 * make sure to pause all device before acknowledging the switch. We
1498 * process the real switch only after we are notified via sysfs, so the
1499 * legacy session might have already started using the devices. If we
1500 * don't pause the devices before the switch, we might confuse the
1501 * session we switch to. */
1502
1503 if (s->vtfd < 0)
1504 return;
1505
1506 session_device_pause_all(s);
93041c60 1507 r = vt_release(s->vtfd, /* restore = */ false);
99d4ad71 1508 if (r == -EIO) {
93041c60 1509 /* Handle the same VT hung-up case as in session_restore_vt */
99d4ad71 1510
93041c60
MY
1511 int fd = session_open_vt(s, /* reopen = */ true);
1512 if (fd >= 0)
1513 r = vt_release(fd, /* restore = */ false);
99d4ad71 1514 }
ce540a24 1515 if (r < 0)
27dafac9 1516 log_debug_errno(r, "Cannot release VT of session %s: %m", s->id);
2ec3ff66
DH
1517}
1518
cc377381 1519bool session_is_controller(Session *s, const char *sender) {
e5c09aad 1520 return streq_ptr(ASSERT_PTR(s)->controller, sender);
ae5e06bd
DH
1521}
1522
b12e5615 1523static void session_release_controller(Session *s, bool notify) {
d7ac0952 1524 _unused_ _cleanup_free_ char *name = NULL;
6d33772f
DH
1525 SessionDevice *sd;
1526
a8d5378a
MY
1527 assert(s);
1528
b12e5615
DH
1529 if (!s->controller)
1530 return;
6d33772f 1531
b12e5615 1532 name = s->controller;
90a18413 1533
6c75e317
ZJS
1534 /* By resetting the controller before releasing the devices, we won't send notification signals.
1535 * This avoids sending useless notifications if the controller is released on disconnects. */
b12e5615
DH
1536 if (!notify)
1537 s->controller = NULL;
6d33772f 1538
b12e5615
DH
1539 while ((sd = hashmap_first(s->devices)))
1540 session_device_free(sd);
1541
1542 s->controller = NULL;
3cde9e8f
DM
1543 s->track = sd_bus_track_unref(s->track);
1544}
1545
1546static int on_bus_track(sd_bus_track *track, void *userdata) {
99534007 1547 Session *s = ASSERT_PTR(userdata);
3cde9e8f
DM
1548
1549 assert(track);
3cde9e8f
DM
1550
1551 session_drop_controller(s);
1552
1553 return 0;
6d33772f
DH
1554}
1555
dc6284e9 1556int session_set_controller(Session *s, const char *sender, bool force, bool prepare) {
b12e5615 1557 _cleanup_free_ char *name = NULL;
ae5e06bd
DH
1558 int r;
1559
1560 assert(s);
1561 assert(sender);
1562
1563 if (session_is_controller(s, sender))
1564 return 0;
1565 if (s->controller && !force)
1566 return -EBUSY;
1567
b12e5615
DH
1568 name = strdup(sender);
1569 if (!name)
ae5e06bd
DH
1570 return -ENOMEM;
1571
3cde9e8f
DM
1572 s->track = sd_bus_track_unref(s->track);
1573 r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s);
1574 if (r < 0)
1575 return r;
1576
1577 r = sd_bus_track_add_name(s->track, name);
1578 if (r < 0)
ae5e06bd 1579 return r;
ae5e06bd 1580
90a18413
DH
1581 /* When setting a session controller, we forcibly mute the VT and set
1582 * it into graphics-mode. Applications can override that by changing
1583 * VT state after calling TakeControl(). However, this serves as a good
1584 * default and well-behaving controllers can now ignore VTs entirely.
1585 * Note that we reset the VT on ReleaseControl() and if the controller
1586 * exits.
1587 * If logind crashes/restarts, we restore the controller during restart
dc6284e9
FB
1588 * (without preparing the VT since the controller has probably overridden
1589 * VT state by now) or reset the VT in case it crashed/exited, too. */
1590 if (prepare) {
1591 r = session_prepare_vt(s);
1592 if (r < 0) {
1593 s->track = sd_bus_track_unref(s->track);
1594 return r;
1595 }
13f493dc 1596 }
baccf3e4 1597
b12e5615 1598 session_release_controller(s, true);
ae2a15bc 1599 s->controller = TAKE_PTR(name);
5157b0d8 1600 (void) session_save(s);
90a18413 1601
ae5e06bd
DH
1602 return 0;
1603}
1604
1605void session_drop_controller(Session *s) {
1606 assert(s);
1607
1608 if (!s->controller)
1609 return;
1610
3cde9e8f 1611 s->track = sd_bus_track_unref(s->track);
db72aea4 1612 session_set_type(s, s->original_type);
b12e5615 1613 session_release_controller(s, false);
5157b0d8 1614 (void) session_save(s);
b12e5615 1615 session_restore_vt(s);
ae5e06bd
DH
1616}
1617
fb6becb4
LP
1618static const char* const session_state_table[_SESSION_STATE_MAX] = {
1619 [SESSION_OPENING] = "opening",
6c75e317
ZJS
1620 [SESSION_ONLINE] = "online",
1621 [SESSION_ACTIVE] = "active",
1622 [SESSION_CLOSING] = "closing",
0604381b
LP
1623};
1624
1625DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState);
1626
20263082 1627static const char* const session_type_table[_SESSION_TYPE_MAX] = {
2c5859af 1628 [SESSION_UNSPECIFIED] = "unspecified",
6c75e317
ZJS
1629 [SESSION_TTY] = "tty",
1630 [SESSION_X11] = "x11",
1631 [SESSION_WAYLAND] = "wayland",
1632 [SESSION_MIR] = "mir",
1633 [SESSION_WEB] = "web",
20263082
LP
1634};
1635
1636DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType);
de07ab16 1637
55efac6c 1638static const char* const session_class_table[_SESSION_CLASS_MAX] = {
6c75e317
ZJS
1639 [SESSION_USER] = "user",
1640 [SESSION_GREETER] = "greeter",
e2acb67b 1641 [SESSION_LOCK_SCREEN] = "lock-screen",
6c75e317 1642 [SESSION_BACKGROUND] = "background",
55efac6c
LP
1643};
1644
1645DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass);
1646
de07ab16
LP
1647static const char* const kill_who_table[_KILL_WHO_MAX] = {
1648 [KILL_LEADER] = "leader",
6c75e317 1649 [KILL_ALL] = "all",
de07ab16
LP
1650};
1651
1652DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
3d0ef5c7
LP
1653
1654static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = {
6c75e317
ZJS
1655 [TTY_FROM_PAM] = "from-pam",
1656 [TTY_FROM_UTMP] = "from-utmp",
3d0ef5c7
LP
1657 [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent",
1658};
1659
1660DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity);