mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
homed: Create & advertise blob directory
This ensures that a user-specific blob directory exists in /var/cache/systemd/homed for as long as the user exists, and gets deleted if the user gets deleted. It also advertises this blob directory via the user record, so that clients can find and use it.
This commit is contained in:
parent
1b466c0940
commit
c3d50255fc
@ -46,6 +46,10 @@
|
||||
url="https://systemd.io/USER_GROUP_API">User/Group Record Lookup API via Varlink</ulink>, and thus may be
|
||||
browsed with
|
||||
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para><filename>systemd-homed.service</filename> also manages blob directories for each home directory
|
||||
it manages. See <ulink url="https://systemd.io/USER_RECORD_BLOB_DIRS">User Record Blob Directories</ulink>
|
||||
for more details.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -137,3 +137,7 @@ int bus_message_append_secret(sd_bus_message *m, UserRecord *secret) {
|
||||
const char *home_record_dir(void) {
|
||||
return secure_getenv("SYSTEMD_HOME_RECORD_DIR") ?: "/var/lib/systemd/home/";
|
||||
}
|
||||
|
||||
const char *home_system_blob_dir(void) {
|
||||
return secure_getenv("SYSTEMD_HOME_SYSTEM_BLOB_DIR") ?: "/var/cache/systemd/home/";
|
||||
}
|
||||
|
@ -35,3 +35,4 @@ int bus_message_append_secret(sd_bus_message *m, UserRecord *secret);
|
||||
#define HOME_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE)
|
||||
|
||||
const char *home_record_dir(void);
|
||||
const char *home_system_blob_dir(void);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "process-util.h"
|
||||
#include "quota-util.h"
|
||||
#include "resize-fs.h"
|
||||
#include "rm-rf.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
@ -96,7 +97,7 @@ static int suitable_home_record(UserRecord *hr) {
|
||||
|
||||
int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
||||
_cleanup_(home_freep) Home *home = NULL;
|
||||
_cleanup_free_ char *nm = NULL, *ns = NULL;
|
||||
_cleanup_free_ char *nm = NULL, *ns = NULL, *blob = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -162,6 +163,13 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
blob = path_join(home_system_blob_dir(), hr->user_name);
|
||||
if (!blob)
|
||||
return -ENOMEM;
|
||||
r = mkdir_safe(blob, 0755, 0, 0, MKDIR_IGNORE_EXISTING);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to create blob dir for user '%s': %m", home->user_name);
|
||||
|
||||
(void) bus_manager_emit_auto_login_changed(m);
|
||||
(void) bus_home_emit_change(home);
|
||||
(void) manager_schedule_rebalance(m, /* immediately= */ false);
|
||||
@ -323,7 +331,9 @@ int home_save_record(Home *h) {
|
||||
}
|
||||
|
||||
int home_unlink_record(Home *h) {
|
||||
_cleanup_free_ char *blob = NULL;
|
||||
const char *fn;
|
||||
int r;
|
||||
|
||||
assert(h);
|
||||
|
||||
@ -335,6 +345,13 @@ int home_unlink_record(Home *h) {
|
||||
if (unlink(fn) < 0 && errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
blob = path_join(home_system_blob_dir(), h->user_name);
|
||||
if (!blob)
|
||||
return -ENOMEM;
|
||||
r = rm_rf(blob, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_MISSING_OK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "quota-util.h"
|
||||
#include "random-util.h"
|
||||
#include "resize-fs.h"
|
||||
#include "rm-rf.h"
|
||||
#include "socket-util.h"
|
||||
#include "sort-util.h"
|
||||
#include "stat-util.h"
|
||||
@ -79,6 +80,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(homes_by_sysfs_hash_ops, char, pat
|
||||
|
||||
static int on_home_inotify(sd_event_source *s, const struct inotify_event *event, void *userdata);
|
||||
static int manager_gc_images(Manager *m);
|
||||
static int manager_gc_blob(Manager *m);
|
||||
static int manager_enumerate_images(Manager *m);
|
||||
static int manager_assess_image(Manager *m, int dir_fd, const char *dir_path, const char *dentry_name);
|
||||
static void manager_revalidate_image(Manager *m, Home *h);
|
||||
@ -1627,6 +1629,9 @@ int manager_startup(Manager *m) {
|
||||
/* Let's clean up home directories whose devices got removed while we were not running */
|
||||
(void) manager_enqueue_gc(m, NULL);
|
||||
|
||||
/* Let's clean up blob directories for home dirs that no longer exist */
|
||||
(void) manager_gc_blob(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1715,6 +1720,29 @@ int manager_gc_images(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_gc_blob(Manager *m) {
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
d = opendir(home_system_blob_dir());
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
return log_error_errno(errno, "Failed to open %s: %m", home_system_blob_dir());
|
||||
}
|
||||
|
||||
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read system blob directory: %m"))
|
||||
if (!hashmap_contains(m->homes_by_name, de->d_name)) {
|
||||
r = rm_rf_at(dirfd(d), de->d_name, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to delete blob dir for missing user '%s', ignoring: %m", de->d_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_deferred_rescan(sd_event_source *s, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
|
||||
|
@ -282,7 +282,7 @@ int user_record_add_binding(
|
||||
gid_t gid) {
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL;
|
||||
_cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL;
|
||||
_cleanup_free_ char *blob = NULL, *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL;
|
||||
sd_id128_t mid;
|
||||
int r;
|
||||
|
||||
@ -291,6 +291,10 @@ int user_record_add_binding(
|
||||
if (!h->json)
|
||||
return -EUNATCH;
|
||||
|
||||
blob = path_join(home_system_blob_dir(), h->user_name);
|
||||
if (!blob)
|
||||
return -ENOMEM;
|
||||
|
||||
r = sd_id128_get_machine(&mid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -331,6 +335,7 @@ int user_record_add_binding(
|
||||
|
||||
r = json_build(&new_binding_entry,
|
||||
JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("blobDirectory", JSON_BUILD_STRING(blob)),
|
||||
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(partition_uuid), "partitionUuid", JSON_BUILD_STRING(SD_ID128_TO_UUID_STRING(partition_uuid))),
|
||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(luks_uuid), "luksUuid", JSON_BUILD_STRING(SD_ID128_TO_UUID_STRING(luks_uuid))),
|
||||
@ -370,6 +375,8 @@ int user_record_add_binding(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
free_and_replace(h->blob_directory, blob);
|
||||
|
||||
if (storage >= 0)
|
||||
h->storage = storage;
|
||||
|
||||
@ -1383,6 +1390,12 @@ int user_record_is_supported(UserRecord *hr, sd_bus_error *error) {
|
||||
if (hr->service && !streq(hr->service, "io.systemd.Home"))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Not accepted with service not matching io.systemd.Home.");
|
||||
|
||||
if (hr->blob_directory) {
|
||||
/* This function is always called w/o binding section, so if hr->blob_dir is set then the caller set it themselves */
|
||||
assert((hr->mask & USER_RECORD_BINDING) == 0);
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot manage custom blob directories.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_ALG AF_INET AF_INET6
|
||||
RestrictNamespaces=mnt user
|
||||
RestrictRealtime=yes
|
||||
StateDirectory=systemd/home
|
||||
CacheDirectory=systemd/home
|
||||
SystemCallArchitectures=native
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallFilter=@system-service @mount quotactl
|
||||
|
Loading…
Reference in New Issue
Block a user