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