]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/home/homed-manager.c
systemd-analyze: added the verb unit-shell to spawn and attach shell
[thirdparty/systemd.git] / src / home / homed-manager.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <grp.h>
4#include <linux/fscrypt.h>
5#include <linux/magic.h>
6#include <math.h>
7#include <openssl/pem.h>
8#include <pwd.h>
9#include <sys/inotify.h>
10#include <sys/ioctl.h>
11#include <sys/stat.h>
12#include <unistd.h>
13
14#include "sd-bus.h"
15#include "sd-event.h"
16#include "sd-gpt.h"
17#include "sd-id128.h"
18
19#include "alloc-util.h"
20#include "btrfs-util.h"
21#include "bus-common-errors.h"
22#include "bus-error.h"
23#include "bus-log-control-api.h"
24#include "bus-object.h"
25#include "clean-ipc.h"
26#include "common-signal.h"
27#include "conf-files.h"
28#include "device-util.h"
29#include "dirent-util.h"
30#include "errno-util.h"
31#include "fd-util.h"
32#include "fdset.h"
33#include "fileio.h"
34#include "format-util.h"
35#include "fs-util.h"
36#include "glyph-util.h"
37#include "home-util.h"
38#include "homed-conf.h"
39#include "homed-home.h"
40#include "homed-manager.h"
41#include "homed-manager-bus.h"
42#include "homed-operation.h"
43#include "homed-varlink.h"
44#include "mkdir.h"
45#include "notify-recv.h"
46#include "openssl-util.h"
47#include "ordered-set.h"
48#include "quota-util.h"
49#include "random-util.h"
50#include "resize-fs.h"
51#include "rm-rf.h"
52#include "set.h"
53#include "siphash24.h"
54#include "sort-util.h"
55#include "stat-util.h"
56#include "string-util.h"
57#include "strv.h"
58#include "sync-util.h"
59#include "time-util.h"
60#include "tmpfile-util.h"
61#include "udev-util.h"
62#include "user-record.h"
63#include "user-record-sign.h"
64#include "user-record-util.h"
65#include "user-util.h"
66#include "varlink-io.systemd.UserDatabase.h"
67#include "varlink-io.systemd.service.h"
68#include "varlink-util.h"
69
70/* Where to look for private/public keys that are used to sign the user records. We are not using
71 * CONF_PATHS_NULSTR() here since we want to insert /var/lib/systemd/home/ in the middle. And we insert that
72 * since we want to auto-generate a persistent private/public key pair if we need to. */
73#define KEY_PATHS_NULSTR \
74 "/etc/systemd/home/\0" \
75 "/run/systemd/home/\0" \
76 "/var/lib/systemd/home/\0" \
77 "/usr/local/lib/systemd/home/\0" \
78 "/usr/lib/systemd/home/\0"
79
80static bool uid_is_home(uid_t uid) {
81 return uid >= HOME_UID_MIN && uid <= HOME_UID_MAX;
82}
83/* Takes a value generated randomly or by hashing and turns it into a UID in the right range */
84
85#define UID_CLAMP_INTO_HOME_RANGE(rnd) (((uid_t) (rnd) % (HOME_UID_MAX - HOME_UID_MIN + 1)) + HOME_UID_MIN)
86
87DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_uid_hash_ops, void, trivial_hash_func, trivial_compare_func, Home, home_free);
88DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_worker_pid_hash_ops, PidRef, pidref_hash_func, pidref_compare_func, Home, home_free);
89DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, path_hash_func, path_compare, Home, home_free);
90
91static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata);
92static int manager_gc_images(Manager *m);
93static int manager_gc_blob(Manager *m);
94static int manager_enumerate_images(Manager *m);
95static int manager_assess_image(Manager *m, int dir_fd, const char *dir_path, const char *dentry_name);
96static void manager_revalidate_image(Manager *m, Home *h);
97
98static void manager_watch_home(Manager *m) {
99 struct statfs sfs;
100 int r;
101
102 assert(m);
103
104 m->inotify_event_source = sd_event_source_disable_unref(m->inotify_event_source);
105 m->scan_slash_home = false;
106
107 if (statfs(get_home_root(), &sfs) < 0) {
108 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
109 "Failed to statfs() %s directory, disabling automatic scanning.", get_home_root());
110 return;
111 }
112
113 if (is_network_fs(&sfs)) {
114 log_info("%s is a network file system, disabling automatic scanning.", get_home_root());
115 return;
116 }
117
118 if (is_fs_type(&sfs, AUTOFS_SUPER_MAGIC)) {
119 log_info("%s is on autofs, disabling automatic scanning.", get_home_root());
120 return;
121 }
122
123 m->scan_slash_home = true;
124
125 r = sd_event_add_inotify(m->event, &m->inotify_event_source, get_home_root(),
126 IN_CREATE|IN_CLOSE_WRITE|IN_DELETE_SELF|IN_MOVE_SELF|IN_ONLYDIR|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE,
127 on_home_inotify, m);
128 if (r < 0)
129 log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
130 "Failed to create inotify watch on %s, ignoring.", get_home_root());
131
132 (void) sd_event_source_set_description(m->inotify_event_source, "home-inotify");
133
134 log_info("Watching %s.", get_home_root());
135}
136
137static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata) {
138 _cleanup_free_ char *j = NULL;
139 Manager *m = ASSERT_PTR(userdata);
140 const char *e, *n;
141
142 assert(event);
143
144 if ((event->mask & (IN_Q_OVERFLOW|IN_MOVE_SELF|IN_DELETE_SELF|IN_IGNORED|IN_UNMOUNT)) != 0) {
145
146 if (FLAGS_SET(event->mask, IN_Q_OVERFLOW))
147 log_debug("%s inotify queue overflow, rescanning.", get_home_root());
148 else if (FLAGS_SET(event->mask, IN_MOVE_SELF))
149 log_info("%s moved or renamed, recreating watch and rescanning.", get_home_root());
150 else if (FLAGS_SET(event->mask, IN_DELETE_SELF))
151 log_info("%s deleted, recreating watch and rescanning.", get_home_root());
152 else if (FLAGS_SET(event->mask, IN_UNMOUNT))
153 log_info("%s unmounted, recreating watch and rescanning.", get_home_root());
154 else if (FLAGS_SET(event->mask, IN_IGNORED))
155 log_info("%s watch invalidated, recreating watch and rescanning.", get_home_root());
156
157 manager_watch_home(m);
158 (void) manager_gc_images(m);
159 (void) manager_enumerate_images(m);
160 (void) bus_manager_emit_auto_login_changed(m);
161 return 0;
162 }
163
164 /* For the other inotify events, let's ignore all events for file names that don't match our
165 * expectations */
166 if (isempty(event->name))
167 return 0;
168 e = endswith(event->name, FLAGS_SET(event->mask, IN_ISDIR) ? ".homedir" : ".home");
169 if (!e)
170 return 0;
171
172 n = strndupa_safe(event->name, e - event->name);
173 if (!suitable_user_name(n))
174 return 0;
175
176 j = path_join(get_home_root(), event->name);
177 if (!j)
178 return log_oom();
179
180 if ((event->mask & (IN_CREATE|IN_CLOSE_WRITE|IN_MOVED_TO)) != 0) {
181 if (FLAGS_SET(event->mask, IN_CREATE))
182 log_debug("%s has been created, having a look.", j);
183 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
184 log_debug("%s has been modified, having a look.", j);
185 else if (FLAGS_SET(event->mask, IN_MOVED_TO))
186 log_debug("%s has been moved in, having a look.", j);
187
188 (void) manager_assess_image(m, /* dir_fd= */ -EBADF, get_home_root(), event->name);
189 (void) bus_manager_emit_auto_login_changed(m);
190 }
191
192 if ((event->mask & (IN_DELETE | IN_CLOSE_WRITE | IN_MOVED_FROM)) != 0) {
193 Home *h;
194
195 if (FLAGS_SET(event->mask, IN_DELETE))
196 log_debug("%s has been deleted, revalidating.", j);
197 else if (FLAGS_SET(event->mask, IN_CLOSE_WRITE))
198 log_debug("%s has been closed after writing, revalidating.", j);
199 else if (FLAGS_SET(event->mask, IN_MOVED_FROM))
200 log_debug("%s has been moved away, revalidating.", j);
201
202 h = hashmap_get(m->homes_by_name, n);
203 if (h && streq(h->user_name, n)) {
204 manager_revalidate_image(m, h);
205 (void) bus_manager_emit_auto_login_changed(m);
206 }
207 }
208
209 return 0;
210}
211
212static int sigusr1_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
213 Manager *m = ASSERT_PTR(userdata);
214 assert(s);
215
216 /* If clients send use SIGUSR1 we'll explicitly rescan for home directories. This is useful in some
217 * cases where inotify isn't good enough, for example if /home/ is overmunted. */
218 manager_watch_home(m);
219 (void) manager_gc_images(m);
220 (void) manager_enumerate_images(m);
221 (void) bus_manager_emit_auto_login_changed(m);
222
223 return 0;
224}
225
226int manager_new(Manager **ret) {
227 _cleanup_(manager_freep) Manager *m = NULL;
228 int r;
229
230 assert(ret);
231
232 m = new(Manager, 1);
233 if (!m)
234 return -ENOMEM;
235
236 *m = (Manager) {
237 .default_storage = _USER_STORAGE_INVALID,
238 .rebalance_interval_usec = 2 * USEC_PER_MINUTE, /* initially, rebalance every 2min */
239 };
240
241 r = manager_parse_config_file(m);
242 if (r < 0)
243 return r;
244
245 r = sd_event_default(&m->event);
246 if (r < 0)
247 return r;
248
249 r = sd_event_set_signal_exit(m->event, true);
250 if (r < 0)
251 return r;
252
253 r = sd_event_add_memory_pressure(m->event, /* ret= */ NULL, /* callback= */ NULL, /* userdata= */ NULL);
254 if (r < 0)
255 log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_WARNING, r,
256 "Failed to allocate memory pressure watch, ignoring: %m");
257
258 r = sd_event_add_signal(m->event, /* ret= */ NULL, (SIGRTMIN+18)|SD_EVENT_SIGNAL_PROCMASK, sigrtmin18_handler, /* userdata = */ NULL);
259 if (r < 0)
260 return r;
261
262 r = sd_event_add_signal(m->event, /* ret= */ NULL, SIGUSR1|SD_EVENT_SIGNAL_PROCMASK, sigusr1_handler, m);
263 if (r < 0)
264 return r;
265
266 (void) sd_event_set_watchdog(m->event, true);
267
268 m->homes_by_uid = hashmap_new(&homes_by_uid_hash_ops);
269 if (!m->homes_by_uid)
270 return -ENOMEM;
271
272 m->homes_by_name = hashmap_new(&string_hash_ops);
273 if (!m->homes_by_name)
274 return -ENOMEM;
275
276 m->homes_by_worker_pid = hashmap_new(&homes_by_worker_pid_hash_ops);
277 if (!m->homes_by_worker_pid)
278 return -ENOMEM;
279
280 m->homes_by_sysfs = hashmap_new(&homes_by_sysfs_hash_ops);
281 if (!m->homes_by_sysfs)
282 return -ENOMEM;
283
284 *ret = TAKE_PTR(m);
285 return 0;
286}
287
288Manager* manager_free(Manager *m) {
289 Home *h;
290
291 assert(m);
292
293 HASHMAP_FOREACH(h, m->homes_by_worker_pid)
294 (void) home_wait_for_worker(h);
295
296 m->bus = sd_bus_flush_close_unref(m->bus);
297 m->polkit_registry = hashmap_free(m->polkit_registry);
298
299 m->device_monitor = sd_device_monitor_unref(m->device_monitor);
300
301 m->inotify_event_source = sd_event_source_unref(m->inotify_event_source);
302 m->notify_socket_path = mfree(m->notify_socket_path);
303 m->deferred_rescan_event_source = sd_event_source_unref(m->deferred_rescan_event_source);
304 m->deferred_gc_event_source = sd_event_source_unref(m->deferred_gc_event_source);
305 m->deferred_auto_login_event_source = sd_event_source_unref(m->deferred_auto_login_event_source);
306 m->rebalance_event_source = sd_event_source_unref(m->rebalance_event_source);
307
308 m->event = sd_event_unref(m->event);
309
310 m->homes_by_uid = hashmap_free(m->homes_by_uid);
311 m->homes_by_name = hashmap_free(m->homes_by_name);
312 m->homes_by_worker_pid = hashmap_free(m->homes_by_worker_pid);
313 m->homes_by_sysfs = hashmap_free(m->homes_by_sysfs);
314
315 if (m->private_key)
316 EVP_PKEY_free(m->private_key);
317
318 hashmap_free(m->public_keys);
319
320 sd_varlink_server_unref(m->varlink_server);
321 free(m->userdb_service);
322
323 free(m->default_file_system_type);
324
325 return mfree(m);
326}
327
328int manager_verify_user_record(Manager *m, UserRecord *hr) {
329 EVP_PKEY *pkey;
330 int r;
331
332 assert(m);
333 assert(hr);
334
335 if (!m->private_key && hashmap_isempty(m->public_keys)) {
336 r = user_record_has_signature(hr);
337 if (r < 0)
338 return r;
339
340 return r ? -ENOKEY : USER_RECORD_UNSIGNED;
341 }
342
343 /* Is it our own? */
344 if (m->private_key) {
345 r = user_record_verify(hr, m->private_key);
346 switch (r) {
347
348 case USER_RECORD_FOREIGN:
349 /* This record is not signed by this key, but let's see below */
350 break;
351
352 case USER_RECORD_SIGNED: /* Signed by us, but also by others, let's propagate that */
353 case USER_RECORD_SIGNED_EXCLUSIVE: /* Signed by us, and nothing else, ditto */
354 case USER_RECORD_UNSIGNED: /* Not signed at all, ditto */
355 default:
356 return r;
357 }
358 }
359
360 HASHMAP_FOREACH(pkey, m->public_keys) {
361 r = user_record_verify(hr, pkey);
362 switch (r) {
363
364 case USER_RECORD_FOREIGN:
365 /* This record is not signed by this key, but let's see our other keys */
366 break;
367
368 case USER_RECORD_SIGNED: /* It's signed by this key we are happy with, but which is not our own. */
369 case USER_RECORD_SIGNED_EXCLUSIVE:
370 return USER_RECORD_FOREIGN;
371
372 case USER_RECORD_UNSIGNED: /* It's not signed at all */
373 default:
374 return r;
375 }
376 }
377
378 return -ENOKEY;
379}
380
381static int manager_add_home_by_record(
382 Manager *m,
383 const char *name,
384 int dir_fd,
385 const char *fname) {
386
387 _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
388 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
389 int r, is_signed;
390 struct stat st;
391 Home *h;
392
393 assert(m);
394 assert(name);
395 assert(fname);
396
397 if (fstatat(dir_fd, fname, &st, 0) < 0)
398 return log_error_errno(errno, "Failed to stat identity record %s: %m", fname);
399
400 if (!S_ISREG(st.st_mode)) {
401 log_debug("Identity record file %s is not a regular file, ignoring.", fname);
402 return 0;
403 }
404
405 if (st.st_size == 0)
406 goto unlink_this_file;
407
408 unsigned line = 0, column = 0;
409 r = sd_json_parse_file_at(NULL, dir_fd, fname, SD_JSON_PARSE_SENSITIVE, &v, &line, &column);
410 if (r < 0)
411 return log_error_errno(r, "Failed to parse identity record at %s:%u%u: %m", fname, line, column);
412
413 if (sd_json_variant_is_blank_object(v))
414 goto unlink_this_file;
415
416 hr = user_record_new();
417 if (!hr)
418 return log_oom();
419
420 r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG|USER_RECORD_PERMISSIVE);
421 if (r < 0)
422 return r;
423
424 if (!streq_ptr(hr->user_name, name))
425 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
426 "Identity's user name %s does not match file name %s, refusing.",
427 hr->user_name, name);
428
429 is_signed = manager_verify_user_record(m, hr);
430 switch (is_signed) {
431
432 case -ENOKEY:
433 return log_warning_errno(is_signed, "User record %s is not signed by any accepted key, ignoring.", fname);
434 case USER_RECORD_UNSIGNED:
435 return log_warning_errno(SYNTHETIC_ERRNO(EPERM), "User record %s is not signed at all, ignoring.", fname);
436 case USER_RECORD_SIGNED:
437 log_info("User record %s is signed by us (and others), accepting.", fname);
438 break;
439 case USER_RECORD_SIGNED_EXCLUSIVE:
440 log_info("User record %s is signed only by us, accepting.", fname);
441 break;
442 case USER_RECORD_FOREIGN:
443 log_info("User record %s is signed by registered key from others, accepting.", fname);
444 break;
445 default:
446 assert(is_signed < 0);
447 return log_error_errno(is_signed, "Failed to verify signature of user record in %s: %m", fname);
448 }
449
450 h = hashmap_get(m->homes_by_name, name);
451 if (h) {
452 r = home_set_record(h, hr);
453 if (r < 0)
454 return log_error_errno(r, "Failed to update home record for %s: %m", name);
455
456 /* If we acquired a record now for a previously unallocated entry, then reset the state. This
457 * makes sure home_get_state() will check for the availability of the image file dynamically
458 * in order to detect to distinguish HOME_INACTIVE and HOME_ABSENT. */
459 if (h->state == HOME_UNFIXATED)
460 h->state = _HOME_STATE_INVALID;
461 } else {
462 r = home_new(m, hr, NULL, &h);
463 if (r < 0)
464 return log_error_errno(r, "Failed to allocate new home object: %m");
465
466 log_info("Added registered home for user %s.", hr->user_name);
467 }
468
469 /* Only entries we exclusively signed are writable to us, hence remember the result */
470 h->signed_locally = is_signed == USER_RECORD_SIGNED_EXCLUSIVE;
471
472 return 1;
473
474unlink_this_file:
475 /* If this is an empty file, then let's just remove it. An empty file is not useful in any case, and
476 * apparently xfs likes to leave empty files around when not unmounted cleanly (see
477 * https://github.com/systemd/systemd/issues/15178 for example). Note that we don't delete non-empty
478 * files even if they are invalid, because that's just too risky, we might delete data the user still
479 * needs. But empty files are never useful, hence let's just remove them. */
480
481 if (unlinkat(dir_fd, fname, 0) < 0)
482 return log_error_errno(errno, "Failed to remove empty user record file %s: %m", fname);
483
484 log_notice("Discovered empty user record file %s/%s, removed automatically.", home_record_dir(), fname);
485 return 0;
486}
487
488static int manager_enumerate_records(Manager *m) {
489 _cleanup_closedir_ DIR *d = NULL;
490
491 assert(m);
492
493 d = opendir(home_record_dir());
494 if (!d)
495 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
496 "Failed to open %s: %m", home_record_dir());
497
498 FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read record directory: %m")) {
499 _cleanup_free_ char *n = NULL;
500 const char *e;
501
502 if (!dirent_is_file(de))
503 continue;
504
505 e = endswith(de->d_name, ".identity");
506 if (!e)
507 continue;
508
509 n = strndup(de->d_name, e - de->d_name);
510 if (!n)
511 return log_oom();
512
513 if (!suitable_user_name(n))
514 continue;
515
516 (void) manager_add_home_by_record(m, n, dirfd(d), de->d_name);
517 }
518
519 return 0;
520}
521
522static int search_quota(uid_t uid, const char *exclude_quota_path) {
523 struct stat exclude_st = {};
524 dev_t previous_devno = 0;
525 int r;
526
527 /* Checks whether the specified UID owns any files on the files system, but ignore any file system
528 * backing the specified file. The file is used when operating on home directories, where it's OK if
529 * the UID of them already owns files. */
530
531 if (exclude_quota_path && stat(exclude_quota_path, &exclude_st) < 0) {
532 if (errno != ENOENT)
533 return log_warning_errno(errno, "Failed to stat %s, ignoring: %m", exclude_quota_path);
534 }
535
536 /* Check a few usual suspects where regular users might own files. Note that this is by no means
537 * comprehensive, but should cover most cases. Note that in an ideal world every user would be
538 * registered in NSS and avoid our own UID range, but for all other cases, it's a good idea to be
539 * paranoid and check quota if we can. */
540 FOREACH_STRING(where, get_home_root(), "/tmp/", "/var/", "/var/mail/", "/var/tmp/", "/var/spool/") {
541 struct dqblk req;
542 struct stat st;
543
544 _cleanup_close_ int fd = open(where, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
545 if (fd < 0) {
546 log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
547 "Failed to open '%s', ignoring: %m", where);
548 continue;
549 }
550
551 if (fstat(fd, &st) < 0) {
552 log_error_errno(errno, "Failed to stat '%s', ignoring: %m", where);
553 continue;
554 }
555
556 if (st.st_dev == exclude_st.st_dev) { /* If an exclude path is specified, then ignore quota
557 * reported on the same block device as that path. */
558 log_debug("Directory %s is where the home directory is located, not checking quota for UID use.", where);
559 continue;
560 }
561
562 if (st.st_dev == previous_devno) { /* Does this directory have the same devno as the previous
563 * one we tested? If so, there's no point in testing this
564 * again. */
565 log_debug("Directory %s is on same device as previous tested directory, not checking quota for UID use a second time.", where);
566 continue;
567 }
568
569 previous_devno = st.st_dev;
570
571 r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_GETQUOTA, USRQUOTA), uid, &req);
572 if (r < 0) {
573 if (ERRNO_IS_NOT_SUPPORTED(r))
574 log_debug_errno(r, "No UID quota support on %s, ignoring.", where);
575 else if (r == -ESRCH)
576 log_debug_errno(r, "UID quota not enabled on %s (for user " UID_FMT "), ignoring.", where, uid);
577 else if (ERRNO_IS_PRIVILEGE(r))
578 log_debug_errno(r, "UID quota support for %s prohibited, ignoring.", where);
579 else
580 log_warning_errno(r, "Failed to query quota on %s, ignoring: %m", where);
581
582 continue;
583 }
584
585 if ((FLAGS_SET(req.dqb_valid, QIF_SPACE) && req.dqb_curspace > 0) ||
586 (FLAGS_SET(req.dqb_valid, QIF_INODES) && req.dqb_curinodes > 0)) {
587 log_debug("Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where);
588 return 1;
589 }
590 }
591
592 return 0;
593}
594
595static int manager_acquire_uid(
596 Manager *m,
597 uid_t start_uid,
598 const char *user_name,
599 const char *exclude_quota_path,
600 uid_t *ret) {
601
602 static const uint8_t hash_key[] = {
603 0xa3, 0xb8, 0x82, 0x69, 0x9a, 0x71, 0xf7, 0xa9,
604 0xe0, 0x7c, 0xf6, 0xf1, 0x21, 0x69, 0xd2, 0x1e
605 };
606
607 enum {
608 PHASE_SUGGESTED,
609 PHASE_HASHED,
610 PHASE_RANDOM
611 } phase = PHASE_SUGGESTED;
612
613 unsigned n_tries = 100;
614 int r;
615
616 assert(m);
617 assert(ret);
618
619 for (;;) {
620 _cleanup_free_ struct passwd *pw = NULL;
621 _cleanup_free_ struct group *gr = NULL;
622 uid_t candidate;
623 Home *other;
624
625 if (--n_tries <= 0)
626 return -EBUSY;
627
628 switch (phase) {
629
630 case PHASE_SUGGESTED:
631 phase = PHASE_HASHED;
632
633 if (!uid_is_home(start_uid))
634 continue;
635
636 candidate = start_uid;
637 break;
638
639 case PHASE_HASHED:
640 phase = PHASE_RANDOM;
641
642 if (!user_name)
643 continue;
644
645 candidate = UID_CLAMP_INTO_HOME_RANGE(siphash24(user_name, strlen(user_name), hash_key));
646 break;
647
648 case PHASE_RANDOM:
649 random_bytes(&candidate, sizeof(candidate));
650 candidate = UID_CLAMP_INTO_HOME_RANGE(candidate);
651 break;
652
653 default:
654 assert_not_reached();
655 }
656
657 other = hashmap_get(m->homes_by_uid, UID_TO_PTR(candidate));
658 if (other) {
659 log_debug("Candidate UID " UID_FMT " already used by another home directory (%s), let's try another.",
660 candidate, other->user_name);
661 continue;
662 }
663
664 r = getpwuid_malloc(candidate, &pw);
665 if (r >= 0) {
666 log_debug("Candidate UID " UID_FMT " already registered by another user in NSS (%s), let's try another.",
667 candidate, pw->pw_name);
668 continue;
669 }
670 if (r != -ESRCH) {
671 log_debug_errno(r, "Failed to check if an NSS user is already registered for candidate UID " UID_FMT ", assuming there might be: %m", candidate);
672 continue;
673 }
674
675 r = getgrgid_malloc((gid_t) candidate, &gr);
676 if (r >= 0) {
677 log_debug("Candidate UID " UID_FMT " already registered by another group in NSS (%s), let's try another.",
678 candidate, gr->gr_name);
679 continue;
680 }
681 if (r != -ESRCH) {
682 log_debug_errno(r, "Failed to check if an NSS group is already registered for candidate UID " UID_FMT ", assuming there might be: %m", candidate);
683 continue;
684 }
685
686 r = search_ipc(candidate, (gid_t) candidate);
687 if (r < 0)
688 continue;
689 if (r > 0) {
690 log_debug_errno(r, "Candidate UID " UID_FMT " already owns IPC objects, let's try another: %m",
691 candidate);
692 continue;
693 }
694
695 r = search_quota(candidate, exclude_quota_path);
696 if (r != 0)
697 continue;
698
699 *ret = candidate;
700 return 0;
701 }
702}
703
704static int manager_add_home_by_image(
705 Manager *m,
706 const char *user_name,
707 const char *realm,
708 const char *image_path,
709 const char *sysfs,
710 UserStorage storage,
711 uid_t start_uid) {
712
713 _cleanup_(user_record_unrefp) UserRecord *hr = NULL;
714 uid_t uid;
715 Home *h;
716 int r;
717
718 assert(m);
719
720 assert(m);
721 assert(user_name);
722 assert(image_path);
723 assert(storage >= 0);
724 assert(storage < _USER_STORAGE_MAX);
725
726 h = hashmap_get(m->homes_by_name, user_name);
727 if (h) {
728 bool same;
729
730 if (!streq(h->user_name, user_name)) {
731 log_debug("Found an image for user %s which already is an alias for another user, skipping.", user_name);
732 return 0; /* Ignore images that would synthesize a user that conflicts with an alias of another user */
733 }
734
735 if (h->state != HOME_UNFIXATED) {
736 log_debug("Found an image for user %s which already has a record, skipping.", user_name);
737 return 0; /* ignore images that synthesize a user we already have a record for */
738 }
739
740 same = user_record_storage(h->record) == storage;
741 if (same) {
742 if (h->sysfs && sysfs)
743 same = path_equal(h->sysfs, sysfs);
744 else if (!!h->sysfs != !!sysfs)
745 same = false;
746 else {
747 const char *p;
748
749 p = user_record_image_path(h->record);
750 same = p && path_equal(p, image_path);
751 }
752 }
753
754 if (!same) {
755 log_debug("Found multiple images for user '%s', ignoring image '%s'.", user_name, image_path);
756 return 0;
757 }
758 } else {
759 /* Check NSS, in case there's another user or group by this name */
760 if (getpwnam_malloc(user_name, /* ret= */ NULL) >= 0 || getgrnam_malloc(user_name, /* ret= */ NULL) >= 0) {
761 log_debug("Found an existing user or group by name '%s', ignoring image '%s'.", user_name, image_path);
762 return 0;
763 }
764 }
765
766 if (h && uid_is_valid(h->uid))
767 uid = h->uid;
768 else {
769 r = manager_acquire_uid(m, start_uid, user_name,
770 IN_SET(storage, USER_SUBVOLUME, USER_DIRECTORY, USER_FSCRYPT) ? image_path : NULL,
771 &uid);
772 if (r < 0)
773 return log_warning_errno(r, "Failed to acquire unused UID for %s: %m", user_name);
774 }
775
776 hr = user_record_new();
777 if (!hr)
778 return log_oom();
779
780 r = user_record_synthesize(hr, user_name, realm, image_path, storage, uid, (gid_t) uid);
781 if (r < 0)
782 return log_error_errno(r, "Failed to synthesize home record for %s (image %s): %m", user_name, image_path);
783
784 if (h) {
785 r = home_set_record(h, hr);
786 if (r < 0)
787 return log_error_errno(r, "Failed to update home record for %s: %m", user_name);
788 } else {
789 r = home_new(m, hr, sysfs, &h);
790 if (r < 0)
791 return log_error_errno(r, "Failed to allocate new home object: %m");
792
793 h->state = HOME_UNFIXATED;
794
795 log_info("Discovered new home for user %s through image %s.", user_name, image_path);
796 }
797
798 return 1;
799}
800
801int manager_augment_record_with_uid(
802 Manager *m,
803 UserRecord *hr) {
804
805 const char *exclude_quota_path = NULL;
806 uid_t start_uid = UID_INVALID, uid;
807 int r;
808
809 assert(m);
810 assert(hr);
811
812 if (uid_is_valid(hr->uid))
813 return 0;
814
815 if (IN_SET(hr->storage, USER_CLASSIC, USER_SUBVOLUME, USER_DIRECTORY, USER_FSCRYPT)) {
816 const char * ip;
817
818 ip = user_record_image_path(hr);
819 if (ip) {
820 struct stat st;
821
822 if (stat(ip, &st) < 0) {
823 if (errno != ENOENT)
824 log_warning_errno(errno, "Failed to stat(%s): %m", ip);
825 } else if (uid_is_home(st.st_uid)) {
826 start_uid = st.st_uid;
827 exclude_quota_path = ip;
828 }
829 }
830 }
831
832 r = manager_acquire_uid(m, start_uid, hr->user_name, exclude_quota_path, &uid);
833 if (r < 0)
834 return r;
835
836 log_debug("Acquired new UID " UID_FMT " for %s.", uid, hr->user_name);
837
838 r = user_record_add_binding(
839 hr,
840 _USER_STORAGE_INVALID,
841 NULL,
842 SD_ID128_NULL,
843 SD_ID128_NULL,
844 SD_ID128_NULL,
845 NULL,
846 NULL,
847 UINT64_MAX,
848 NULL,
849 NULL,
850 uid,
851 (gid_t) uid);
852 if (r < 0)
853 return r;
854
855 return 1;
856}
857
858static int manager_assess_image(
859 Manager *m,
860 int dir_fd,
861 const char *dir_path,
862 const char *dentry_name) {
863
864 char *luks_suffix, *directory_suffix;
865 _cleanup_free_ char *path = NULL;
866 struct stat st;
867 int r;
868
869 assert(m);
870 assert(dir_path);
871 assert(dentry_name);
872
873 /* Maybe registers the specified .home or .homedir as a home we manage. Returns:
874 *
875 * -EMEDIUMTYPE: Not a dir with .homedir suffix or a file with .home suffix */
876
877 luks_suffix = endswith(dentry_name, ".home");
878 if (luks_suffix)
879 directory_suffix = NULL;
880 else
881 directory_suffix = endswith(dentry_name, ".homedir");
882
883 /* Early filter out: by name */
884 if (!luks_suffix && !directory_suffix)
885 return -EMEDIUMTYPE;
886
887 path = path_join(dir_path, dentry_name);
888 if (!path)
889 return log_oom();
890
891 /* Follow symlinks here, to allow people to link in stuff to make them available locally. */
892 if (dir_fd >= 0)
893 r = fstatat(dir_fd, dentry_name, &st, 0);
894 else
895 r = stat(path, &st);
896 if (r < 0)
897 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
898 "Failed to stat() directory entry '%s', ignoring: %m", dentry_name);
899
900 if (S_ISREG(st.st_mode)) {
901 _cleanup_free_ char *n = NULL, *user_name = NULL, *realm = NULL;
902
903 if (!luks_suffix)
904 return -EMEDIUMTYPE;
905
906 n = strndup(dentry_name, luks_suffix - dentry_name);
907 if (!n)
908 return log_oom();
909
910 r = split_user_name_realm(n, &user_name, &realm);
911 if (r == -EINVAL) /* Not the right format: ignore */
912 return -EMEDIUMTYPE;
913 if (r < 0)
914 return log_error_errno(r, "Failed to split image name into user name/realm: %m");
915
916 return manager_add_home_by_image(m, user_name, realm, path, NULL, USER_LUKS, UID_INVALID);
917 }
918
919 if (S_ISDIR(st.st_mode)) {
920 _cleanup_free_ char *n = NULL, *user_name = NULL, *realm = NULL;
921 _cleanup_close_ int fd = -EBADF;
922 UserStorage storage;
923
924 if (!directory_suffix)
925 return -EMEDIUMTYPE;
926
927 n = strndup(dentry_name, directory_suffix - dentry_name);
928 if (!n)
929 return log_oom();
930
931 r = split_user_name_realm(n, &user_name, &realm);
932 if (r == -EINVAL) /* Not the right format: ignore */
933 return -EMEDIUMTYPE;
934 if (r < 0)
935 return log_error_errno(r, "Failed to split image name into user name/realm: %m");
936
937 if (dir_fd >= 0)
938 fd = openat(dir_fd, dentry_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
939 else
940 fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC);
941 if (fd < 0)
942 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
943 "Failed to open directory '%s', ignoring: %m", path);
944
945 if (fstat(fd, &st) < 0)
946 return log_warning_errno(errno, "Failed to fstat() %s, ignoring: %m", path);
947
948 assert(S_ISDIR(st.st_mode)); /* Must hold, we used O_DIRECTORY above */
949
950 r = btrfs_is_subvol_fd(fd);
951 if (r < 0)
952 return log_warning_errno(r, "Failed to determine whether %s is a btrfs subvolume: %m", path);
953 if (r > 0)
954 storage = USER_SUBVOLUME;
955 else {
956 struct fscrypt_policy policy;
957
958 if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &policy) < 0) {
959
960 if (errno == ENODATA)
961 log_debug_errno(errno, "Determined %s is not fscrypt encrypted.", path);
962 else if (ERRNO_IS_NOT_SUPPORTED(errno))
963 log_debug_errno(errno, "Determined %s is not fscrypt encrypted because kernel or file system doesn't support it.", path);
964 else
965 log_debug_errno(errno, "FS_IOC_GET_ENCRYPTION_POLICY failed with unexpected error code on %s, ignoring: %m", path);
966
967 storage = USER_DIRECTORY;
968 } else
969 storage = USER_FSCRYPT;
970 }
971
972 return manager_add_home_by_image(m, user_name, realm, path, NULL, storage, st.st_uid);
973 }
974
975 return -EMEDIUMTYPE;
976}
977
978int manager_adopt_home(Manager *m, const char *path) {
979 int r;
980
981 assert(m);
982 assert(path);
983
984 _cleanup_free_ char *fn = NULL;
985 r = path_extract_filename(path, &fn);
986 if (r < 0)
987 return r;
988
989 _cleanup_free_ char *dir = NULL;
990 r = path_extract_directory(path, &dir);
991 if (r < 0)
992 return r;
993
994 return manager_assess_image(m, /* dir_fd= */ -EBADF, dir, fn);
995}
996
997int manager_enumerate_images(Manager *m) {
998 _cleanup_closedir_ DIR *d = NULL;
999
1000 assert(m);
1001
1002 if (!m->scan_slash_home)
1003 return 0;
1004
1005 d = opendir(get_home_root());
1006 if (!d)
1007 return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
1008 "Failed to open %s: %m", get_home_root());
1009
1010 FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read %s directory: %m", get_home_root()))
1011 (void) manager_assess_image(m, dirfd(d), get_home_root(), de->d_name);
1012
1013 return 0;
1014}
1015
1016static int manager_connect_bus(Manager *m) {
1017 _cleanup_free_ char *b = NULL;
1018 const char *suffix, *busname;
1019 int r;
1020
1021 assert(m);
1022 assert(!m->bus);
1023
1024 r = sd_bus_default_system(&m->bus);
1025 if (r < 0)
1026 return log_error_errno(r, "Failed to connect to system bus: %m");
1027
1028 r = bus_add_implementation(m->bus, &manager_object, m);
1029 if (r < 0)
1030 return r;
1031
1032 r = bus_log_control_api_register(m->bus);
1033 if (r < 0)
1034 return r;
1035
1036 suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
1037 if (suffix) {
1038 b = strjoin("org.freedesktop.home1.", suffix);
1039 if (!b)
1040 return log_oom();
1041 busname = b;
1042 } else
1043 busname = "org.freedesktop.home1";
1044
1045 r = sd_bus_request_name_async(m->bus, NULL, busname, 0, NULL, NULL);
1046 if (r < 0)
1047 return log_error_errno(r, "Failed to request name: %m");
1048
1049 r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
1050 if (r < 0)
1051 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1052
1053 (void) sd_bus_set_exit_on_disconnect(m->bus, true);
1054
1055 return 0;
1056}
1057
1058static int manager_bind_varlink(Manager *m) {
1059 _cleanup_free_ char *p = NULL;
1060 const char *suffix, *socket_path;
1061 int r;
1062
1063 assert(m);
1064 assert(!m->varlink_server);
1065
1066 r = varlink_server_new(
1067 &m->varlink_server,
1068 SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA|SD_VARLINK_SERVER_INPUT_SENSITIVE,
1069 m);
1070 if (r < 0)
1071 return log_error_errno(r, "Failed to allocate varlink server: %m");
1072
1073 r = sd_varlink_server_add_interface_many(
1074 m->varlink_server,
1075 &vl_interface_io_systemd_UserDatabase,
1076 &vl_interface_io_systemd_service);
1077 if (r < 0)
1078 return log_error_errno(r, "Failed to add UserDatabase interface to varlink server: %m");
1079
1080 r = sd_varlink_server_bind_method_many(
1081 m->varlink_server,
1082 "io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,
1083 "io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record,
1084 "io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships,
1085 "io.systemd.service.Ping", varlink_method_ping,
1086 "io.systemd.service.SetLogLevel", varlink_method_set_log_level,
1087 "io.systemd.service.GetEnvironment", varlink_method_get_environment);
1088 if (r < 0)
1089 return log_error_errno(r, "Failed to register varlink methods: %m");
1090
1091 /* To make things easier to debug, when working from a homed managed home directory, let's optionally
1092 * use a different varlink socket name */
1093 suffix = getenv("SYSTEMD_HOME_DEBUG_SUFFIX");
1094 if (suffix) {
1095 p = strjoin("/run/systemd/userdb/io.systemd.Home.", suffix);
1096 if (!p)
1097 return log_oom();
1098 socket_path = p;
1099 } else
1100 socket_path = "/run/systemd/userdb/io.systemd.Home";
1101
1102 r = sd_varlink_server_listen_address(m->varlink_server, socket_path, 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
1103 if (r < 0)
1104 return log_error_errno(r, "Failed to bind to varlink socket: %m");
1105
1106 r = sd_varlink_server_attach_event(m->varlink_server, m->event, SD_EVENT_PRIORITY_NORMAL);
1107 if (r < 0)
1108 return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
1109
1110 assert(!m->userdb_service);
1111 r = path_extract_filename(socket_path, &m->userdb_service);
1112 if (r < 0)
1113 return log_error_errno(r, "Failed to extract filename from socket path '%s': %m", socket_path);
1114
1115 /* Avoid recursion */
1116 if (setenv("SYSTEMD_BYPASS_USERDB", m->userdb_service, 1) < 0)
1117 return log_error_errno(errno, "Failed to set $SYSTEMD_BYPASS_USERDB: %m");
1118
1119 return 0;
1120}
1121
1122static int on_notify_socket(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1123 Manager *m = ASSERT_PTR(userdata);
1124 int r;
1125
1126 assert(s);
1127
1128 _cleanup_(fdset_free_asyncp) FDSet *passed_fds = NULL;
1129 _cleanup_(pidref_done) PidRef sender = PIDREF_NULL;
1130 _cleanup_strv_free_ char **l = NULL;
1131 r = notify_recv_with_fds_strv(fd, &l, /* ret_ucred= */ NULL, &sender, &passed_fds);
1132 if (r == -EAGAIN)
1133 return 0;
1134 if (r < 0)
1135 return r;
1136
1137 if (fdset_size(passed_fds) > 1) {
1138 log_warning("Received notify datagram with multiple fds, ignoring.");
1139 return 0;
1140 }
1141
1142 Home *h = hashmap_get(m->homes_by_worker_pid, &sender);
1143 if (!h) {
1144 log_warning("Received notify datagram of unknown process, ignoring.");
1145 return 0;
1146 }
1147
1148 home_process_notify(h, l, fdset_steal_first(passed_fds));
1149 return 0;
1150}
1151
1152static int manager_listen_notify(Manager *m) {
1153 int r;
1154
1155 assert(m);
1156 assert(!m->notify_socket_path);
1157
1158 r = notify_socket_prepare_full(
1159 m->event,
1160 SD_EVENT_PRIORITY_NORMAL - 5, /* Make sure we process sd_notify() before SIGCHLD for
1161 * any worker, so that we always know the error number
1162 * of a client before it exits. */
1163 on_notify_socket,
1164 m,
1165 /* accept_fds = */ true,
1166 &m->notify_socket_path,
1167 /* ret_event_source = */ NULL);
1168 if (r < 0)
1169 return log_error_errno(r, "Failed to prepare notify socket: %m");
1170
1171 return 0;
1172}
1173
1174static int manager_add_device(Manager *m, sd_device *d) {
1175 _cleanup_free_ char *user_name = NULL, *realm = NULL, *node = NULL;
1176 const char *tabletype, *parttype, *partname, *partuuid, *sysfs;
1177 sd_id128_t id;
1178 int r;
1179
1180 assert(m);
1181 assert(d);
1182
1183 r = sd_device_get_syspath(d, &sysfs);
1184 if (r < 0)
1185 return log_error_errno(r, "Failed to acquire sysfs path of device: %m");
1186
1187 r = sd_device_get_property_value(d, "ID_PART_TABLE_TYPE", &tabletype);
1188 if (r == -ENOENT)
1189 return 0;
1190 if (r < 0)
1191 return log_error_errno(r, "Failed to acquire ID_PART_TABLE_TYPE device property, ignoring: %m");
1192
1193 if (!streq(tabletype, "gpt")) {
1194 log_debug("Found partition (%s) on non-GPT table, ignoring.", sysfs);
1195 return 0;
1196 }
1197
1198 r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &parttype);
1199 if (r == -ENOENT)
1200 return 0;
1201 if (r < 0)
1202 return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
1203 if (sd_id128_string_equal(parttype, SD_GPT_USER_HOME) <= 0) {
1204 log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
1205 return 0;
1206 }
1207
1208 r = sd_device_get_property_value(d, "ID_PART_ENTRY_NAME", &partname);
1209 if (r < 0)
1210 return log_warning_errno(r, "Failed to acquire ID_PART_ENTRY_NAME device property, ignoring: %m");
1211
1212 r = split_user_name_realm(partname, &user_name, &realm);
1213 if (r == -EINVAL)
1214 return log_warning_errno(r, "Found partition with correct partition type but a non-parsable partition name '%s', ignoring.", partname);
1215 if (r < 0)
1216 return log_error_errno(r, "Failed to validate partition name '%s': %m", partname);
1217
1218 r = sd_device_get_property_value(d, "ID_FS_UUID", &partuuid);
1219 if (r < 0)
1220 return log_warning_errno(r, "Failed to acquire ID_FS_UUID device property, ignoring: %m");
1221
1222 r = sd_id128_from_string(partuuid, &id);
1223 if (r < 0)
1224 return log_warning_errno(r, "Failed to parse ID_FS_UUID field '%s', ignoring: %m", partuuid);
1225
1226 if (asprintf(&node, "/dev/disk/by-uuid/" SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0)
1227 return log_oom();
1228
1229 return manager_add_home_by_image(m, user_name, realm, node, sysfs, USER_LUKS, UID_INVALID);
1230}
1231
1232static int manager_on_device(sd_device_monitor *monitor, sd_device *d, void *userdata) {
1233 Manager *m = ASSERT_PTR(userdata);
1234 int r;
1235
1236 assert(d);
1237
1238 if (device_for_action(d, SD_DEVICE_REMOVE)) {
1239 const char *sysfs;
1240 Home *h;
1241
1242 r = sd_device_get_syspath(d, &sysfs);
1243 if (r < 0) {
1244 log_warning_errno(r, "Failed to acquire sysfs path from device: %m");
1245 return 0;
1246 }
1247
1248 log_info("block device %s has been removed.", sysfs);
1249
1250 /* Let's see if we previously synthesized a home record from this device, if so, let's just
1251 * revalidate that. Otherwise let's revalidate them all, but asynchronously. */
1252 h = hashmap_get(m->homes_by_sysfs, sysfs);
1253 if (h)
1254 manager_revalidate_image(m, h);
1255 else
1256 manager_enqueue_gc(m, NULL);
1257 } else
1258 (void) manager_add_device(m, d);
1259
1260 (void) bus_manager_emit_auto_login_changed(m);
1261 return 0;
1262}
1263
1264static int manager_watch_devices(Manager *m) {
1265 int r;
1266
1267 assert(m);
1268 assert(!m->device_monitor);
1269
1270 r = sd_device_monitor_new(&m->device_monitor);
1271 if (r < 0)
1272 return log_error_errno(r, "Failed to allocate device monitor: %m");
1273
1274 r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "block", NULL);
1275 if (r < 0)
1276 return log_error_errno(r, "Failed to configure device monitor match: %m");
1277
1278 r = sd_device_monitor_attach_event(m->device_monitor, m->event);
1279 if (r < 0)
1280 return log_error_errno(r, "Failed to attach device monitor to event loop: %m");
1281
1282 r = sd_device_monitor_start(m->device_monitor, manager_on_device, m);
1283 if (r < 0)
1284 return log_error_errno(r, "Failed to start device monitor: %m");
1285
1286 return 0;
1287}
1288
1289static int manager_enumerate_devices(Manager *m) {
1290 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
1291 int r;
1292
1293 assert(m);
1294
1295 r = sd_device_enumerator_new(&e);
1296 if (r < 0)
1297 return r;
1298
1299 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
1300 if (r < 0)
1301 return r;
1302
1303 FOREACH_DEVICE(e, d) {
1304 if (device_is_processed(d) <= 0)
1305 continue;
1306 (void) manager_add_device(m, d);
1307 }
1308
1309 return 0;
1310}
1311
1312static int manager_load_key_pair(Manager *m) {
1313 _cleanup_fclose_ FILE *f = NULL;
1314 struct stat st;
1315 int r;
1316
1317 assert(m);
1318
1319 if (m->private_key) {
1320 EVP_PKEY_free(m->private_key);
1321 m->private_key = NULL;
1322 }
1323
1324 r = search_and_fopen_nulstr("local.private", "re", NULL, KEY_PATHS_NULSTR, &f, NULL);
1325 if (r == -ENOENT)
1326 return 0;
1327 if (r < 0)
1328 return log_error_errno(r, "Failed to read private key file: %m");
1329
1330 if (fstat(fileno(f), &st) < 0)
1331 return log_error_errno(errno, "Failed to stat private key file: %m");
1332
1333 r = stat_verify_regular(&st);
1334 if (r < 0)
1335 return log_error_errno(r, "Private key file is not regular: %m");
1336
1337 if (st.st_uid != 0 || (st.st_mode & 0077) != 0)
1338 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Private key file is readable by more than the root user");
1339
1340 m->private_key = PEM_read_PrivateKey(f, NULL, NULL, NULL);
1341 if (!m->private_key)
1342 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to load private key pair");
1343
1344 log_info("Successfully loaded private key pair.");
1345
1346 return 1;
1347}
1348
1349static int manager_generate_key_pair(Manager *m) {
1350 _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
1351 _cleanup_(unlink_and_freep) char *temp_public = NULL, *temp_private = NULL;
1352 _cleanup_fclose_ FILE *fpublic = NULL, *fprivate = NULL;
1353 int r;
1354
1355 if (m->private_key) {
1356 EVP_PKEY_free(m->private_key);
1357 m->private_key = NULL;
1358 }
1359
1360 ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL);
1361 if (!ctx)
1362 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to allocate Ed25519 key generation context.");
1363
1364 if (EVP_PKEY_keygen_init(ctx) <= 0)
1365 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize Ed25519 key generation context.");
1366
1367 log_info("Generating key pair for signing local user identity records.");
1368
1369 if (EVP_PKEY_keygen(ctx, &m->private_key) <= 0)
1370 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate Ed25519 key pair");
1371
1372 log_info("Successfully created Ed25519 key pair.");
1373
1374 (void) mkdir_p("/var/lib/systemd/home", 0755);
1375
1376 /* Write out public key (note that we only do that as a help to the user, we don't make use of this ever */
1377 r = fopen_temporary("/var/lib/systemd/home/local.public", &fpublic, &temp_public);
1378 if (r < 0)
1379 return log_error_errno(r, "Failed to open key file for writing: %m");
1380
1381 if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0)
1382 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key.");
1383
1384 (void) fchmod(fileno(fpublic), 0444); /* Make public key world readable */
1385
1386 r = fflush_sync_and_check(fpublic);
1387 if (r < 0)
1388 return log_error_errno(r, "Failed to write private key: %m");
1389
1390 fpublic = safe_fclose(fpublic);
1391
1392 /* Write out the private key (this actually writes out both private and public, OpenSSL is confusing) */
1393 r = fopen_temporary("/var/lib/systemd/home/local.private", &fprivate, &temp_private);
1394 if (r < 0)
1395 return log_error_errno(r, "Failed to open key file for writing: %m");
1396
1397 if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, NULL) <= 0)
1398 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair.");
1399
1400 (void) fchmod(fileno(fprivate), 0400); /* Make private key root readable */
1401
1402 r = fflush_sync_and_check(fprivate);
1403 if (r < 0)
1404 return log_error_errno(r, "Failed to write private key: %m");
1405
1406 fprivate = safe_fclose(fprivate);
1407
1408 /* Both are written now, move them into place */
1409
1410 if (rename(temp_public, "/var/lib/systemd/home/local.public") < 0)
1411 return log_error_errno(errno, "Failed to move public key file into place: %m");
1412 temp_public = mfree(temp_public);
1413
1414 r = RET_NERRNO(rename(temp_private, "/var/lib/systemd/home/local.private"));
1415 if (r < 0) {
1416 (void) unlink("/var/lib/systemd/home/local.public"); /* try to remove the file we already created */
1417 return log_error_errno(r, "Failed to move private key file into place: %m");
1418 }
1419 temp_private = mfree(temp_private);
1420
1421 r = fsync_path_at(AT_FDCWD, "/var/lib/systemd/home/");
1422 if (r < 0)
1423 log_warning_errno(r, "Failed to sync /var/lib/systemd/home/, ignoring: %m");
1424
1425 return 1;
1426}
1427
1428int manager_acquire_key_pair(Manager *m) {
1429 int r;
1430
1431 assert(m);
1432
1433 /* Already there? */
1434 if (m->private_key)
1435 return 1;
1436
1437 /* First try to load key off disk */
1438 r = manager_load_key_pair(m);
1439 if (r != 0)
1440 return r;
1441
1442 /* Didn't work, generate a new one */
1443 return manager_generate_key_pair(m);
1444}
1445
1446int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus_error *error) {
1447 int r;
1448
1449 assert(m);
1450 assert(u);
1451 assert(ret);
1452
1453 r = manager_acquire_key_pair(m);
1454 if (r < 0)
1455 return r;
1456 if (r == 0)
1457 return sd_bus_error_set(error, BUS_ERROR_NO_PRIVATE_KEY, "Can't sign without local key.");
1458
1459 return user_record_sign(u, m->private_key, ret);
1460}
1461
1462DEFINE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free);
1463
1464static int manager_load_public_key_one(Manager *m, const char *path) {
1465 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
1466 _cleanup_fclose_ FILE *f = NULL;
1467 _cleanup_free_ char *fn = NULL;
1468 struct stat st;
1469 int r;
1470
1471 assert(m);
1472
1473 r = path_extract_filename(path, &fn);
1474 if (r < 0)
1475 return log_error_errno(r, "Failed to extract filename of path '%s': %m", path);
1476
1477 if (streq(fn, "local.public")) /* we already loaded the private key, which includes the public one */
1478 return 0;
1479
1480 f = fopen(path, "re");
1481 if (!f) {
1482 if (errno == ENOENT)
1483 return 0;
1484
1485 return log_error_errno(errno, "Failed to open public key %s: %m", path);
1486 }
1487
1488 if (fstat(fileno(f), &st) < 0)
1489 return log_error_errno(errno, "Failed to stat public key %s: %m", path);
1490
1491 r = stat_verify_regular(&st);
1492 if (r < 0)
1493 return log_error_errno(r, "Public key file %s is not a regular file: %m", path);
1494
1495 if (st.st_uid != 0 || (st.st_mode & 0022) != 0)
1496 return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Public key file %s is writable by more than the root user, refusing.", path);
1497
1498 pkey = PEM_read_PUBKEY(f, &pkey, NULL, NULL);
1499 if (!pkey)
1500 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key file %s.", path);
1501
1502 r = hashmap_ensure_put(&m->public_keys, &public_key_hash_ops, fn, pkey);
1503 if (r < 0)
1504 return log_error_errno(r, "Failed to add public key to set: %m");
1505
1506 TAKE_PTR(fn);
1507 TAKE_PTR(pkey);
1508
1509 return 0;
1510}
1511
1512static int manager_load_public_keys(Manager *m) {
1513 _cleanup_strv_free_ char **files = NULL;
1514 int r;
1515
1516 assert(m);
1517
1518 m->public_keys = hashmap_free(m->public_keys);
1519
1520 r = conf_files_list_nulstr(
1521 &files,
1522 ".public",
1523 NULL,
1524 CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED,
1525 KEY_PATHS_NULSTR);
1526 if (r < 0)
1527 return log_error_errno(r, "Failed to assemble list of public key directories: %m");
1528
1529 STRV_FOREACH(i, files)
1530 (void) manager_load_public_key_one(m, *i);
1531
1532 return 0;
1533}
1534
1535int manager_startup(Manager *m) {
1536 int r;
1537
1538 assert(m);
1539
1540 r = manager_listen_notify(m);
1541 if (r < 0)
1542 return r;
1543
1544 r = manager_connect_bus(m);
1545 if (r < 0)
1546 return r;
1547
1548 r = manager_bind_varlink(m);
1549 if (r < 0)
1550 return r;
1551
1552 r = manager_load_key_pair(m); /* only try to load it, don't generate any */
1553 if (r < 0)
1554 return r;
1555
1556 r = manager_load_public_keys(m);
1557 if (r < 0)
1558 return r;
1559
1560 manager_watch_home(m);
1561 (void) manager_watch_devices(m);
1562
1563 (void) manager_enumerate_records(m);
1564 (void) manager_enumerate_images(m);
1565 (void) manager_enumerate_devices(m);
1566
1567 /* Let's clean up home directories whose devices got removed while we were not running */
1568 (void) manager_enqueue_gc(m, NULL);
1569
1570 /* Let's clean up blob directories for home dirs that no longer exist */
1571 (void) manager_gc_blob(m);
1572
1573 return 0;
1574}
1575
1576void manager_revalidate_image(Manager *m, Home *h) {
1577 int r;
1578
1579 assert(m);
1580 assert(h);
1581
1582 /* Frees an automatically discovered image, if it's synthetic and its image disappeared. Unmounts any
1583 * image if it's mounted but its image vanished. */
1584
1585 if (h->current_operation || !ordered_set_isempty(h->pending_operations))
1586 return;
1587
1588 if (h->state == HOME_UNFIXATED) {
1589 r = user_record_test_image_path(h->record);
1590 if (r < 0)
1591 log_warning_errno(r, "Can't determine if image of %s exists, freeing unfixated user: %m", h->user_name);
1592 else if (r == USER_TEST_ABSENT)
1593 log_info("Image for %s disappeared, freeing unfixated user.", h->user_name);
1594 else
1595 return;
1596
1597 home_free(h);
1598
1599 } else if (h->state < 0) {
1600
1601 r = user_record_test_home_directory(h->record);
1602 if (r < 0) {
1603 log_warning_errno(r, "Unable to determine state of home directory, ignoring: %m");
1604 return;
1605 }
1606
1607 if (r == USER_TEST_MOUNTED) {
1608 r = user_record_test_image_path(h->record);
1609 if (r < 0) {
1610 log_warning_errno(r, "Unable to determine state of image path, ignoring: %m");
1611 return;
1612 }
1613
1614 if (r == USER_TEST_ABSENT) {
1615 _cleanup_(operation_unrefp) Operation *o = NULL;
1616
1617 log_notice("Backing image disappeared while home directory %s was mounted, unmounting it forcibly.", h->user_name);
1618 /* Wowza, the thing is mounted, but the device is gone? Act on it. */
1619
1620 r = home_killall(h);
1621 if (r < 0)
1622 log_warning_errno(r, "Failed to kill processes of user %s, ignoring: %m", h->user_name);
1623
1624 /* We enqueue the operation here, after all the home directory might
1625 * currently already run some operation, and we can deactivate it only after
1626 * that's complete. */
1627 o = operation_new(OPERATION_DEACTIVATE_FORCE, NULL);
1628 if (!o) {
1629 log_oom();
1630 return;
1631 }
1632
1633 r = home_schedule_operation(h, o, NULL);
1634 if (r < 0)
1635 log_warning_errno(r, "Failed to enqueue forced home directory %s deactivation, ignoring: %m", h->user_name);
1636 }
1637 }
1638 }
1639}
1640
1641int manager_gc_images(Manager *m) {
1642 Home *h;
1643
1644 assert_se(m);
1645
1646 if (m->gc_focus) {
1647 /* Focus on a specific home */
1648
1649 h = TAKE_PTR(m->gc_focus);
1650 manager_revalidate_image(m, h);
1651 } else {
1652 /* Gc all */
1653
1654 HASHMAP_FOREACH(h, m->homes_by_uid)
1655 manager_revalidate_image(m, h);
1656 }
1657
1658 return 0;
1659}
1660
1661static int manager_gc_blob(Manager *m) {
1662 _cleanup_closedir_ DIR *d = NULL;
1663 int r;
1664
1665 assert(m);
1666
1667 d = opendir(home_system_blob_dir());
1668 if (!d) {
1669 if (errno == ENOENT)
1670 return 0;
1671 return log_error_errno(errno, "Failed to open %s: %m", home_system_blob_dir());
1672 }
1673
1674 FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m")) {
1675 Home *found = hashmap_get(m->homes_by_name, de->d_name);
1676 if (!found || !streq(found->user_name, de->d_name)) {
1677 r = rm_rf_at(dirfd(d), de->d_name, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
1678 if (r < 0)
1679 log_warning_errno(r, "Failed to delete blob dir for missing user '%s', ignoring: %m", de->d_name);
1680 }
1681 }
1682
1683 return 0;
1684}
1685
1686static int on_deferred_rescan(sd_event_source *s, void *userdata) {
1687 Manager *m = ASSERT_PTR(userdata);
1688
1689 m->deferred_rescan_event_source = sd_event_source_disable_unref(m->deferred_rescan_event_source);
1690
1691 manager_enumerate_devices(m);
1692 manager_enumerate_images(m);
1693 return 0;
1694}
1695
1696int manager_enqueue_rescan(Manager *m) {
1697 int r;
1698
1699 assert(m);
1700
1701 if (m->deferred_rescan_event_source)
1702 return 0;
1703
1704 if (!m->event)
1705 return 0;
1706
1707 if (IN_SET(sd_event_get_state(m->event), SD_EVENT_FINISHED, SD_EVENT_EXITING))
1708 return 0;
1709
1710 r = sd_event_add_defer(m->event, &m->deferred_rescan_event_source, on_deferred_rescan, m);
1711 if (r < 0)
1712 return log_error_errno(r, "Failed to allocate rescan event source: %m");
1713
1714 r = sd_event_source_set_priority(m->deferred_rescan_event_source, SD_EVENT_PRIORITY_IDLE+1);
1715 if (r < 0)
1716 log_warning_errno(r, "Failed to tweak priority of event source, ignoring: %m");
1717
1718 (void) sd_event_source_set_description(m->deferred_rescan_event_source, "deferred-rescan");
1719 return 1;
1720}
1721
1722static int on_deferred_gc(sd_event_source *s, void *userdata) {
1723 Manager *m = ASSERT_PTR(userdata);
1724
1725 m->deferred_gc_event_source = sd_event_source_disable_unref(m->deferred_gc_event_source);
1726
1727 manager_gc_images(m);
1728 return 0;
1729}
1730
1731int manager_enqueue_gc(Manager *m, Home *focus) {
1732 int r;
1733
1734 assert(m);
1735
1736 /* This enqueues a request to GC dead homes. It may be called with focus=NULL in which case all homes
1737 * will be scanned, or with the parameter set, in which case only that home is checked. */
1738
1739 if (!m->event)
1740 return 0;
1741
1742 if (IN_SET(sd_event_get_state(m->event), SD_EVENT_FINISHED, SD_EVENT_EXITING))
1743 return 0;
1744
1745 /* If a focus home is specified, then remember to focus just on this home. Otherwise invalidate any
1746 * focus that might be set to look at all homes. */
1747
1748 if (m->deferred_gc_event_source) {
1749 if (m->gc_focus != focus) /* not the same focus, then look at everything */
1750 m->gc_focus = NULL;
1751
1752 return 0;
1753 } else
1754 m->gc_focus = focus; /* start focused */
1755
1756 r = sd_event_add_defer(m->event, &m->deferred_gc_event_source, on_deferred_gc, m);
1757 if (r < 0)
1758 return log_error_errno(r, "Failed to allocate GC event source: %m");
1759
1760 r = sd_event_source_set_priority(m->deferred_gc_event_source, SD_EVENT_PRIORITY_IDLE);
1761 if (r < 0)
1762 log_warning_errno(r, "Failed to tweak priority of event source, ignoring: %m");
1763
1764 (void) sd_event_source_set_description(m->deferred_gc_event_source, "deferred-gc");
1765 return 1;
1766}
1767
1768static bool manager_shall_rebalance(Manager *m) {
1769 Home *h;
1770
1771 assert(m);
1772
1773 if (IN_SET(m->rebalance_state, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING))
1774 return true;
1775
1776 HASHMAP_FOREACH(h, m->homes_by_uid)
1777 if (home_shall_rebalance(h))
1778 return true;
1779
1780 return false;
1781}
1782
1783static int home_cmp(Home *const*a, Home *const*b) {
1784 int r;
1785
1786 assert(a);
1787 assert(*a);
1788 assert(b);
1789 assert(*b);
1790
1791 /* Order user records by their weight (and by their name, to make things stable). We put the records
1792 * with the highest weight last, since we distribute space from the beginning and round down, hence
1793 * later entries tend to get slightly more than earlier entries. */
1794
1795 r = CMP(user_record_rebalance_weight((*a)->record), user_record_rebalance_weight((*b)->record));
1796 if (r != 0)
1797 return r;
1798
1799 return strcmp((*a)->user_name, (*b)->user_name);
1800}
1801
1802static int manager_rebalance_calculate(Manager *m) {
1803 uint64_t weight_sum, free_sum, usage_sum = 0, min_free = UINT64_MAX;
1804 _cleanup_free_ Home **array = NULL;
1805 bool relevant = false;
1806 struct statfs sfs;
1807 int c = 0, r;
1808 Home *h;
1809
1810 assert(m);
1811
1812 if (statfs(get_home_root(), &sfs) < 0)
1813 return log_error_errno(errno, "Failed to statfs() /home: %m");
1814
1815 free_sum = (uint64_t) sfs.f_bsize * sfs.f_bavail; /* This much free space is available on the
1816 * underlying pool directory */
1817
1818 weight_sum = REBALANCE_WEIGHT_BACKING; /* Grant the underlying pool directory a fixed weight of 20
1819 * (home dirs get 100 by default, i.e. 5x more). This weight
1820 * is not configurable, the per-home weights are. */
1821
1822 HASHMAP_FOREACH(h, m->homes_by_uid) {
1823 statfs_f_type_t fstype;
1824 h->rebalance_pending = false; /* First, reset the flag, we only want it to be true for the
1825 * homes that qualify for rebalancing */
1826
1827 if (!home_shall_rebalance(h)) /* Only look at actual candidates */
1828 continue;
1829
1830 if (home_is_busy(h))
1831 return -EBUSY; /* Let's not rebalance if there's a busy home directory. */
1832
1833 r = home_get_disk_status(
1834 h,
1835 &h->rebalance_size,
1836 &h->rebalance_usage,
1837 &h->rebalance_free,
1838 NULL,
1839 NULL,
1840 &fstype,
1841 NULL);
1842 if (r < 0) {
1843 log_warning_errno(r, "Failed to get free space of home '%s', ignoring.", h->user_name);
1844 continue;
1845 }
1846
1847 if (h->rebalance_free > UINT64_MAX - free_sum)
1848 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Rebalance free overflow");
1849 free_sum += h->rebalance_free;
1850
1851 if (h->rebalance_usage > UINT64_MAX - usage_sum)
1852 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Rebalance usage overflow");
1853 usage_sum += h->rebalance_usage;
1854
1855 h->rebalance_weight = user_record_rebalance_weight(h->record);
1856 if (h->rebalance_weight > UINT64_MAX - weight_sum)
1857 return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Rebalance weight overflow");
1858 weight_sum += h->rebalance_weight;
1859
1860 h->rebalance_min = minimal_size_by_fs_magic(fstype);
1861
1862 if (!GREEDY_REALLOC(array, c+1))
1863 return log_oom();
1864
1865 array[c++] = h;
1866 }
1867
1868 if (c == 0) {
1869 log_debug("No homes to rebalance.");
1870 return 0;
1871 }
1872
1873 assert(weight_sum > 0);
1874
1875 log_debug("Disk space usage by all home directories to rebalance: %s — available disk space: %s",
1876 FORMAT_BYTES(usage_sum), FORMAT_BYTES(free_sum));
1877
1878 /* Bring the home directories in a well-defined order, so that we distribute space in a reproducible
1879 * way for the same parameters. */
1880 typesafe_qsort(array, c, home_cmp);
1881
1882 for (int i = 0; i < c; i++) {
1883 uint64_t new_free;
1884 double d;
1885
1886 h = array[i];
1887
1888 assert(h->rebalance_free <= free_sum);
1889 assert(h->rebalance_usage <= usage_sum);
1890 assert(h->rebalance_weight <= weight_sum);
1891
1892 d = ((double) (free_sum / 4096) * (double) h->rebalance_weight) / (double) weight_sum; /* Calculate new space for this home in units of 4K */
1893
1894 /* Convert from units of 4K back to bytes */
1895 if (d >= (double) (UINT64_MAX/4096))
1896 new_free = UINT64_MAX;
1897 else
1898 new_free = (uint64_t) d * 4096;
1899
1900 /* Subtract the weight and assigned space from the sums now, to distribute the rounding noise
1901 * to the remaining home dirs */
1902 free_sum = LESS_BY(free_sum, new_free);
1903 weight_sum = LESS_BY(weight_sum, h->rebalance_weight);
1904
1905 /* Keep track of home directory with the least amount of space left: we want to schedule the
1906 * next rebalance more quickly if this is low */
1907 if (new_free < min_free)
1908 min_free = h->rebalance_size;
1909
1910 if (new_free > UINT64_MAX - h->rebalance_usage)
1911 h->rebalance_goal = UINT64_MAX-1; /* maximum size */
1912 else {
1913 h->rebalance_goal = h->rebalance_usage + new_free;
1914
1915 if (h->rebalance_min != UINT64_MAX && h->rebalance_goal < h->rebalance_min)
1916 h->rebalance_goal = h->rebalance_min;
1917 }
1918
1919 /* Skip over this home if the state doesn't match the operation */
1920 if ((m->rebalance_state == REBALANCE_SHRINKING && h->rebalance_goal > h->rebalance_size) ||
1921 (m->rebalance_state == REBALANCE_GROWING && h->rebalance_goal < h->rebalance_size))
1922 h->rebalance_pending = false;
1923 else {
1924 log_debug("Rebalancing home directory '%s' %s %s %s.", h->user_name,
1925 FORMAT_BYTES(h->rebalance_size),
1926 glyph(GLYPH_ARROW_RIGHT),
1927 FORMAT_BYTES(h->rebalance_goal));
1928 h->rebalance_pending = true;
1929 }
1930
1931 if ((fabs((double) h->rebalance_size - (double) h->rebalance_goal) * 100 / (double) h->rebalance_size) >= 5.0)
1932 relevant = true;
1933 }
1934
1935 /* Scale next rebalancing interval based on the least amount of space of any of the home
1936 * directories. We pick a time in the range 1min … 15min, scaled by log2(min_free), so that:
1937 * 10M → ~0.7min, 100M → ~2.7min, 1G → ~4.6min, 10G → ~6.5min, 100G ~8.4 */
1938 m->rebalance_interval_usec = (usec_t) CLAMP((LESS_BY(log2(min_free), 22)*15*USEC_PER_MINUTE)/26,
1939 1 * USEC_PER_MINUTE,
1940 15 * USEC_PER_MINUTE);
1941
1942 log_debug("Rebalancing interval set to %s.", FORMAT_TIMESPAN(m->rebalance_interval_usec, USEC_PER_MSEC));
1943
1944 /* Let's suppress small resizes, growing/shrinking file systems isn't free after all */
1945 if (!relevant) {
1946 log_debug("Skipping rebalancing, since all calculated size changes are below ±5%%.");
1947 return 0;
1948 }
1949
1950 return c;
1951}
1952
1953static int manager_rebalance_apply(Manager *m) {
1954 int c = 0, r;
1955 Home *h;
1956
1957 assert(m);
1958
1959 HASHMAP_FOREACH(h, m->homes_by_uid) {
1960 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1961
1962 if (!h->rebalance_pending)
1963 continue;
1964
1965 h->rebalance_pending = false;
1966
1967 r = home_resize(h, h->rebalance_goal, /* secret= */ NULL, &error);
1968 if (r < 0)
1969 log_warning_errno(r, "Failed to resize home '%s' for rebalancing, ignoring: %s",
1970 h->user_name, bus_error_message(&error, r));
1971 else
1972 c++;
1973 }
1974
1975 return c;
1976}
1977
1978static void manager_rebalance_reply_messages(Manager *m) {
1979 int r;
1980
1981 assert(m);
1982
1983 for (;;) {
1984 _cleanup_(sd_bus_message_unrefp) sd_bus_message *msg =
1985 set_steal_first(m->rebalance_pending_method_calls);
1986
1987 if (!msg)
1988 break;
1989
1990 r = sd_bus_reply_method_return(msg, NULL);
1991 if (r < 0)
1992 log_debug_errno(r, "Failed to reply to rebalance method call, ignoring: %m");
1993 }
1994}
1995
1996static int manager_rebalance_now(Manager *m) {
1997 RebalanceState busy_state; /* the state to revert to when operation fails if busy */
1998 int r;
1999
2000 assert(m);
2001
2002 log_debug("Rebalancing now...");
2003
2004 /* We maintain a simple state engine here to keep track of what we are doing. We'll first shrink all
2005 * homes that shall be shrunk and then grow all homes that shall be grown, so that they can take up
2006 * the space now freed. */
2007
2008 for (;;) {
2009 switch (m->rebalance_state) {
2010
2011 case REBALANCE_IDLE:
2012 case REBALANCE_PENDING:
2013 case REBALANCE_WAITING:
2014 /* First shrink large home dirs */
2015 m->rebalance_state = REBALANCE_SHRINKING;
2016 busy_state = REBALANCE_PENDING;
2017
2018 /* We are initiating the next rebalancing cycle now, let's make the queued methods
2019 * calls the pending ones, and flush out any pending ones (which shouldn't exist at
2020 * this time anyway) */
2021 set_clear(m->rebalance_pending_method_calls);
2022 SWAP_TWO(m->rebalance_pending_method_calls, m->rebalance_queued_method_calls);
2023
2024 log_debug("Shrinking phase..");
2025 break;
2026
2027 case REBALANCE_SHRINKING:
2028 /* Then grow small home dirs */
2029 m->rebalance_state = REBALANCE_GROWING;
2030 busy_state = REBALANCE_SHRINKING;
2031 log_debug("Growing phase..");
2032 break;
2033
2034 case REBALANCE_GROWING:
2035 /* Finally, we are done */
2036 log_info("Rebalancing complete.");
2037 m->rebalance_state = REBALANCE_IDLE;
2038 r = 0;
2039 goto finish;
2040
2041 case REBALANCE_OFF:
2042 default:
2043 assert_not_reached();
2044 }
2045
2046 r = manager_rebalance_calculate(m);
2047 if (r == -EBUSY) {
2048 /* Calculations failed because one home directory is currently busy. Revert to a state that
2049 * tells us what to do next. */
2050 log_debug("Can't enter phase, busy.");
2051 m->rebalance_state = busy_state;
2052 return r;
2053 }
2054 if (r < 0)
2055 goto finish;
2056 if (r == 0)
2057 continue; /* got to next step immediately, if there's nothing to do */
2058
2059 r = manager_rebalance_apply(m);
2060 if (r < 0)
2061 goto finish;
2062 if (r > 0)
2063 break; /* At least one resize operation is now pending, we are done for now */
2064
2065 /* If there was nothing to apply, go for next state right-away */
2066 }
2067
2068 return 0;
2069
2070finish:
2071 /* Reset state and schedule next rebalance */
2072 m->rebalance_state = REBALANCE_IDLE;
2073 manager_rebalance_reply_messages(m);
2074 (void) manager_schedule_rebalance(m, /* immediately= */ false);
2075 return r;
2076}
2077
2078static int on_rebalance_timer(sd_event_source *s, usec_t t, void *userdata) {
2079 Manager *m = ASSERT_PTR(userdata);
2080
2081 assert(s);
2082 assert(IN_SET(m->rebalance_state, REBALANCE_WAITING, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING));
2083
2084 (void) manager_rebalance_now(m);
2085 return 0;
2086}
2087
2088int manager_schedule_rebalance(Manager *m, bool immediately) {
2089 int r;
2090
2091 assert(m);
2092
2093 /* Check if there are any records where rebalancing is requested */
2094 if (!manager_shall_rebalance(m)) {
2095 log_debug("Not scheduling rebalancing, not needed.");
2096 r = 0; /* report that we didn't schedule anything because nothing needed it */
2097 goto turn_off;
2098 }
2099
2100 if (immediately) {
2101 /* If we are told to rebalance immediately, then mark a rebalance as pending (even if we area
2102 * already running one) */
2103
2104 if (m->rebalance_event_source) {
2105 r = sd_event_source_set_time(m->rebalance_event_source, 0);
2106 if (r < 0) {
2107 log_error_errno(r, "Failed to schedule immediate rebalancing: %m");
2108 goto turn_off;
2109 }
2110
2111 r = sd_event_source_set_enabled(m->rebalance_event_source, SD_EVENT_ONESHOT);
2112 if (r < 0) {
2113 log_error_errno(r, "Failed to enable rebalancing event source: %m");
2114 goto turn_off;
2115 }
2116 } else {
2117 r = sd_event_add_time(m->event, &m->rebalance_event_source, CLOCK_MONOTONIC, 0, USEC_PER_SEC, on_rebalance_timer, m);
2118 if (r < 0) {
2119 log_error_errno(r, "Failed to allocate rebalance event source: %m");
2120 goto turn_off;
2121 }
2122
2123 r = sd_event_source_set_priority(m->rebalance_event_source, SD_EVENT_PRIORITY_IDLE + 10);
2124 if (r < 0) {
2125 log_error_errno(r, "Failed to set rebalance event source priority: %m");
2126 goto turn_off;
2127 }
2128
2129 (void) sd_event_source_set_description(m->rebalance_event_source, "rebalance");
2130
2131 }
2132
2133 if (!IN_SET(m->rebalance_state, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING))
2134 m->rebalance_state = REBALANCE_PENDING;
2135
2136 log_debug("Scheduled immediate rebalancing...");
2137 return 1; /* report that we scheduled something */
2138 }
2139
2140 /* If we are told to schedule a rebalancing eventually, then do so only if we are not executing
2141 * anything yet. Also if we have something scheduled already, leave it in place */
2142 if (!IN_SET(m->rebalance_state, REBALANCE_OFF, REBALANCE_IDLE))
2143 return 1; /* report that there's already something scheduled */
2144
2145 if (m->rebalance_event_source) {
2146 r = sd_event_source_set_time_relative(m->rebalance_event_source, m->rebalance_interval_usec);
2147 if (r < 0) {
2148 log_error_errno(r, "Failed to schedule immediate rebalancing: %m");
2149 goto turn_off;
2150 }
2151
2152 r = sd_event_source_set_enabled(m->rebalance_event_source, SD_EVENT_ONESHOT);
2153 if (r < 0) {
2154 log_error_errno(r, "Failed to enable rebalancing event source: %m");
2155 goto turn_off;
2156 }
2157 } else {
2158 r = sd_event_add_time_relative(m->event, &m->rebalance_event_source, CLOCK_MONOTONIC, m->rebalance_interval_usec, USEC_PER_SEC, on_rebalance_timer, m);
2159 if (r < 0) {
2160 log_error_errno(r, "Failed to allocate rebalance event source: %m");
2161 goto turn_off;
2162 }
2163
2164 r = sd_event_source_set_priority(m->rebalance_event_source, SD_EVENT_PRIORITY_IDLE + 10);
2165 if (r < 0) {
2166 log_error_errno(r, "Failed to set rebalance event source priority: %m");
2167 goto turn_off;
2168 }
2169
2170 (void) sd_event_source_set_description(m->rebalance_event_source, "rebalance");
2171 }
2172
2173 m->rebalance_state = REBALANCE_WAITING; /* We managed to enqueue a timer event, we now wait until it fires */
2174 log_debug("Scheduled rebalancing in %s...", FORMAT_TIMESPAN(m->rebalance_interval_usec, 0));
2175 return 1; /* report that we scheduled something */
2176
2177turn_off:
2178 m->rebalance_event_source = sd_event_source_disable_unref(m->rebalance_event_source);
2179 m->rebalance_state = REBALANCE_OFF;
2180 manager_rebalance_reply_messages(m);
2181 return r;
2182}
2183
2184int manager_reschedule_rebalance(Manager *m) {
2185 int r;
2186
2187 assert(m);
2188
2189 /* If a rebalance is pending reschedules it so it gets executed immediately */
2190
2191 if (!IN_SET(m->rebalance_state, REBALANCE_PENDING, REBALANCE_SHRINKING, REBALANCE_GROWING))
2192 return 0;
2193
2194 r = manager_schedule_rebalance(m, /* immediately= */ true);
2195 if (r < 0)
2196 return r;
2197
2198 return 1;
2199}
2200
2201int manager_get_home_by_name(Manager *m, const char *user_name, Home **ret) {
2202 assert(m);
2203 assert(user_name);
2204
2205 Home *h = hashmap_get(m->homes_by_name, user_name);
2206 if (!h) {
2207 /* Also search by username and realm. For that simply chop off realm, then look for the home, and verify it afterwards. */
2208 const char *realm = strrchr(user_name, '@');
2209 if (realm) {
2210 _cleanup_free_ char *prefix = strndup(user_name, realm - user_name);
2211 if (!prefix)
2212 return -ENOMEM;
2213
2214 Home *j;
2215 j = hashmap_get(m->homes_by_name, prefix);
2216 if (j && user_record_matches_user_name(j->record, user_name))
2217 h = j;
2218 }
2219 }
2220
2221 if (ret)
2222 *ret = h;
2223
2224 return !!h;
2225}