1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-13 01:57:42 +03:00

pid1: unify implemenation of /run/ disk space safety check a bit

reload/reexec currently used a separate implementation of the /run/ disk
space check, different from the one used for switch-root, even though
the code is mostly the same. The one difference is that the former
checks are authoritative, the latter are just informational (that's
because refusing a reload/reexec is relatively benign, but refusing a
switch-root quite troublesome, since this code is entered when it's
already "too late" to turn turn back, i.e. when the preparatory
transaction to initiate the switch root are already fully executed.

Let's share some code, and unify codepaths.

(This is preparation for later addition of a "userspace reboot" concept)

No change in behaviour, just refactoring.
This commit is contained in:
Lennart Poettering 2023-04-28 16:14:32 +02:00 committed by Luca Boccassi
parent 5ae89ef347
commit c23e9b6a64

View File

@ -1475,19 +1475,32 @@ static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bu
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
}
static int verify_run_space(const char *message, sd_bus_error *error) {
static int get_run_space(uint64_t *ret, sd_bus_error *error) {
struct statvfs svfs;
uint64_t available;
assert(ret);
if (statvfs("/run/systemd", &svfs) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
*ret = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
return 0;
}
static int verify_run_space(const char *message, sd_bus_error *error) {
uint64_t available = 0; /* unnecessary, but used to trick out gcc's incorrect maybe-uninitialized warning */
int r;
assert(message);
r = get_run_space(&available, error);
if (r < 0)
return r;
if (available < RELOAD_DISK_SPACE_MIN)
return sd_bus_error_setf(error,
BUS_ERROR_DISK_FULL,
"%s, not enough space available on /run/systemd. "
"%s, not enough space available on /run/systemd/. "
"Currently, %s are free, but a safety buffer of %s is enforced.",
message,
FORMAT_BYTES(available),
@ -1500,6 +1513,8 @@ int verify_run_space_and_log(const char *message) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(message);
r = verify_run_space(message, &error);
if (r < 0)
return log_error_errno(r, "%s", bus_error_message(&error, r));
@ -1507,6 +1522,26 @@ int verify_run_space_and_log(const char *message) {
return 0;
}
static int verify_run_space_permissive(const char *message, sd_bus_error *error) {
uint64_t available = 0; /* unnecessary, but used to trick out gcc's incorrect maybe-uninitialized warning */
int r;
assert(message);
r = get_run_space(&available, error);
if (r < 0)
return r;
if (available < RELOAD_DISK_SPACE_MIN)
log_warning("Dangerously low amount of free space on /run/systemd/, %s.\n"
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
message,
FORMAT_BYTES(available),
FORMAT_BYTES(RELOAD_DISK_SPACE_MIN));
return 0;
}
static void log_caller(sd_bus_message *message, Manager *manager, const char *method) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *comm = NULL;
@ -1709,22 +1744,13 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
_cleanup_free_ char *ri = NULL, *rt = NULL;
const char *root, *init;
Manager *m = ASSERT_PTR(userdata);
struct statvfs svfs;
uint64_t available;
int r;
assert(message);
if (statvfs("/run/systemd", &svfs) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m");
available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize;
if (available < RELOAD_DISK_SPACE_MIN)
log_warning("Dangerously low amount of free space on /run/systemd, root switching might fail.\n"
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
FORMAT_BYTES(available),
FORMAT_BYTES(RELOAD_DISK_SPACE_MIN));
r = verify_run_space_permissive("root switching may fail", error);
if (r < 0)
return r;
r = mac_selinux_access_check(message, "reboot", error);
if (r < 0)