1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-26 03:22:00 +03:00

core: serialize/deserialize varlink sockets for pid1

Fixes #20330
This commit is contained in:
Anita Zhang 2022-10-05 00:13:32 -07:00
parent 658138f3af
commit 008798e90c
4 changed files with 126 additions and 0 deletions

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "clean-ipc.h"
#include "core-varlink.h"
#include "dbus.h"
#include "fd-util.h"
#include "fileio.h"
@ -13,6 +14,7 @@
#include "syslog-util.h"
#include "unit-serialize.h"
#include "user-util.h"
#include "varlink-internal.h"
int manager_open_serialization(Manager *m, FILE **ret_f) {
_cleanup_close_ int fd = -1;
@ -175,6 +177,10 @@ int manager_serialize(
if (r < 0)
return r;
r = varlink_server_serialize(m->varlink_server, f, fds);
if (r < 0)
return r;
(void) fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units) {
@ -290,6 +296,7 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) {
}
int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
bool deserialize_varlink_sockets = false;
int r = 0;
assert(m);
@ -516,7 +523,32 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
if (strv_extend(&m->deserialized_subscribed, val) < 0)
return -ENOMEM;
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
r = manager_setup_varlink_server(m, &s);
if (r < 0) {
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
continue;
}
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0) {
log_warning_errno(r, "Failed to attach varlink connection to event loop, ignoring: %m");
continue;
}
m->varlink_server = TAKE_PTR(s);
deserialize_varlink_sockets = true;
}
/* To void unnecessary deserialization (i.e. during reload vs. reexec) we only deserialize
* the FDs if we had to create a new m->varlink_server. The deserialize_varlink_sockets flag
* is initialized outside of the loop, is flipped after the VarlinkServer is setup, and
* remains set until all serialized contents are handled. */
if (deserialize_varlink_sockets)
(void) varlink_server_deserialize_one(m->varlink_server, val, fds);
} else {
ManagerTimestamp q;

View File

@ -326,6 +326,7 @@ shared_sources = files(
'utmp-wtmp.h',
'varlink.c',
'varlink.h',
'varlink-internal.h',
'verb-log-control.c',
'verb-log-control.h',
'verbs.c',

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdio.h>
#include "fdset.h"
#include "varlink.h"
int varlink_server_serialize(VarlinkServer *s, FILE *f, FDSet *fds);
int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *fds);

View File

@ -12,6 +12,7 @@
#include "list.h"
#include "process-util.h"
#include "selinux-util.h"
#include "serialize.h"
#include "set.h"
#include "socket-util.h"
#include "string-table.h"
@ -21,6 +22,7 @@
#include "umask-util.h"
#include "user-util.h"
#include "varlink.h"
#include "varlink-internal.h"
#define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U
#define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U
@ -2577,3 +2579,84 @@ int varlink_server_set_description(VarlinkServer *s, const char *description) {
return free_and_strdup(&s->description, description);
}
int varlink_server_serialize(VarlinkServer *s, FILE *f, FDSet *fds) {
assert(f);
assert(fds);
if (!s)
return 0;
LIST_FOREACH(sockets, ss, s->sockets) {
int copy;
assert(ss->address);
assert(ss->fd >= 0);
fprintf(f, "varlink-server-socket-address=%s", ss->address);
/* If we fail to serialize the fd, it will be considered an error during deserialization */
copy = fdset_put_dup(fds, ss->fd);
if (copy < 0)
return copy;
fprintf(f, " varlink-server-socket-fd=%i", copy);
fputc('\n', f);
}
return 0;
}
int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *fds) {
_cleanup_(varlink_server_socket_freep) VarlinkServerSocket *ss = NULL;
_cleanup_free_ char *address = NULL;
const char *v = ASSERT_PTR(value);
int r, fd = -1;
char *buf;
size_t n;
assert(s);
assert(fds);
n = strcspn(v, " ");
address = strndup(v, n);
if (!address)
return log_oom_debug();
if (v[n] != ' ')
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to deserialize VarlinkServerSocket: %s: %m", value);
v = startswith(v + n + 1, "varlink-server-socket-fd=");
if (!v)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Failed to deserialize VarlinkServerSocket fd %s: %m", value);
n = strcspn(v, " ");
buf = strndupa_safe(v, n);
r = safe_atoi(buf, &fd);
if (r < 0)
return log_debug_errno(r, "Unable to parse VarlinkServerSocket varlink-server-socket-fd=%s: %m", buf);
if (!fdset_contains(fds, fd))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
"VarlinkServerSocket varlink-server-socket-fd= has unknown fd %d: %m", fd);
ss = new(VarlinkServerSocket, 1);
if (!ss)
return log_oom_debug();
*ss = (VarlinkServerSocket) {
.server = s,
.address = TAKE_PTR(address),
.fd = fdset_remove(fds, fd),
};
r = varlink_server_add_socket_event_source(s, ss, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
return log_debug_errno(r, "Failed to add VarlinkServerSocket event source to the event loop: %m");
LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
return 0;
}