]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace-util: introduce netns_acquire()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 19 Jan 2024 02:34:17 +0000 (11:34 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 19 Jan 2024 06:06:08 +0000 (15:06 +0900)
Similar to userns_acquire(), but for network namespace.

src/basic/namespace-util.c
src/basic/namespace-util.h

index 2ecce5fa6148f90fa9dd06b536ff5763681fb495..d517263b36b147bdc245ef707967bb513b2ca851 100644 (file)
@@ -255,6 +255,33 @@ int userns_acquire(const char *uid_map, const char *gid_map) {
         return TAKE_FD(userns_fd);
 }
 
+int netns_acquire(void) {
+        _cleanup_(sigkill_waitp) pid_t pid = 0;
+        _cleanup_close_ int netns_fd = -EBADF;
+        int r;
+
+        /* Forks off a process in a new network namespace, acquires a network namespace fd, and then kills
+         * the process again. This way we have a netns fd that is not bound to any process. */
+
+        r = safe_fork("(sd-mknetns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_NETNS, &pid);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to fork process (sd-mknetns): %m");
+        if (r == 0)
+                /* Child. We do nothing here, just freeze until somebody kills us. */
+                freeze();
+
+        r = namespace_open(pid,
+                           /* ret_pidns_fd = */ NULL,
+                           /* ret_mntns_fd = */ NULL,
+                           &netns_fd,
+                           /* ret_userns_fd = */ NULL,
+                           /* ret_root_fd = */ NULL);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to open netns fd: %m");
+
+        return TAKE_FD(netns_fd);
+}
+
 int in_same_namespace(pid_t pid1, pid_t pid2, NamespaceType type) {
         const char *ns_path;
         struct stat ns_st1, ns_st2;
index cd5b8ecab594ac48b90d44373d1e43323a768103..d1d015612fd2d2fd4880022b03e5e81e2ca16b45 100644 (file)
@@ -51,4 +51,5 @@ static inline bool userns_shift_range_valid(uid_t shift, uid_t range) {
 }
 
 int userns_acquire(const char *uid_map, const char *gid_map);
+int netns_acquire(void);
 int in_same_namespace(pid_t pid1, pid_t pid2, NamespaceType type);