chiark / gitweb /
logind: enable limiting of user session scopes using pam context objects (#8397)
[elogind.git] / src / login / logind.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2011 Lennart Poettering
6 ***/
7
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #if 0 /// elogind needs the systems udev header
14 #include "libudev.h"
15 #else
16 #include <libudev.h>
17 #endif // 0
18 #include "sd-daemon.h"
19
20 #include "alloc-util.h"
21 #include "bus-error.h"
22 #include "bus-util.h"
23 //#include "cgroup-util.h"
24 #include "conf-parser.h"
25 #include "def.h"
26 #include "dirent-util.h"
27 #include "fd-util.h"
28 #include "format-util.h"
29 #include "fs-util.h"
30 #include "logind.h"
31 //#include "parse-util.h"
32 //#include "process-util.h"
33 #include "selinux-util.h"
34 #include "signal-util.h"
35 #include "strv.h"
36 #include "udev-util.h"
37 /// Additional includes needed by elogind
38 #include "cgroup.h"       // From src/core/
39 #include "elogind.h"
40 #include "label.h"
41 #include "musl_missing.h"
42 #include "process-util.h"
43 #include "cgroup-util.h"
44
45 static void manager_free(Manager *m);
46
47 static void manager_reset_config(Manager *m) {
48 #if 0 /// elogind does not support autospawning of vts
49         m->n_autovts = 6;
50         m->reserve_vt = 6;
51 #endif // 0
52         m->remove_ipc = true;
53         m->inhibit_delay_max = 5 * USEC_PER_SEC;
54         m->handle_power_key = HANDLE_POWEROFF;
55         m->handle_suspend_key = HANDLE_SUSPEND;
56         m->handle_hibernate_key = HANDLE_HIBERNATE;
57         m->handle_lid_switch = HANDLE_SUSPEND;
58         m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID;
59         m->handle_lid_switch_docked = HANDLE_IGNORE;
60         m->power_key_ignore_inhibited = false;
61         m->suspend_key_ignore_inhibited = false;
62         m->hibernate_key_ignore_inhibited = false;
63         m->lid_switch_ignore_inhibited = true;
64
65         m->holdoff_timeout_usec = 30 * USEC_PER_SEC;
66
67         m->idle_action_usec = 30 * USEC_PER_MINUTE;
68         m->idle_action = HANDLE_IGNORE;
69
70         m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
71         m->user_tasks_max = system_tasks_max_scale(DEFAULT_USER_TASKS_MAX_PERCENTAGE, 100U); /* 33% */
72         m->sessions_max = 8192;
73         m->inhibitors_max = 8192;
74
75         m->kill_user_processes = KILL_USER_PROCESSES;
76
77         m->kill_only_users = strv_free(m->kill_only_users);
78         m->kill_exclude_users = strv_free(m->kill_exclude_users);
79 }
80
81 static Manager *manager_new(void) {
82         Manager *m;
83         int r;
84
85         m = new0(Manager, 1);
86         if (!m)
87                 return NULL;
88
89         m->console_active_fd = -1;
90 #if 0 /// UNNEEDED by elogind
91         m->reserve_vt_fd = -1;
92 #endif // 0
93
94         m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
95
96         m->devices = hashmap_new(&string_hash_ops);
97         m->seats = hashmap_new(&string_hash_ops);
98         m->sessions = hashmap_new(&string_hash_ops);
99         m->users = hashmap_new(NULL);
100         m->inhibitors = hashmap_new(&string_hash_ops);
101         m->buttons = hashmap_new(&string_hash_ops);
102
103         m->user_units = hashmap_new(&string_hash_ops);
104         m->session_units = hashmap_new(&string_hash_ops);
105
106         if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units)
107                 goto fail;
108
109 #if 1 /// elogind needs some more data
110         r = elogind_manager_new(m);
111         if (r < 0)
112                 goto fail;
113 #endif // 1
114         m->udev = udev_new();
115         if (!m->udev)
116                 goto fail;
117
118         r = sd_event_default(&m->event);
119         if (r < 0)
120                 goto fail;
121
122         sd_event_set_watchdog(m->event, true);
123
124         manager_reset_config(m);
125
126         return m;
127
128 fail:
129         manager_free(m);
130         return NULL;
131 }
132
133 static void manager_free(Manager *m) {
134         Session *session;
135         User *u;
136         Device *d;
137         Seat *s;
138         Inhibitor *i;
139         Button *b;
140
141         if (!m)
142                 return;
143
144         while ((session = hashmap_first(m->sessions)))
145                 session_free(session);
146
147         while ((u = hashmap_first(m->users)))
148                 user_free(u);
149
150         while ((d = hashmap_first(m->devices)))
151                 device_free(d);
152
153         while ((s = hashmap_first(m->seats)))
154                 seat_free(s);
155
156         while ((i = hashmap_first(m->inhibitors)))
157                 inhibitor_free(i);
158
159         while ((b = hashmap_first(m->buttons)))
160                 button_free(b);
161
162         hashmap_free(m->devices);
163         hashmap_free(m->seats);
164         hashmap_free(m->sessions);
165         hashmap_free(m->users);
166         hashmap_free(m->inhibitors);
167         hashmap_free(m->buttons);
168
169         hashmap_free(m->user_units);
170         hashmap_free(m->session_units);
171
172         sd_event_source_unref(m->idle_action_event_source);
173         sd_event_source_unref(m->inhibit_timeout_source);
174         sd_event_source_unref(m->scheduled_shutdown_timeout_source);
175         sd_event_source_unref(m->nologin_timeout_source);
176         sd_event_source_unref(m->wall_message_timeout_source);
177
178         sd_event_source_unref(m->console_active_event_source);
179         sd_event_source_unref(m->udev_seat_event_source);
180         sd_event_source_unref(m->udev_device_event_source);
181         sd_event_source_unref(m->udev_vcsa_event_source);
182         sd_event_source_unref(m->udev_button_event_source);
183         sd_event_source_unref(m->lid_switch_ignore_event_source);
184
185         safe_close(m->console_active_fd);
186
187         udev_monitor_unref(m->udev_seat_monitor);
188         udev_monitor_unref(m->udev_device_monitor);
189         udev_monitor_unref(m->udev_vcsa_monitor);
190         udev_monitor_unref(m->udev_button_monitor);
191
192         udev_unref(m->udev);
193
194         if (m->unlink_nologin)
195                 (void) unlink_or_warn("/run/nologin");
196
197         bus_verify_polkit_async_registry_free(m->polkit_registry);
198
199         sd_bus_unref(m->bus);
200         sd_event_unref(m->event);
201
202 #if 0 /// elogind does not support autospawning of vts
203         safe_close(m->reserve_vt_fd);
204 #endif // 0
205 #if 1 /// elogind has to free its own data
206         elogind_manager_free(m);
207 #endif // 1
208
209         strv_free(m->kill_only_users);
210         strv_free(m->kill_exclude_users);
211
212         free(m->scheduled_shutdown_type);
213         free(m->scheduled_shutdown_tty);
214         free(m->wall_message);
215 #if 0 /// UNNEEDED by elogind
216         free(m->action_job);
217 #endif // 0
218         free(m);
219 }
220
221 static int manager_enumerate_devices(Manager *m) {
222         struct udev_list_entry *item = NULL, *first = NULL;
223         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
224         int r;
225
226         assert(m);
227
228         /* Loads devices from udev and creates seats for them as
229          * necessary */
230
231         e = udev_enumerate_new(m->udev);
232         if (!e)
233                 return -ENOMEM;
234
235         r = udev_enumerate_add_match_tag(e, "master-of-seat");
236         if (r < 0)
237                 return r;
238
239         r = udev_enumerate_add_match_is_initialized(e);
240         if (r < 0)
241                 return r;
242
243         r = udev_enumerate_scan_devices(e);
244         if (r < 0)
245                 return r;
246
247         first = udev_enumerate_get_list_entry(e);
248         udev_list_entry_foreach(item, first) {
249                 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
250                 int k;
251
252                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
253                 if (!d)
254                         return -ENOMEM;
255
256                 k = manager_process_seat_device(m, d);
257                 if (k < 0)
258                         r = k;
259         }
260
261         return r;
262 }
263
264 static int manager_enumerate_buttons(Manager *m) {
265         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
266         struct udev_list_entry *item = NULL, *first = NULL;
267         int r;
268
269         assert(m);
270
271         /* Loads buttons from udev */
272
273         if (manager_all_buttons_ignored(m))
274                 return 0;
275
276         e = udev_enumerate_new(m->udev);
277         if (!e)
278                 return -ENOMEM;
279
280         r = udev_enumerate_add_match_subsystem(e, "input");
281         if (r < 0)
282                 return r;
283
284         r = udev_enumerate_add_match_tag(e, "power-switch");
285         if (r < 0)
286                 return r;
287
288         r = udev_enumerate_add_match_is_initialized(e);
289         if (r < 0)
290                 return r;
291
292         r = udev_enumerate_scan_devices(e);
293         if (r < 0)
294                 return r;
295
296         first = udev_enumerate_get_list_entry(e);
297         udev_list_entry_foreach(item, first) {
298                 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
299                 int k;
300
301                 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
302                 if (!d)
303                         return -ENOMEM;
304
305                 k = manager_process_button_device(m, d);
306                 if (k < 0)
307                         r = k;
308         }
309
310         return r;
311 }
312
313 static int manager_enumerate_seats(Manager *m) {
314         _cleanup_closedir_ DIR *d = NULL;
315         struct dirent *de;
316         int r = 0;
317
318         assert(m);
319
320         /* This loads data about seats stored on disk, but does not
321          * actually create any seats. Removes data of seats that no
322          * longer exist. */
323
324         d = opendir("/run/systemd/seats");
325         if (!d) {
326                 if (errno == ENOENT)
327                         return 0;
328
329                 return log_error_errno(errno, "Failed to open /run/systemd/seats: %m");
330         }
331
332         FOREACH_DIRENT(de, d, return -errno) {
333                 Seat *s;
334                 int k;
335
336                 if (!dirent_is_file(de))
337                         continue;
338
339                 s = hashmap_get(m->seats, de->d_name);
340                 if (!s) {
341                         if (unlinkat(dirfd(d), de->d_name, 0) < 0)
342                                 log_warning("Failed to remove /run/systemd/seats/%s: %m",
343                                             de->d_name);
344                         continue;
345                 }
346
347                 k = seat_load(s);
348                 if (k < 0)
349                         r = k;
350         }
351
352         return r;
353 }
354
355 static int manager_enumerate_linger_users(Manager *m) {
356         _cleanup_closedir_ DIR *d = NULL;
357         struct dirent *de;
358         int r = 0;
359
360         assert(m);
361
362         d = opendir("/var/lib/elogind/linger");
363         if (!d) {
364                 if (errno == ENOENT)
365                         return 0;
366
367                 return log_error_errno(errno, "Failed to open /var/lib/elogind/linger/: %m");
368         }
369
370         FOREACH_DIRENT(de, d, return -errno) {
371                 int k;
372
373                 if (!dirent_is_file(de))
374                         continue;
375
376                 k = manager_add_user_by_name(m, de->d_name, NULL);
377                 if (k < 0) {
378                         log_notice_errno(k, "Couldn't add lingering user %s: %m", de->d_name);
379                         r = k;
380                 }
381         }
382
383         return r;
384 }
385
386 static int manager_enumerate_users(Manager *m) {
387         _cleanup_closedir_ DIR *d = NULL;
388         struct dirent *de;
389         int r, k;
390
391         assert(m);
392
393         /* Add lingering users */
394         r = manager_enumerate_linger_users(m);
395
396         /* Read in user data stored on disk */
397         d = opendir("/run/systemd/users");
398         if (!d) {
399                 if (errno == ENOENT)
400                         return 0;
401
402                 return log_error_errno(errno, "Failed to open /run/systemd/users: %m");
403         }
404
405         FOREACH_DIRENT(de, d, return -errno) {
406                 User *u;
407
408                 if (!dirent_is_file(de))
409                         continue;
410
411                 k = manager_add_user_by_name(m, de->d_name, &u);
412                 if (k < 0) {
413                         log_error_errno(k, "Failed to add user by file name %s: %m", de->d_name);
414
415                         r = k;
416                         continue;
417                 }
418
419                 user_add_to_gc_queue(u);
420
421                 k = user_load(u);
422                 if (k < 0)
423                         r = k;
424         }
425
426         return r;
427 }
428
429 static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) {
430         _cleanup_strv_free_ char **parts = NULL;
431         _cleanup_free_ char *id = NULL;
432         unsigned int major, minor;
433         int r;
434
435         parts = strv_split(fdname, "-");
436         if (!parts)
437                 return -ENOMEM;
438         if (strv_length(parts) != 5)
439                 return -EINVAL;
440
441         if (!streq(parts[0], "session"))
442                 return -EINVAL;
443         id = strdup(parts[1]);
444         if (!id)
445                 return -ENOMEM;
446
447         if (!streq(parts[2], "device"))
448                 return -EINVAL;
449         r = safe_atou(parts[3], &major) ||
450             safe_atou(parts[4], &minor);
451         if (r < 0)
452                 return r;
453
454         *dev = makedev(major, minor);
455         *session_id = TAKE_PTR(id);
456
457         return 0;
458 }
459
460 static int manager_attach_fds(Manager *m) {
461         _cleanup_strv_free_ char **fdnames = NULL;
462         int n, i, fd;
463
464         /* Upon restart, PID1 will send us back all fds of session devices
465          * that we previously opened. Each file descriptor is associated
466          * with a given session. The session ids are passed through FDNAMES. */
467
468         n = sd_listen_fds_with_names(true, &fdnames);
469         if (n <= 0)
470                 return n;
471
472         for (i = 0; i < n; i++) {
473                 _cleanup_free_ char *id = NULL;
474                 dev_t dev;
475                 struct stat st;
476                 SessionDevice *sd;
477                 Session *s;
478                 int r;
479
480                 fd = SD_LISTEN_FDS_START + i;
481
482                 r = parse_fdname(fdnames[i], &id, &dev);
483                 if (r < 0) {
484                         log_debug_errno(r, "Failed to parse fd name %s: %m", fdnames[i]);
485                         close_nointr(fd);
486                         continue;
487                 }
488
489                 s = hashmap_get(m->sessions, id);
490                 if (!s) {
491                         /* If the session doesn't exist anymore, the associated session
492                          * device attached to this fd doesn't either. Let's simply close
493                          * this fd. */
494                         log_debug("Failed to attach fd for unknown session: %s", id);
495                         close_nointr(fd);
496                         continue;
497                 }
498
499                 if (fstat(fd, &st) < 0) {
500                         /* The device is allowed to go away at a random point, in which
501                          * case fstat failing is expected. */
502                         log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id);
503                         close_nointr(fd);
504                         continue;
505                 }
506
507                 if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) {
508                         log_debug("Device fd doesn't point to the expected character device node");
509                         close_nointr(fd);
510                         continue;
511                 }
512
513                 sd = hashmap_get(s->devices, &dev);
514                 if (!sd) {
515                         /* Weird, we got an fd for a session device which wasn't
516                          * recorded in the session state file... */
517                         log_warning("Got fd for missing session device [%u:%u] in session %s",
518                                     major(dev), minor(dev), s->id);
519                         close_nointr(fd);
520                         continue;
521                 }
522
523                 log_debug("Attaching fd to session device [%u:%u] for session %s",
524                           major(dev), minor(dev), s->id);
525
526                 session_device_attach_fd(sd, fd, s->was_active);
527         }
528
529         return 0;
530 }
531
532 static int manager_enumerate_sessions(Manager *m) {
533         _cleanup_closedir_ DIR *d = NULL;
534         struct dirent *de;
535         int r = 0, k;
536
537         assert(m);
538
539         /* Read in session data stored on disk */
540         d = opendir("/run/systemd/sessions");
541         if (!d) {
542                 if (errno == ENOENT)
543                         return 0;
544
545                 return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m");
546         }
547
548         FOREACH_DIRENT(de, d, return -errno) {
549                 struct Session *s;
550
551                 if (!dirent_is_file(de))
552                         continue;
553
554                 if (!session_id_valid(de->d_name)) {
555                         log_warning("Invalid session file name '%s', ignoring.", de->d_name);
556                         r = -EINVAL;
557                         continue;
558                 }
559
560                 k = manager_add_session(m, de->d_name, &s);
561                 if (k < 0) {
562                         log_error_errno(k, "Failed to add session by file name %s: %m", de->d_name);
563                         r = k;
564                         continue;
565                 }
566
567                 session_add_to_gc_queue(s);
568
569                 k = session_load(s);
570                 if (k < 0)
571                         r = k;
572         }
573
574         /* We might be restarted and PID1 could have sent us back the
575          * session device fds we previously saved. */
576         k = manager_attach_fds(m);
577         if (k < 0)
578                 log_warning_errno(k, "Failed to reattach session device fds: %m");
579
580         return r;
581 }
582
583 static int manager_enumerate_inhibitors(Manager *m) {
584         _cleanup_closedir_ DIR *d = NULL;
585         struct dirent *de;
586         int r = 0;
587
588         assert(m);
589
590         d = opendir("/run/systemd/inhibit");
591         if (!d) {
592                 if (errno == ENOENT)
593                         return 0;
594
595                 return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m");
596         }
597
598         FOREACH_DIRENT(de, d, return -errno) {
599                 int k;
600                 Inhibitor *i;
601
602                 if (!dirent_is_file(de))
603                         continue;
604
605                 k = manager_add_inhibitor(m, de->d_name, &i);
606                 if (k < 0) {
607                         log_notice_errno(k, "Couldn't add inhibitor %s: %m", de->d_name);
608                         r = k;
609                         continue;
610                 }
611
612                 k = inhibitor_load(i);
613                 if (k < 0)
614                         r = k;
615         }
616
617         return r;
618 }
619
620 static int manager_dispatch_seat_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
621         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
622         Manager *m = userdata;
623
624         assert(m);
625
626         d = udev_monitor_receive_device(m->udev_seat_monitor);
627         if (!d)
628                 return -ENOMEM;
629
630         manager_process_seat_device(m, d);
631         return 0;
632 }
633
634 static int manager_dispatch_device_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
635         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
636         Manager *m = userdata;
637
638         assert(m);
639
640         d = udev_monitor_receive_device(m->udev_device_monitor);
641         if (!d)
642                 return -ENOMEM;
643
644         manager_process_seat_device(m, d);
645         return 0;
646 }
647
648 #if 0 /// UNNEEDED by elogind
649 static int manager_dispatch_vcsa_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
650         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
651         Manager *m = userdata;
652         const char *name;
653
654         assert(m);
655
656         d = udev_monitor_receive_device(m->udev_vcsa_monitor);
657         if (!d)
658                 return -ENOMEM;
659
660         name = udev_device_get_sysname(d);
661
662         /* Whenever a VCSA device is removed try to reallocate our
663          * VTs, to make sure our auto VTs never go away. */
664
665         if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
666                 seat_preallocate_vts(m->seat0);
667
668         return 0;
669 }
670 #endif // 0
671
672 static int manager_dispatch_button_udev(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
673         _cleanup_udev_device_unref_ struct udev_device *d = NULL;
674         Manager *m = userdata;
675
676         assert(m);
677
678         d = udev_monitor_receive_device(m->udev_button_monitor);
679         if (!d)
680                 return -ENOMEM;
681
682         manager_process_button_device(m, d);
683         return 0;
684 }
685
686 static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
687         Manager *m = userdata;
688
689         assert(m);
690         assert(m->seat0);
691         assert(m->console_active_fd == fd);
692
693         seat_read_active_vt(m->seat0);
694         return 0;
695 }
696
697 #if 0 /// UNNEEDED by elogind
698 static int manager_reserve_vt(Manager *m) {
699         _cleanup_free_ char *p = NULL;
700
701         assert(m);
702
703         if (m->reserve_vt <= 0)
704                 return 0;
705
706         if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
707                 return log_oom();
708
709         m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
710         if (m->reserve_vt_fd < 0) {
711
712                 /* Don't complain on VT-less systems */
713                 if (errno != ENOENT)
714                         log_warning_errno(errno, "Failed to pin reserved VT: %m");
715                 return -errno;
716         }
717
718         return 0;
719 }
720 #endif // 0
721
722 static int manager_connect_bus(Manager *m) {
723         int r;
724
725         assert(m);
726         assert(!m->bus);
727
728         r = sd_bus_default_system(&m->bus);
729         if (r < 0)
730                 return log_error_errno(r, "Failed to connect to system bus: %m");
731
732         r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
733         if (r < 0)
734                 return log_error_errno(r, "Failed to add manager object vtable: %m");
735
736         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
737         if (r < 0)
738                 return log_error_errno(r, "Failed to add seat object vtable: %m");
739
740         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
741         if (r < 0)
742                 return log_error_errno(r, "Failed to add seat enumerator: %m");
743
744         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
745         if (r < 0)
746                 return log_error_errno(r, "Failed to add session object vtable: %m");
747
748         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
749         if (r < 0)
750                 return log_error_errno(r, "Failed to add session enumerator: %m");
751
752         r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
753         if (r < 0)
754                 return log_error_errno(r, "Failed to add user object vtable: %m");
755
756         r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
757         if (r < 0)
758                 return log_error_errno(r, "Failed to add user enumerator: %m");
759
760 #if 0 /// elogind does not support systemd as PID 1
761         r = sd_bus_match_signal_async(
762                         m->bus,
763                         NULL,
764                         "org.freedesktop.systemd1",
765                         "/org/freedesktop/systemd1",
766                         "org.freedesktop.systemd1.Manager",
767                         "JobRemoved",
768                         match_job_removed, NULL, m);
769         if (r < 0)
770                 return log_error_errno(r, "Failed to request match for JobRemoved: %m");
771
772         r = sd_bus_match_signal_async(
773                         m->bus,
774                         NULL,
775                         "org.freedesktop.systemd1",
776                         "/org/freedesktop/systemd1",
777                         "org.freedesktop.systemd1.Manager",
778                         "UnitRemoved",
779                         match_unit_removed, NULL, m);
780         if (r < 0)
781                 return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
782
783         r = sd_bus_match_signal_async(
784                         m->bus,
785                         NULL,
786                         "org.freedesktop.systemd1",
787                         NULL,
788                         "org.freedesktop.DBus.Properties",
789                         "PropertiesChanged",
790                         match_properties_changed, NULL, m);
791         if (r < 0)
792                 return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
793
794         r = sd_bus_match_signal_async(
795                         m->bus,
796                         NULL,
797                         "org.freedesktop.systemd1",
798                         "/org/freedesktop/systemd1",
799                         "org.freedesktop.systemd1.Manager",
800                         "Reloading",
801                         match_reloading, NULL, m);
802         if (r < 0)
803                 return log_error_errno(r, "Failed to request match for Reloading: %m");
804
805         r = sd_bus_call_method_async(
806                         m->bus,
807                         NULL,
808                         "org.freedesktop.systemd1",
809                         "/org/freedesktop/systemd1",
810                         "org.freedesktop.systemd1.Manager",
811                         "Subscribe",
812                         NULL, NULL,
813                         NULL);
814 #endif // 0
815         if (r < 0)
816                 return log_error_errno(r, "Failed to enable subscription: %m");
817
818         r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
819         if (r < 0)
820                 return log_error_errno(r, "Failed to request name: %m");
821
822         r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
823         if (r < 0)
824                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
825
826 #if 0 /// elogind has to setup its release agent
827         return 0;
828 #else
829         r = elogind_setup_cgroups_agent(m);
830
831         return r;
832 #endif // 0
833 }
834
835 static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) {
836         Manager *m = data;
837         Session *active, *iter;
838
839         /*
840          * We got a VT-switch signal and we have to acknowledge it immediately.
841          * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately,
842          * old user-space might run multiple sessions on a single VT, *sigh*.
843          * Therefore, we have to iterate all sessions and find one with a vtfd
844          * on the requested VT.
845          * As only VTs with active controllers have VT_PROCESS set, our current
846          * notion of the active VT might be wrong (for instance if the switch
847          * happens while we setup VT_PROCESS). Therefore, read the current VT
848          * first and then use s->active->vtnr as reference. Note that this is
849          * not racy, as no further VT-switch can happen as long as we're in
850          * synchronous VT_PROCESS mode.
851          */
852
853         assert(m->seat0);
854         seat_read_active_vt(m->seat0);
855
856         active = m->seat0->active;
857         if (!active || active->vtnr < 1) {
858                 log_warning("Received VT_PROCESS signal without a registered session on that VT.");
859                 return 0;
860         }
861
862         if (active->vtfd >= 0) {
863                 session_leave_vt(active);
864         } else {
865                 LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) {
866                         if (iter->vtnr == active->vtnr && iter->vtfd >= 0) {
867                                 session_leave_vt(iter);
868                                 break;
869                         }
870                 }
871         }
872
873         return 0;
874 }
875
876 static int manager_connect_console(Manager *m) {
877         int r;
878
879         assert(m);
880         assert(m->console_active_fd < 0);
881
882         /* On certain architectures (S390 and Xen, and containers),
883            /dev/tty0 does not exist, so don't fail if we can't open
884            it. */
885         if (access("/dev/tty0", F_OK) < 0)
886                 return 0;
887
888         m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
889         if (m->console_active_fd < 0) {
890
891                 /* On some systems the device node /dev/tty0 may exist
892                  * even though /sys/class/tty/tty0 does not. */
893                 if (errno == ENOENT)
894                         return 0;
895
896                 return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
897         }
898
899         r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
900         if (r < 0) {
901                 log_error("Failed to watch foreground console");
902                 return r;
903         }
904
905         /*
906          * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
907          * as VT-acquire signal. We ignore any acquire-events (yes, we still
908          * have to provide a valid signal-number for it!) and acknowledge all
909          * release events immediately.
910          */
911
912         if (SIGRTMIN + 1 > SIGRTMAX) {
913                 log_error("Not enough real-time signals available: %u-%u", SIGRTMIN, SIGRTMAX);
914                 return -EINVAL;
915         }
916
917         assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0);
918         assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0);
919
920         r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
921         if (r < 0)
922                 return r;
923
924         return 0;
925 }
926
927 static int manager_connect_udev(Manager *m) {
928         int r;
929
930         assert(m);
931         assert(!m->udev_seat_monitor);
932         assert(!m->udev_device_monitor);
933         assert(!m->udev_vcsa_monitor);
934         assert(!m->udev_button_monitor);
935
936         m->udev_seat_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
937         if (!m->udev_seat_monitor)
938                 return -ENOMEM;
939
940         r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat");
941         if (r < 0)
942                 return r;
943
944         r = udev_monitor_enable_receiving(m->udev_seat_monitor);
945         if (r < 0)
946                 return r;
947
948         r = sd_event_add_io(m->event, &m->udev_seat_event_source, udev_monitor_get_fd(m->udev_seat_monitor), EPOLLIN, manager_dispatch_seat_udev, m);
949         if (r < 0)
950                 return r;
951
952         m->udev_device_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
953         if (!m->udev_device_monitor)
954                 return -ENOMEM;
955
956         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "input", NULL);
957         if (r < 0)
958                 return r;
959
960         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "graphics", NULL);
961         if (r < 0)
962                 return r;
963
964         r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_device_monitor, "drm", NULL);
965         if (r < 0)
966                 return r;
967
968         r = udev_monitor_enable_receiving(m->udev_device_monitor);
969         if (r < 0)
970                 return r;
971
972         r = sd_event_add_io(m->event, &m->udev_device_event_source, udev_monitor_get_fd(m->udev_device_monitor), EPOLLIN, manager_dispatch_device_udev, m);
973         if (r < 0)
974                 return r;
975
976         /* Don't watch keys if nobody cares */
977         if (!manager_all_buttons_ignored(m)) {
978                 m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
979                 if (!m->udev_button_monitor)
980                         return -ENOMEM;
981
982                 r = udev_monitor_filter_add_match_tag(m->udev_button_monitor, "power-switch");
983                 if (r < 0)
984                         return r;
985
986                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_button_monitor, "input", NULL);
987                 if (r < 0)
988                         return r;
989
990                 r = udev_monitor_enable_receiving(m->udev_button_monitor);
991                 if (r < 0)
992                         return r;
993
994                 r = sd_event_add_io(m->event, &m->udev_button_event_source, udev_monitor_get_fd(m->udev_button_monitor), EPOLLIN, manager_dispatch_button_udev, m);
995                 if (r < 0)
996                         return r;
997         }
998
999         /* Don't bother watching VCSA devices, if nobody cares */
1000 #if 0 /// elogind does not support autospawning of vts
1001         if (m->n_autovts > 0 && m->console_active_fd >= 0) {
1002
1003                 m->udev_vcsa_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
1004                 if (!m->udev_vcsa_monitor)
1005                         return -ENOMEM;
1006
1007                 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_vcsa_monitor, "vc", NULL);
1008                 if (r < 0)
1009                         return r;
1010
1011                 r = udev_monitor_enable_receiving(m->udev_vcsa_monitor);
1012                 if (r < 0)
1013                         return r;
1014
1015                 r = sd_event_add_io(m->event, &m->udev_vcsa_event_source, udev_monitor_get_fd(m->udev_vcsa_monitor), EPOLLIN, manager_dispatch_vcsa_udev, m);
1016                 if (r < 0)
1017                         return r;
1018         }
1019 #endif // 0
1020
1021         return 0;
1022 }
1023
1024 static void manager_gc(Manager *m, bool drop_not_started) {
1025         Seat *seat;
1026         Session *session;
1027         User *user;
1028
1029         assert(m);
1030
1031         while ((seat = m->seat_gc_queue)) {
1032                 LIST_REMOVE(gc_queue, m->seat_gc_queue, seat);
1033                 seat->in_gc_queue = false;
1034
1035                 if (seat_may_gc(seat, drop_not_started)) {
1036                         seat_stop(seat, false);
1037                         seat_free(seat);
1038                 }
1039         }
1040
1041         while ((session = m->session_gc_queue)) {
1042                 LIST_REMOVE(gc_queue, m->session_gc_queue, session);
1043                 session->in_gc_queue = false;
1044
1045                 /* First, if we are not closing yet, initiate stopping */
1046                 if (session_may_gc(session, drop_not_started) &&
1047                     session_get_state(session) != SESSION_CLOSING)
1048                         session_stop(session, false);
1049
1050                 /* Normally, this should make the session referenced
1051                  * again, if it doesn't then let's get rid of it
1052                  * immediately */
1053                 if (session_may_gc(session, drop_not_started)) {
1054                         session_finalize(session);
1055                         session_free(session);
1056                 }
1057         }
1058
1059         while ((user = m->user_gc_queue)) {
1060                 LIST_REMOVE(gc_queue, m->user_gc_queue, user);
1061                 user->in_gc_queue = false;
1062
1063                 /* First step: queue stop jobs */
1064                 if (user_may_gc(user, drop_not_started))
1065                         user_stop(user, false);
1066
1067                 /* Second step: finalize user */
1068                 if (user_may_gc(user, drop_not_started)) {
1069                         user_finalize(user);
1070                         user_free(user);
1071                 }
1072         }
1073 }
1074
1075 static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) {
1076         Manager *m = userdata;
1077         struct dual_timestamp since;
1078         usec_t n, elapse;
1079         int r;
1080
1081         assert(m);
1082
1083         if (m->idle_action == HANDLE_IGNORE ||
1084             m->idle_action_usec <= 0)
1085                 return 0;
1086
1087         n = now(CLOCK_MONOTONIC);
1088
1089         r = manager_get_idle_hint(m, &since);
1090         if (r <= 0)
1091                 /* Not idle. Let's check if after a timeout it might be idle then. */
1092                 elapse = n + m->idle_action_usec;
1093         else {
1094                 /* Idle! Let's see if it's time to do something, or if
1095                  * we shall sleep for longer. */
1096
1097                 if (n >= since.monotonic + m->idle_action_usec &&
1098                     (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) {
1099                         log_info("System idle. Taking action.");
1100
1101                         manager_handle_action(m, 0, m->idle_action, false, false);
1102                         m->idle_action_not_before_usec = n;
1103                 }
1104
1105                 elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec;
1106         }
1107
1108         if (!m->idle_action_event_source) {
1109
1110                 r = sd_event_add_time(
1111                                 m->event,
1112                                 &m->idle_action_event_source,
1113                                 CLOCK_MONOTONIC,
1114                                 elapse, USEC_PER_SEC*30,
1115                                 manager_dispatch_idle_action, m);
1116                 if (r < 0)
1117                         return log_error_errno(r, "Failed to add idle event source: %m");
1118
1119                 r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
1120                 if (r < 0)
1121                         return log_error_errno(r, "Failed to set idle event source priority: %m");
1122         } else {
1123                 r = sd_event_source_set_time(m->idle_action_event_source, elapse);
1124                 if (r < 0)
1125                         return log_error_errno(r, "Failed to set idle event timer: %m");
1126
1127                 r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT);
1128                 if (r < 0)
1129                         return log_error_errno(r, "Failed to enable idle event timer: %m");
1130         }
1131
1132         return 0;
1133 }
1134
1135 static int manager_parse_config_file(Manager *m) {
1136 #if 0 /// elogind parses its own config file
1137         assert(m);
1138
1139         return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf",
1140                                         CONF_PATHS_NULSTR("systemd/logind.conf.d"),
1141                                         "Login\0",
1142                                         config_item_perf_lookup, logind_gperf_lookup,
1143 #else
1144          const char* logind_conf = getenv("ELOGIND_CONF_FILE");
1145
1146          assert(m);
1147
1148          if (!logind_conf)
1149                  logind_conf = PKGSYSCONFDIR "/logind.conf";
1150
1151          return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0",
1152                              config_item_perf_lookup, logind_gperf_lookup,
1153 #endif // 0
1154                                         CONFIG_PARSE_WARN, m);
1155 }
1156
1157 static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
1158         Manager *m = userdata;
1159         int r;
1160
1161         manager_reset_config(m);
1162         r = manager_parse_config_file(m);
1163         if (r < 0)
1164                 log_warning_errno(r, "Failed to parse config file, using defaults: %m");
1165         else
1166                 log_info("Config file reloaded.");
1167
1168 #if 1 /// elogind needs an Add-On for sleep configuration
1169         elogind_manager_reset_config(m);
1170 #endif // 1
1171         return 0;
1172 }
1173
1174 static int manager_startup(Manager *m) {
1175         int r;
1176         Seat *seat;
1177         Session *session;
1178         User *user;
1179         Button *button;
1180         Inhibitor *inhibitor;
1181         Iterator i;
1182
1183         assert(m);
1184
1185         assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0);
1186
1187         r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m);
1188         if (r < 0)
1189                 return log_error_errno(r, "Failed to register SIGHUP handler: %m");
1190
1191 #if 1 /// elogind needs some extra preparations before connecting...
1192         elogind_manager_startup(m);
1193 #endif // 1
1194         /* Connect to console */
1195         r = manager_connect_console(m);
1196         if (r < 0)
1197                 return r;
1198
1199         /* Connect to udev */
1200         r = manager_connect_udev(m);
1201         if (r < 0)
1202                 return log_error_errno(r, "Failed to create udev watchers: %m");
1203
1204         /* Connect to the bus */
1205         r = manager_connect_bus(m);
1206         if (r < 0)
1207                 return r;
1208
1209         /* Instantiate magic seat 0 */
1210         r = manager_add_seat(m, "seat0", &m->seat0);
1211         if (r < 0)
1212                 return log_error_errno(r, "Failed to add seat0: %m");
1213
1214         r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec);
1215         if (r < 0)
1216                 log_warning_errno(r, "Failed to set up lid switch ignore event source: %m");
1217
1218         /* Deserialize state */
1219         r = manager_enumerate_devices(m);
1220         if (r < 0)
1221                 log_warning_errno(r, "Device enumeration failed: %m");
1222
1223         r = manager_enumerate_seats(m);
1224         if (r < 0)
1225                 log_warning_errno(r, "Seat enumeration failed: %m");
1226
1227         r = manager_enumerate_users(m);
1228         if (r < 0)
1229                 log_warning_errno(r, "User enumeration failed: %m");
1230
1231         r = manager_enumerate_sessions(m);
1232         if (r < 0)
1233                 log_warning_errno(r, "Session enumeration failed: %m");
1234
1235         r = manager_enumerate_inhibitors(m);
1236         if (r < 0)
1237                 log_warning_errno(r, "Inhibitor enumeration failed: %m");
1238
1239         r = manager_enumerate_buttons(m);
1240         if (r < 0)
1241                 log_warning_errno(r, "Button enumeration failed: %m");
1242
1243         /* Remove stale objects before we start them */
1244         manager_gc(m, false);
1245
1246         /* Reserve the special reserved VT */
1247 #if 0 /// elogind does not support autospawning of vts
1248         manager_reserve_vt(m);
1249 #endif // 0
1250
1251         /* And start everything */
1252         HASHMAP_FOREACH(seat, m->seats, i)
1253                 seat_start(seat);
1254
1255         HASHMAP_FOREACH(user, m->users, i)
1256                 user_start(user);
1257
1258         HASHMAP_FOREACH(session, m->sessions, i)
1259                 session_start(session, NULL);
1260
1261         HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
1262                 inhibitor_start(inhibitor);
1263
1264         HASHMAP_FOREACH(button, m->buttons, i)
1265                 button_check_switches(button);
1266
1267         manager_dispatch_idle_action(NULL, 0, m);
1268
1269         return 0;
1270 }
1271
1272 static int manager_run(Manager *m) {
1273         int r;
1274
1275         assert(m);
1276
1277         for (;;) {
1278                 r = sd_event_get_state(m->event);
1279                 if (r < 0)
1280                         return r;
1281                 if (r == SD_EVENT_FINISHED)
1282                         return 0;
1283
1284                 manager_gc(m, true);
1285
1286                 r = manager_dispatch_delayed(m, false);
1287                 if (r < 0)
1288                         return r;
1289                 if (r > 0)
1290                         continue;
1291
1292                 r = sd_event_run(m->event, (uint64_t) -1);
1293                 if (r < 0)
1294                         return r;
1295         }
1296 }
1297
1298 int main(int argc, char *argv[]) {
1299         Manager *m = NULL;
1300         int r;
1301
1302 #if 1 /// perform extra checks for elogind startup
1303         r = elogind_startup(argc, argv);
1304         if (r)
1305                 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1306 #endif // 1
1307         elogind_set_program_name(argv[0]);
1308         log_set_target(LOG_TARGET_AUTO);
1309         log_set_facility(LOG_AUTH);
1310         log_parse_environment();
1311 #if ENABLE_DEBUG_ELOGIND
1312         log_set_max_level(LOG_DEBUG);
1313         log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1314 #endif // ENABLE_DEBUG_ELOGIND
1315         log_open();
1316
1317         umask(0022);
1318
1319 #if 0 /// elogind has some extra functionality at startup, argc can be != 1
1320         if (argc != 1) {
1321                 log_error("This program takes no arguments.");
1322                 r = -EINVAL;
1323                 goto finish;
1324         }
1325 #endif // 0
1326
1327         r = mac_selinux_init();
1328         if (r < 0) {
1329                 log_error_errno(r, "Could not initialize labelling: %m");
1330                 goto finish;
1331         }
1332
1333         /* Always create the directories people can create inotify
1334          * watches in. Note that some applications might check for the
1335          * existence of /run/systemd/seats/ to determine whether
1336          * logind is available, so please always make sure this check
1337          * stays in. */
1338 #if 0 /// elogind can not rely on systemd to help, so we need a bit more effort than this
1339         mkdir_label("/run/systemd/seats", 0755);
1340         mkdir_label("/run/systemd/users", 0755);
1341         mkdir_label("/run/systemd/sessions", 0755);
1342 #else
1343         r = mkdir_label("/run/systemd", 0755);
1344         if ( (r < 0) && (-EEXIST != r) )
1345                 return log_error_errno(r, "Failed to create /run/systemd : %m");
1346         r = mkdir_label("/run/systemd/seats", 0755);
1347         if ( r < 0 && (-EEXIST != r) )
1348                 return log_error_errno(r, "Failed to create /run/systemd/seats : %m");
1349         r = mkdir_label("/run/systemd/users", 0755);
1350         if ( r < 0 && (-EEXIST != r) )
1351                 return log_error_errno(r, "Failed to create /run/systemd/users : %m");
1352         r = mkdir_label("/run/systemd/sessions", 0755);
1353         if ( r < 0 && (-EEXIST != r) )
1354                 return log_error_errno(r, "Failed to create /run/systemd/sessions : %m");
1355         r = mkdir_label("/run/systemd/machines", 0755);
1356         if ( r < 0 && (-EEXIST != r) )
1357                 return log_error_errno(r, "Failed to create /run/systemd/machines : %m");
1358 #endif // 0
1359
1360         m = manager_new();
1361         if (!m) {
1362                 r = log_oom();
1363                 goto finish;
1364         }
1365
1366         manager_parse_config_file(m);
1367
1368 #if 1 /// elogind needs an Add-On for sleep configuration
1369         elogind_manager_reset_config(m);
1370 #endif // 1
1371         r = manager_startup(m);
1372         if (r < 0) {
1373                 log_error_errno(r, "Failed to fully start up daemon: %m");
1374                 goto finish;
1375         }
1376
1377         log_debug("elogind running as pid "PID_FMT, getpid_cached());
1378
1379         sd_notify(false,
1380                   "READY=1\n"
1381                   "STATUS=Processing requests...");
1382
1383         r = manager_run(m);
1384
1385         log_debug("elogind stopped as pid "PID_FMT, getpid_cached());
1386
1387 finish:
1388         sd_notify(false,
1389                   "STOPPING=1\n"
1390                   "STATUS=Shutting down...");
1391
1392         manager_free(m);
1393
1394         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1395 }