summaryrefslogtreecommitdiff
path: root/src/network/networkctl.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-05-26 10:39:33 +0200
committerLennart Poettering <lennart@poettering.net>2021-05-26 10:40:57 +0200
commit3b085db3b67d72065defa94a823b8ac62131a0b7 (patch)
treeceff98d982f84d1648f4d4f852760cd67b1d3e6e /src/network/networkctl.c
parentf2ef8b28a5266a0070b0cb8b6375e418a5300975 (diff)
downloadsystemd-3b085db3b67d72065defa94a823b8ac62131a0b7.tar.gz
networkctl: politely refuse being called from a different netns than the networkd instance we talk to
Otherwise things get very confusing since we mix up netens data from our client side and from the data we retrieve from networkd. In the long run we should teach networkctl some switch to operate safely on other netns, and in that case also determine the right networkd instance for that namespace. Fixes: #19236
Diffstat (limited to 'src/network/networkctl.c')
-rw-r--r--src/network/networkctl.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 9d3e3f033b..619ef91288 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -2993,6 +2993,45 @@ static int networkctl_main(int argc, char *argv[]) {
return dispatch_verb(argc, argv, verbs, NULL);
}
+static int check_netns_match(void) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+ struct stat st;
+ uint64_t id;
+ int r;
+
+ r = sd_bus_open_system(&bus);
+ if (r < 0)
+ return log_error_errno(r, "Failed to connect system bus: %m");
+
+ r = sd_bus_get_property_trivial(
+ bus,
+ "org.freedesktop.network1",
+ "/org/freedesktop/network1",
+ "org.freedesktop.network1.Manager",
+ "NamespaceId",
+ &error,
+ 't',
+ &id);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to query network namespace of networkd, ignoring: %s", bus_error_message(&error, r));
+ return 0;
+ }
+ if (id == 0) {
+ log_debug("systemd-networkd.service not running in a network namespace (?), skipping netns check.");
+ return 0;
+ }
+
+ if (stat("/proc/self/ns/net", &st) < 0)
+ return log_error_errno(r, "Failed to determine our own network namespace ID: %m");
+
+ if (id != st.st_ino)
+ return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
+ "networkctl must be invoked in same network namespace as systemd-networkd.service.");
+
+ return 0;
+}
+
static void warn_networkd_missing(void) {
if (access("/run/systemd/netif/state", F_OK) >= 0)
@@ -3010,6 +3049,10 @@ static int run(int argc, char* argv[]) {
if (r <= 0)
return r;
+ r = check_netns_match();
+ if (r < 0)
+ return r;
+
warn_networkd_missing();
return networkctl_main(argc, argv);