mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
serialize: add explicit calls for finishing serialization
These new calls will do three things: 1. in case of FILE* stuff: flush any pending bytes onto the fd, just in case 2. seal the backing memfd 3. seek back to the beginning. Note that this adds sealing to serialization: once we serialized fully, we'll seal the thing off for further modifications, before we pass the fd over to the target process. This should add a bit of robustness, and maybe finds a bug or two one day, if we accidentally write to a serialization that is complete.
This commit is contained in:
parent
4d98709cb2
commit
5d1e57b820
@ -516,8 +516,9 @@ int exec_spawn(
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(unit, r, "Failed to serialize parameters: %m");
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_unit_error_errno(unit, errno, "Failed to reseek on serialization stream: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(unit, r, "Failed to finish serialization stream: %m");
|
||||
|
||||
r = fd_cloexec(fileno(f), false);
|
||||
if (r < 0)
|
||||
|
@ -34,12 +34,12 @@
|
||||
#include "clock-warp.h"
|
||||
#include "conf-parser.h"
|
||||
#include "confidential-virt.h"
|
||||
#include "constants.h"
|
||||
#include "copy.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "crash-handler.h"
|
||||
#include "dbus-manager.h"
|
||||
#include "dbus.h"
|
||||
#include "constants.h"
|
||||
#include "dev-setup.h"
|
||||
#include "efi-random.h"
|
||||
#include "efivars.h"
|
||||
@ -87,6 +87,7 @@
|
||||
#include "seccomp-util.h"
|
||||
#include "selinux-setup.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "signal-util.h"
|
||||
#include "smack-setup.h"
|
||||
#include "special.h"
|
||||
@ -1233,14 +1234,14 @@ static int prepare_reexecute(
|
||||
assert(ret_f);
|
||||
assert(ret_fds);
|
||||
|
||||
r = manager_open_serialization(m, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create serialization file: %m");
|
||||
|
||||
/* Make sure nothing is really destructed when we shut down */
|
||||
m->n_reloading++;
|
||||
bus_manager_send_reloading(m, true);
|
||||
|
||||
r = manager_open_serialization(m, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create serialization file: %m");
|
||||
|
||||
fds = fdset_new();
|
||||
if (!fds)
|
||||
return log_oom();
|
||||
@ -1249,8 +1250,9 @@ static int prepare_reexecute(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to rewind serialization fd: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization file: %m");
|
||||
|
||||
r = fd_cloexec(fileno(f), false);
|
||||
if (r < 0)
|
||||
|
@ -186,10 +186,6 @@ int manager_serialize(
|
||||
return r;
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to flush serialization: %m");
|
||||
|
||||
r = bus_fdset_add_all(m, fds);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add bus sockets to serialization: %m");
|
||||
|
@ -80,6 +80,7 @@
|
||||
#include "rlimit-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "special.h"
|
||||
@ -3762,8 +3763,9 @@ int manager_reload(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to seek to beginning of serialization: %m");
|
||||
r = finish_serialization_file(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization: %m");
|
||||
|
||||
/* 💀 This is the point of no return, from here on there is no way back. 💀 */
|
||||
reloading = NULL;
|
||||
|
@ -199,8 +199,9 @@ static int do_execute(
|
||||
}
|
||||
|
||||
if (callbacks) {
|
||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to seek on serialization fd: %m");
|
||||
r = finish_serialization_fd(fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization fd: %m");
|
||||
|
||||
r = callbacks[STDOUT_GENERATE](TAKE_FD(fd), callback_args[STDOUT_GENERATE]);
|
||||
if (r < 0)
|
||||
@ -290,12 +291,14 @@ int execute_strv(
|
||||
if (!callbacks)
|
||||
return 0;
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||
return log_error_errno(errno, "Failed to rewind serialization fd: %m");
|
||||
r = finish_serialization_fd(fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to finish serialization fd: %m");
|
||||
|
||||
r = callbacks[STDOUT_CONSUME](TAKE_FD(fd), callback_args[STDOUT_CONSUME]);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse returned data: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -549,7 +549,7 @@ void deserialize_ratelimit(RateLimit *rl, const char *name, const char *value) {
|
||||
int open_serialization_fd(const char *ident) {
|
||||
assert(ident);
|
||||
|
||||
int fd = memfd_new(ident);
|
||||
int fd = memfd_new_full(ident, MFD_ALLOW_SEALING);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
@ -572,6 +572,33 @@ int open_serialization_file(const char *ident, FILE **ret) {
|
||||
return -errno;
|
||||
|
||||
*ret = TAKE_PTR(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int finish_serialization_fd(int fd) {
|
||||
assert(fd >= 0);
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||
return -errno;
|
||||
|
||||
return memfd_set_sealed(fd);
|
||||
}
|
||||
|
||||
int finish_serialization_file(FILE *f) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (fseeko(f, 0, SEEK_SET) < 0)
|
||||
return -errno;
|
||||
|
||||
int fd = fileno(f);
|
||||
if (fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
return memfd_set_sealed(fd);
|
||||
}
|
||||
|
@ -51,3 +51,6 @@ void deserialize_ratelimit(RateLimit *rl, const char *name, const char *value);
|
||||
|
||||
int open_serialization_fd(const char *ident);
|
||||
int open_serialization_file(const char *ident, FILE **ret);
|
||||
|
||||
int finish_serialization_fd(int fd);
|
||||
int finish_serialization_file(FILE *f);
|
||||
|
@ -127,6 +127,8 @@ TEST(open_serialization_fd) {
|
||||
assert_se(fd >= 0);
|
||||
|
||||
assert_se(write(fd, "test\n", 5) == 5);
|
||||
|
||||
assert_se(finish_serialization_fd(fd) >= 0);
|
||||
}
|
||||
|
||||
TEST(open_serialization_file) {
|
||||
@ -138,6 +140,8 @@ TEST(open_serialization_file) {
|
||||
assert_se(f);
|
||||
|
||||
assert_se(fwrite("test\n", 1, 5, f) == 5);
|
||||
|
||||
assert_se(finish_serialization_file(f) >= 0);
|
||||
}
|
||||
|
||||
TEST(fd_move_above_stdio) {
|
||||
|
Loading…
Reference in New Issue
Block a user