mirror of
https://github.com/systemd/systemd
synced 2024-07-22 10:44:58 +00:00
parent
2aaf565a2d
commit
86019efa44
|
@ -610,6 +610,17 @@
|
|||
node is not allowed if any of the other storage backends are used.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--drop-caches=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
<listitem><para>Automatically flush OS file system caches on logout. This is useful in combination
|
||||
with the fscrypt storage backend to ensure the OS does not keep decrypted versions of the files and
|
||||
directories in memory (and accessible) after logout. This option is also supported on other backends,
|
||||
but should not bring any benefit there. Defaults to off, except if the selected storage backend is
|
||||
fscrypt, where it defaults to on. Note that flushing OS caches will negatively influence performance
|
||||
of the OS shortly after logout.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fs-type=</option><replaceable>TYPE</replaceable></term>
|
||||
|
||||
|
|
|
@ -2131,6 +2131,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||
" --storage=STORAGE Storage type to use (luks, fscrypt, directory,\n"
|
||||
" subvolume, cifs)\n"
|
||||
" --image-path=PATH Path to image file/directory\n"
|
||||
" --drop-caches=BOOL Whether to automatically drop caches on logout\n"
|
||||
"\n%4$sLUKS Storage User Record Properties:%5$s\n"
|
||||
" --fs-type=TYPE File system type to use in case of luks\n"
|
||||
" storage (btrfs, ext4, xfs)\n"
|
||||
|
@ -2245,6 +2246,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_RECOVERY_KEY,
|
||||
ARG_AND_RESIZE,
|
||||
ARG_AND_CHANGE_PASSWORD,
|
||||
ARG_DROP_CACHES,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
|
@ -2327,6 +2329,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "recovery-key", required_argument, NULL, ARG_RECOVERY_KEY },
|
||||
{ "and-resize", required_argument, NULL, ARG_AND_RESIZE },
|
||||
{ "and-change-password", required_argument, NULL, ARG_AND_CHANGE_PASSWORD },
|
||||
{ "drop-caches", required_argument, NULL, ARG_DROP_CACHES },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -3450,6 +3453,26 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
arg_and_change_password = true;
|
||||
break;
|
||||
|
||||
case ARG_DROP_CACHES: {
|
||||
bool drop_caches;
|
||||
|
||||
if (isempty(optarg)) {
|
||||
r = drop_from_identity("dropCaches");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = parse_boolean_argument("--drop-caches=", optarg, &drop_caches);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = json_variant_set_field_boolean(&arg_identity_extra, "dropCaches", r);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set drop caches field: %m");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "rm-rf.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "sync-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "user-util.h"
|
||||
#include "virt.h"
|
||||
|
@ -283,6 +284,20 @@ int user_record_authenticate(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void drop_caches_now(void) {
|
||||
int r;
|
||||
|
||||
/* Drop file system caches now. See https://www.kernel.org/doc/Documentation/sysctl/vm.txt for
|
||||
* details. We write "2" into /proc/sys/vm/drop_caches to ensure dentries/inodes are flushed, but not
|
||||
* more. */
|
||||
|
||||
r = write_string_file("/proc/sys/vm/drop_caches", "2\n", WRITE_STRING_FILE_DISABLE_BUFFER);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to drop caches, ignoring: %m");
|
||||
else
|
||||
log_debug("Dropped caches.");
|
||||
}
|
||||
|
||||
int home_setup_undo(HomeSetup *setup) {
|
||||
int r = 0, q;
|
||||
|
||||
|
@ -295,6 +310,9 @@ int home_setup_undo(HomeSetup *setup) {
|
|||
r = q;
|
||||
}
|
||||
|
||||
if (syncfs(setup->root_fd) < 0)
|
||||
log_debug_errno(errno, "Failed to synchronize home directory, ignoring: %m");
|
||||
|
||||
setup->root_fd = safe_close(setup->root_fd);
|
||||
}
|
||||
|
||||
|
@ -345,6 +363,9 @@ int home_setup_undo(HomeSetup *setup) {
|
|||
setup->volume_key = mfree(setup->volume_key);
|
||||
setup->volume_key_size = 0;
|
||||
|
||||
if (setup->do_drop_caches)
|
||||
drop_caches_now();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -367,6 +388,9 @@ int home_prepare(
|
|||
|
||||
/* Makes a home directory accessible (through the root_fd file descriptor, not by path!). */
|
||||
|
||||
if (!already_activated) /* If we set up the directory, we should also drop caches once we are done */
|
||||
setup->do_drop_caches = setup->do_drop_caches || user_record_drop_caches(h);
|
||||
|
||||
switch (user_record_storage(h)) {
|
||||
|
||||
case USER_LUKS:
|
||||
|
@ -827,6 +851,13 @@ static int home_deactivate(UserRecord *h, bool force) {
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Sync explicitly, so that the drop caches logic below can work as documented */
|
||||
r = syncfs_path(AT_FDCWD, user_record_home_directory(h));
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to synchronize home directory, ignoring: %m");
|
||||
else
|
||||
log_info("Syncing completed.");
|
||||
|
||||
if (umount2(user_record_home_directory(h), UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0)) < 0)
|
||||
return log_error_errno(errno, "Failed to unmount %s: %m", user_record_home_directory(h));
|
||||
|
||||
|
@ -846,6 +877,9 @@ static int home_deactivate(UserRecord *h, bool force) {
|
|||
if (!done)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home is not active.");
|
||||
|
||||
if (user_record_drop_caches(h))
|
||||
drop_caches_now();
|
||||
|
||||
log_info("Everything completed.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1268,9 +1302,21 @@ static int home_remove(UserRecord *h) {
|
|||
if (unlink(ip) < 0) {
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to remove %s: %m", ip);
|
||||
} else
|
||||
} else {
|
||||
_cleanup_free_ char *parent = NULL;
|
||||
|
||||
deleted = true;
|
||||
|
||||
r = path_extract_directory(ip, &parent);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to determine parent directory of '%s': %m", ip);
|
||||
else {
|
||||
r = fsync_path_at(AT_FDCWD, parent);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to synchronize disk after deleting '%s', ignoring: %m", ip);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (S_ISBLK(st.st_mode))
|
||||
log_info("Not removing file system on block device %s.", ip);
|
||||
else
|
||||
|
@ -1285,7 +1331,7 @@ static int home_remove(UserRecord *h) {
|
|||
case USER_FSCRYPT:
|
||||
assert(ip);
|
||||
|
||||
r = rm_rf(ip, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
|
||||
r = rm_rf(ip, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_SYNCFS);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
return log_warning_errno(r, "Failed to remove %s: %m", ip);
|
||||
|
@ -1316,9 +1362,12 @@ static int home_remove(UserRecord *h) {
|
|||
deleted = true;
|
||||
}
|
||||
|
||||
if (deleted)
|
||||
if (deleted) {
|
||||
if (user_record_drop_caches(h))
|
||||
drop_caches_now();
|
||||
|
||||
log_info("Everything completed.");
|
||||
else
|
||||
} else
|
||||
return log_notice_errno(SYNTHETIC_ERRNO(EALREADY),
|
||||
"Nothing to remove.");
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct HomeSetup {
|
|||
bool do_offline_fitrim;
|
||||
bool do_offline_fallocate;
|
||||
bool do_mark_clean;
|
||||
bool do_drop_caches;
|
||||
|
||||
uint64_t partition_offset;
|
||||
uint64_t partition_size;
|
||||
|
|
|
@ -435,6 +435,9 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
|
|||
if (hr->password_change_now >= 0)
|
||||
printf("Pas. Ch. Now: %s\n", yes_no(hr->password_change_now));
|
||||
|
||||
if (hr->drop_caches >= 0 || user_record_drop_caches(hr))
|
||||
printf(" Drop Caches: %s\n", yes_no(user_record_drop_caches(hr)));
|
||||
|
||||
if (!strv_isempty(hr->ssh_authorized_keys))
|
||||
printf("SSH Pub. Key: %zu\n", strv_length(hr->ssh_authorized_keys));
|
||||
|
||||
|
|
|
@ -202,6 +202,7 @@ UserRecord* user_record_new(void) {
|
|||
.pkcs11_protected_authentication_path_permitted = -1,
|
||||
.fido2_user_presence_permitted = -1,
|
||||
.fido2_user_verification_permitted = -1,
|
||||
.drop_caches = -1,
|
||||
};
|
||||
|
||||
return h;
|
||||
|
@ -1284,6 +1285,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
|
|||
{ "luksPbkdfTimeCostUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_time_cost_usec), 0 },
|
||||
{ "luksPbkdfMemoryCost", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_memory_cost), 0 },
|
||||
{ "luksPbkdfParallelThreads", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_parallel_threads), 0 },
|
||||
{ "dropCaches", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, drop_caches), 0 },
|
||||
{ "rateLimitIntervalUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, ratelimit_interval_usec), 0 },
|
||||
{ "rateLimitBurst", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, ratelimit_burst), 0 },
|
||||
{ "enforcePasswordPolicy", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, enforce_password_policy), 0 },
|
||||
|
@ -1620,7 +1622,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
|
|||
{ "luksUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, luks_uuid), 0 },
|
||||
{ "fileSystemUuid", JSON_VARIANT_STRING, json_dispatch_id128, offsetof(UserRecord, file_system_uuid), 0 },
|
||||
{ "luksDiscard", _JSON_VARIANT_TYPE_INVALID, json_dispatch_tristate, offsetof(UserRecord, luks_discard), 0 },
|
||||
{ "luksOfflineDiscard", _JSON_VARIANT_TYPE_INVALID, json_dispatch_tristate, offsetof(UserRecord, luks_offline_discard), 0 },
|
||||
{ "luksOfflineDiscard", _JSON_VARIANT_TYPE_INVALID, json_dispatch_tristate, offsetof(UserRecord, luks_offline_discard), 0 },
|
||||
{ "luksCipher", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_cipher), JSON_SAFE },
|
||||
{ "luksCipherMode", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, luks_cipher_mode), JSON_SAFE },
|
||||
{ "luksVolumeKeySize", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_volume_key_size), 0 },
|
||||
|
@ -1629,6 +1631,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
|
|||
{ "luksPbkdfTimeCostUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_time_cost_usec), 0 },
|
||||
{ "luksPbkdfMemoryCost", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_memory_cost), 0 },
|
||||
{ "luksPbkdfParallelThreads", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, luks_pbkdf_parallel_threads), 0 },
|
||||
{ "dropCaches", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, drop_caches), 0 },
|
||||
{ "service", JSON_VARIANT_STRING, json_dispatch_string, offsetof(UserRecord, service), JSON_SAFE },
|
||||
{ "rateLimitIntervalUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, ratelimit_interval_usec), 0 },
|
||||
{ "rateLimitBurst", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(UserRecord, ratelimit_burst), 0 },
|
||||
|
@ -2021,6 +2024,16 @@ bool user_record_can_authenticate(UserRecord *h) {
|
|||
return !strv_isempty(h->hashed_password);
|
||||
}
|
||||
|
||||
bool user_record_drop_caches(UserRecord *h) {
|
||||
assert(h);
|
||||
|
||||
if (h->drop_caches >= 0)
|
||||
return h->drop_caches;
|
||||
|
||||
/* By default drop caches on fscrypt, not otherwise. */
|
||||
return user_record_storage(h) == USER_FSCRYPT;
|
||||
}
|
||||
|
||||
uint64_t user_record_ratelimit_next_try(UserRecord *h) {
|
||||
assert(h);
|
||||
|
||||
|
|
|
@ -353,6 +353,7 @@ typedef struct UserRecord {
|
|||
int removable;
|
||||
int enforce_password_policy;
|
||||
int auto_login;
|
||||
int drop_caches;
|
||||
|
||||
uint64_t stop_delay_usec; /* How long to leave systemd --user around on log-out */
|
||||
int kill_processes; /* Whether to kill user processes forcibly on log-out */
|
||||
|
@ -419,6 +420,7 @@ int user_record_removable(UserRecord *h);
|
|||
usec_t user_record_ratelimit_interval_usec(UserRecord *h);
|
||||
uint64_t user_record_ratelimit_burst(UserRecord *h);
|
||||
bool user_record_can_authenticate(UserRecord *h);
|
||||
bool user_record_drop_caches(UserRecord *h);
|
||||
|
||||
int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret);
|
||||
|
||||
|
|
Loading…
Reference in a new issue