From: Yu Watanabe Date: Fri, 15 Mar 2024 15:55:10 +0000 (+0900) Subject: network/varlink: pass file descriptor of state directory with SetPersistentStorage... X-Git-Tag: v256-rc1~482^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bfd8f70cb8e8c273c2d80064d8c2d004d8a5e562;p=thirdparty%2Fsystemd.git network/varlink: pass file descriptor of state directory with SetPersistentStorage method The state directory is owned by systemd-networkd-persistent-storage.service, at least technically. Let's not directly access the storage through the path, but through the fd. Addresses https://github.com/systemd/systemd/pull/31746#issuecomment-1993556966. Suggested-by: Mike Yuan --- diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 7ee0961fa6a..91285e81160 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -102,6 +102,10 @@ static int varlink_connect_networkd(Varlink **ret_varlink) { if (r < 0) return log_error_errno(r, "Failed to connect to network service /run/systemd/netif/io.systemd.Network: %m"); + r = varlink_set_allow_fd_passing_output(vl, true); + if (r < 0) + return log_error_errno(r, "Failed to allow passing file descriptor through varlink: %m"); + r = varlink_call_and_log(vl, "io.systemd.Network.GetNamespaceId", /* parameters= */ NULL, &reply); if (r < 0) return r; @@ -2943,6 +2947,20 @@ static int verb_persistent_storage(int argc, char *argv[], void *userdata) { if (r < 0) return r; + if (ready) { + _cleanup_close_ int fd = -EBADF; + + fd = open("/var/lib/systemd/network/", O_CLOEXEC | O_DIRECTORY); + if (fd < 0) + return log_error_errno(errno, "Failed to open /var/lib/systemd/network/: %m"); + + r = varlink_push_fd(vl, fd); + if (r < 0) + return log_error_errno(r, "Failed to push file descriptor of /var/lib/systemd/network/ into varlink: %m"); + + TAKE_FD(fd); + } + return varlink_callb_and_log(vl, "io.systemd.Network.SetPersistentStorage", /* reply = */ NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR_BOOLEAN("Ready", ready))); } diff --git a/src/network/networkd-manager-varlink.c b/src/network/networkd-manager-varlink.c index b1b60ac48fb..2ccd1df1ef3 100644 --- a/src/network/networkd-manager-varlink.c +++ b/src/network/networkd-manager-varlink.c @@ -185,12 +185,18 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet return r; if (ready) { - _cleanup_close_ int fd = -EBADF; struct stat st, st_prev; + int fd; - fd = open("/var/lib/systemd/network/", O_CLOEXEC | O_DIRECTORY | O_PATH); + fd = varlink_peek_fd(vlink, 0); if (fd < 0) - return log_warning_errno(errno, "Failed to open /var/lib/systemd/network/: %m"); + return log_warning_errno(fd, "Failed to peek file descriptor of the persistent storage: %m"); + + r = fd_verify_safe_flags_full(fd, O_DIRECTORY); + if (r == -EREMOTEIO) + return log_warning_errno(r, "Passed persistent storage fd has unexpected flags, refusing."); + if (r < 0) + return log_warning_errno(r, "Failed to verify flags of passed persistent storage fd: %m"); r = fd_is_read_only_fs(fd); if (r < 0) @@ -201,7 +207,11 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet } if (fstat(fd, &st) < 0) - return log_warning_errno(r, "Failed to stat the persistent storage: %m"); + return log_warning_errno(r, "Failed to stat the passed persistent storage fd: %m"); + + r = stat_verify_directory(&st); + if (r < 0) + return log_warning_errno(r, "The passed persistent storage fd is not a directory, refusing: %m"); if (manager->persistent_storage_fd >= 0 && fstat(manager->persistent_storage_fd, &st_prev) >= 0 && @@ -225,9 +235,9 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet if (ready) { _cleanup_close_ int fd = -EBADF; - fd = open("/var/lib/systemd/network/", O_CLOEXEC | O_DIRECTORY | O_PATH); + fd = varlink_take_fd(vlink, 0); if (fd < 0) - return log_warning_errno(errno, "Failed to open /var/lib/systemd/network/: %m"); + return log_warning_errno(fd, "Failed to take file descriptor of the persistent storage: %m"); close_and_replace(manager->persistent_storage_fd, fd); } else @@ -238,6 +248,18 @@ static int vl_method_set_persistent_storage(Varlink *vlink, JsonVariant *paramet return varlink_reply(vlink, NULL); } +static int on_connect(VarlinkServer *s, Varlink *vlink, void *userdata) { + int r; + + assert(vlink); + + r = varlink_set_allow_fd_passing_input(vlink, true); + if (r < 0) + return log_warning_errno(r, "Failed to allow receiving file descriptor through varlink: %m"); + + return 0; +} + int manager_connect_varlink(Manager *m) { _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL; int r; @@ -274,6 +296,10 @@ int manager_connect_varlink(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to attach varlink connection to event loop: %m"); + r = varlink_server_bind_connect(s, on_connect); + if (r < 0) + return log_error_errno(r, "Failed to set on-connect callback for varlink: %m"); + m->varlink_server = TAKE_PTR(s); return 0; }