mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-20 14:03:39 +03:00
Merge pull request #5219 from poettering/run-size-check
before reloading, check that /run/systemd has enough space
This commit is contained in:
commit
55295fd84d
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
@ -38,6 +39,7 @@
|
|||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "install.h"
|
#include "install.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "selinux-access.h"
|
#include "selinux-access.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
@ -48,6 +50,10 @@
|
|||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
#include "watchdog.h"
|
#include "watchdog.h"
|
||||||
|
|
||||||
|
/* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state there, and if
|
||||||
|
* we can't we'll fail badly. */
|
||||||
|
#define RELOAD_DISK_SPACE_MIN (UINT64_C(16) * UINT64_C(1024) * UINT64_C(1024))
|
||||||
|
|
||||||
static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
|
static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) {
|
||||||
return (runtime ? UNIT_FILE_RUNTIME : 0) |
|
return (runtime ? UNIT_FILE_RUNTIME : 0) |
|
||||||
(force ? UNIT_FILE_FORCE : 0);
|
(force ? UNIT_FILE_FORCE : 0);
|
||||||
@ -1312,6 +1318,40 @@ static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
|
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int verify_run_space(const char *message, sd_bus_error *error) {
|
||||||
|
struct statvfs svfs;
|
||||||
|
uint64_t available;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
|
||||||
|
return sd_bus_error_setf(error,
|
||||||
|
BUS_ERROR_DISK_FULL,
|
||||||
|
"%s, not enough space available on /run/systemd. "
|
||||||
|
"Currently, %s are free, but a safety buffer of %s is enforced.",
|
||||||
|
message,
|
||||||
|
format_bytes(fb_available, sizeof(fb_available), available),
|
||||||
|
format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify_run_space_and_log(const char *message) {
|
||||||
|
sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = verify_run_space(message, &error);
|
||||||
|
if (r < 0)
|
||||||
|
log_error_errno(r, "%s", bus_error_message(&error, r));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
Manager *m = userdata;
|
Manager *m = userdata;
|
||||||
int r;
|
int r;
|
||||||
@ -1319,6 +1359,10 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
|
|||||||
assert(message);
|
assert(message);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
r = verify_run_space("Refusing to reload", error);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = mac_selinux_access_check(message, "reload", error);
|
r = mac_selinux_access_check(message, "reload", error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1351,6 +1395,10 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
|
|||||||
assert(message);
|
assert(message);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
r = verify_run_space("Refusing to reexecute", error);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
r = mac_selinux_access_check(message, "reload", error);
|
r = mac_selinux_access_check(message, "reload", error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1469,11 +1517,26 @@ static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_er
|
|||||||
char *ri = NULL, *rt = NULL;
|
char *ri = NULL, *rt = NULL;
|
||||||
const char *root, *init;
|
const char *root, *init;
|
||||||
Manager *m = userdata;
|
Manager *m = userdata;
|
||||||
|
struct statvfs svfs;
|
||||||
|
uint64_t available;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX];
|
||||||
|
log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfuly. "
|
||||||
|
"Currently, %s are free, but %s are suggested. Proceeding anyway.",
|
||||||
|
format_bytes(fb_available, sizeof(fb_available), available),
|
||||||
|
format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN));
|
||||||
|
}
|
||||||
|
|
||||||
r = mac_selinux_access_check(message, "reboot", error);
|
r = mac_selinux_access_check(message, "reboot", error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -26,3 +26,5 @@ extern const sd_bus_vtable bus_manager_vtable[];
|
|||||||
void bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
|
void bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
|
||||||
void bus_manager_send_reloading(Manager *m, bool active);
|
void bus_manager_send_reloading(Manager *m, bool active);
|
||||||
void bus_manager_send_change_signal(Manager *m);
|
void bus_manager_send_change_signal(Manager *m);
|
||||||
|
|
||||||
|
int verify_run_space_and_log(const char *message);
|
||||||
|
@ -1984,7 +1984,9 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
|
|||||||
if (MANAGER_IS_SYSTEM(m)) {
|
if (MANAGER_IS_SYSTEM(m)) {
|
||||||
/* This is for compatibility with the
|
/* This is for compatibility with the
|
||||||
* original sysvinit */
|
* original sysvinit */
|
||||||
m->exit_code = MANAGER_REEXECUTE;
|
r = verify_run_space_and_log("Refusing to reexecute");
|
||||||
|
if (r >= 0)
|
||||||
|
m->exit_code = MANAGER_REEXECUTE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2061,7 +2063,9 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
case SIGHUP:
|
case SIGHUP:
|
||||||
m->exit_code = MANAGER_RELOAD;
|
r = verify_run_space_and_log("Refusing to reload");
|
||||||
|
if (r >= 0)
|
||||||
|
m->exit_code = MANAGER_RELOAD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
@ -2432,18 +2436,22 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int manager_open_serialization(Manager *m, FILE **_f) {
|
int manager_open_serialization(Manager *m, FILE **_f) {
|
||||||
const char *path;
|
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
assert(_f);
|
assert(_f);
|
||||||
|
|
||||||
path = MANAGER_IS_SYSTEM(m) ? "/run/systemd" : "/tmp";
|
fd = memfd_create("systemd-serialization", MFD_CLOEXEC);
|
||||||
fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
|
if (fd < 0) {
|
||||||
if (fd < 0)
|
const char *path;
|
||||||
return -errno;
|
|
||||||
|
|
||||||
log_debug("Serializing state to %s", path);
|
path = MANAGER_IS_SYSTEM(m) ? "/run/systemd" : "/tmp";
|
||||||
|
fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
log_debug("Serializing state to %s.", path);
|
||||||
|
} else
|
||||||
|
log_debug("Serializing state to memfd.");
|
||||||
|
|
||||||
f = fdopen(fd, "w+");
|
f = fdopen(fd, "w+");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -47,6 +47,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
|||||||
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
|
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
|
||||||
|
SD_BUS_ERROR_MAP(BUS_ERROR_DISK_FULL, ENOSPC),
|
||||||
|
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
|
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
|
||||||
#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
|
#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
|
||||||
#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
|
#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
|
||||||
|
#define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull"
|
||||||
|
|
||||||
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
|
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
|
||||||
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
|
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user