From: Yu Watanabe Date: Tue, 2 Jun 2026 02:32:26 +0000 (+0900) Subject: namespace-util: introduce network_namespace_is_init() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfe19f1350bf82d0499d3370179e963f74c9e3c7;p=thirdparty%2Fsystemd.git namespace-util: introduce network_namespace_is_init() --- diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index db95ab86275..72e7005c946 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -410,12 +411,48 @@ int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, return true; } +int network_namespace_is_init(int socket_fd) { + struct stat a, b; + int r; + + /* This works only when privileged. */ + + r = RET_NERRNO(stat(pid_namespace_path(1, NAMESPACE_NET), &a)); + if (r == -ENOENT) { + /* If the /proc/ns/ API is not around in /proc/ then ns is off in the kernel and we are in the init ns */ + r = proc_mounted(); + if (r < 0) + return -ENOENT; /* If we can't determine if /proc/ is mounted propagate original error */ + + return r ? true : -ENOSYS; + } + if (r < 0) + return r; + + if (socket_fd >= 0) { + _cleanup_close_ int netns = ioctl(socket_fd, SIOCGSKNS); + if (netns < 0) + return -errno; + + if (fstat(netns, &b) < 0) + return -errno; + } else { + if (stat(pid_namespace_path(0, NAMESPACE_NET), &b) < 0) + return -errno; + } + + return stat_inode_same(&a, &b); +} + int namespace_is_init(NamespaceType type) { int r; assert(type >= 0); assert(type < _NAMESPACE_TYPE_MAX); + if (type == NAMESPACE_NET) + return network_namespace_is_init(/* socket_fd= */ -EBADF); + if (namespace_info[type].root_inode == 0) return -EBADR; /* Cannot answer this question */ diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index b82efc826b7..d0eff636a9d 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -52,6 +52,7 @@ int fd_is_namespace(int fd, NamespaceType type); int is_our_namespace(int fd, NamespaceType type); int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); +int network_namespace_is_init(int socket_fd); int namespace_is_init(NamespaceType type); int pidref_in_same_namespace(PidRef *pid1, PidRef *pid2, NamespaceType type); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index b9f4e35f2e1..7b95a591355 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -253,6 +253,8 @@ TEST(namespace_is_init) { r = namespace_is_init(t); if (r == -EBADR) log_info_errno(r, "In root namespace of type '%s': don't know", namespace_info[t].proc_name); + else if (t == NAMESPACE_NET && ERRNO_IS_NEG_PRIVILEGE(r)) + log_info_errno(r, "In root namespace of type '%s': no privilege: %m", namespace_info[t].proc_name); else { ASSERT_OK(r); log_info("In root namespace of type '%s': %s", namespace_info[t].proc_name, yes_no(r));