From 13339577c339b470986203fdc988db7a8c8dc87d Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 8 Mar 2023 15:30:19 +0100 Subject: [PATCH] namespace: Modernize shareable namespace functions --- src/core/namespace.c | 140 +++++++++++++++++++------------------------ src/core/namespace.h | 4 +- 2 files changed, 63 insertions(+), 81 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 252f5c9d2c..b4bb01bb74 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -24,6 +24,7 @@ #include "glyph-util.h" #include "label.h" #include "list.h" +#include "lock-util.h" #include "loop-util.h" #include "loopback-setup.h" #include "missing_syscall.h" @@ -2847,9 +2848,9 @@ int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) { return 0; } -int setup_shareable_ns(const int ns_storage_socket[static 2], unsigned long nsflag) { +int setup_shareable_ns(int ns_storage_socket[static 2], unsigned long nsflag) { _cleanup_close_ int ns = -EBADF; - int r, q; + int r; const char *ns_name, *ns_path; assert(ns_storage_socket); @@ -2867,57 +2868,47 @@ int setup_shareable_ns(const int ns_storage_socket[static 2], unsigned long nsfl * * It's a bit crazy, but hey, works great! */ - if (lockf(ns_storage_socket[0], F_LOCK, 0) < 0) + r = posix_lock(ns_storage_socket[0], LOCK_EX); + if (r < 0) + return r; + + CLEANUP_POSIX_UNLOCK(ns_storage_socket[0]); + + ns = receive_one_fd(ns_storage_socket[0], MSG_PEEK|MSG_DONTWAIT); + if (ns >= 0) { + /* Yay, found something, so let's join the namespace */ + r = RET_NERRNO(setns(ns, nsflag)); + if (r < 0) + return r; + + return 0; + } + + if (ns != -EAGAIN) + return ns; + + /* Nothing stored yet, so let's create a new namespace. */ + + if (unshare(nsflag) < 0) return -errno; - ns = receive_one_fd(ns_storage_socket[0], MSG_DONTWAIT); - if (ns == -EAGAIN) { - /* Nothing stored yet, so let's create a new namespace. */ + (void) loopback_setup(); - if (unshare(nsflag) < 0) { - r = -errno; - goto fail; - } + ns_path = strjoina("/proc/self/ns/", ns_name); + ns = open(ns_path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (ns < 0) + return -errno; - (void) loopback_setup(); + r = send_one_fd(ns_storage_socket[1], ns, MSG_DONTWAIT); + if (r < 0) + return r; - ns_path = strjoina("/proc/self/ns/", ns_name); - ns = open(ns_path, O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (ns < 0) { - r = -errno; - goto fail; - } - - r = 1; - - } else if (ns < 0) { - r = ns; - goto fail; - - } else { - /* Yay, found something, so let's join the namespace */ - if (setns(ns, nsflag) < 0) { - r = -errno; - goto fail; - } - - r = 0; - } - - q = send_one_fd(ns_storage_socket[1], ns, MSG_DONTWAIT); - if (q < 0) { - r = q; - goto fail; - } - -fail: - (void) lockf(ns_storage_socket[0], F_ULOCK, 0); - return r; + return 1; } -int open_shareable_ns_path(const int ns_storage_socket[static 2], const char *path, unsigned long nsflag) { +int open_shareable_ns_path(int ns_storage_socket[static 2], const char *path, unsigned long nsflag) { _cleanup_close_ int ns = -EBADF; - int q, r; + int r; assert(ns_storage_socket); assert(ns_storage_socket[0] >= 0); @@ -2928,44 +2919,35 @@ int open_shareable_ns_path(const int ns_storage_socket[static 2], const char *pa * it. This is supposed to be called ahead of time, i.e. before setup_shareable_ns() which will * allocate a new anonymous ns if needed. */ - if (lockf(ns_storage_socket[0], F_LOCK, 0) < 0) + r = posix_lock(ns_storage_socket[0], LOCK_EX); + if (r < 0) + return r; + + CLEANUP_POSIX_UNLOCK(ns_storage_socket[0]); + + ns = receive_one_fd(ns_storage_socket[0], MSG_PEEK|MSG_DONTWAIT); + if (ns >= 0) + return 0; + if (ns != -EAGAIN) + return ns; + + /* Nothing stored yet. Open the file from the file system. */ + + ns = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (ns < 0) return -errno; - ns = receive_one_fd(ns_storage_socket[0], MSG_DONTWAIT); - if (ns == -EAGAIN) { - /* Nothing stored yet. Open the file from the file system. */ + r = fd_is_ns(ns, nsflag); + if (r == 0) + return -EINVAL; + if (r < 0 && r != -EUCLEAN) /* EUCLEAN: we don't know */ + return r; - ns = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); - if (ns < 0) { - r = -errno; - goto fail; - } + r = send_one_fd(ns_storage_socket[1], ns, MSG_DONTWAIT); + if (r < 0) + return r; - r = fd_is_ns(ns, nsflag); - if (r == 0) { /* Not a ns of our type? Refuse early. */ - r = -EINVAL; - goto fail; - } - if (r < 0 && r != -EUCLEAN) /* EUCLEAN: we don't know */ - goto fail; - - r = 1; - - } else if (ns < 0) { - r = ns; - goto fail; - } else - r = 0; /* Already allocated */ - - q = send_one_fd(ns_storage_socket[1], ns, MSG_DONTWAIT); - if (q < 0) { - r = q; - goto fail; - } - -fail: - (void) lockf(ns_storage_socket[0], F_ULOCK, 0); - return r; + return 1; } bool ns_type_supported(NamespaceType type) { diff --git a/src/core/namespace.h b/src/core/namespace.h index 74f78784b6..52ab6c4f2f 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -153,8 +153,8 @@ int setup_tmp_dirs( char **tmp_dir, char **var_tmp_dir); -int setup_shareable_ns(const int ns_storage_socket[static 2], unsigned long nsflag); -int open_shareable_ns_path(const int netns_storage_socket[static 2], const char *path, unsigned long nsflag); +int setup_shareable_ns(int ns_storage_socket[static 2], unsigned long nsflag); +int open_shareable_ns_path(int netns_storage_socket[static 2], const char *path, unsigned long nsflag); const char* protect_home_to_string(ProtectHome p) _const_; ProtectHome protect_home_from_string(const char *s) _pure_;