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