[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250509072054.148257-4-chenridong@huaweicloud.com>
Date: Fri, 9 May 2025 07:20:52 +0000
From: Chen Ridong <chenridong@...weicloud.com>
To: akpm@...ux-foundation.org,
paulmck@...nel.org,
bigeasy@...utronix.de,
legion@...nel.org,
roman.gushchin@...ux.dev,
brauner@...nel.org,
tglx@...utronix.de,
frederic@...nel.org,
peterz@...radead.org,
oleg@...hat.com,
joel.granados@...nel.org,
viro@...iv.linux.org.uk,
lorenzo.stoakes@...cle.com,
avagin@...gle.com,
mengensun@...cent.com,
linux@...ssschuh.net,
jlayton@...nel.org,
ruanjinjie@...wei.com,
kees@...nel.org
Cc: linux-kernel@...r.kernel.org,
lujialin4@...wei.com,
chenridong@...weicloud.com
Subject: [RFC next v2 3/5] user_namespace: add user_ns iteration helper
From: Chen Ridong <chenridong@...wei.com>
Add a helper function named 'ns_next_child_pre' that performs
a pre-order traversal of a namespace's descendants.
Signed-off-by: Chen Ridong <chenridong@...wei.com>
---
include/linux/user_namespace.h | 9 +++++++
kernel/user_namespace.c | 44 ++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index d84b2703caab..823df9267a4a 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -169,6 +169,15 @@ static inline void set_userns_rlimit_max(struct user_namespace *ns,
ns->rlimit_max[type] = max <= LONG_MAX ? max : LONG_MAX;
}
+struct user_namespace *ns_next_child(struct user_namespace *pos,
+ struct user_namespace *parent);
+struct user_namespace *ns_next_child_pre(struct user_namespace *pos,
+ struct user_namespace *root);
+
+#define ns_for_each_child_pre(pos, ns) \
+ for ((pos) = ns_next_child_pre(NULL, (ns)); (pos); \
+ (pos) = ns_next_child_pre((pos), (ns)))
+
#ifdef CONFIG_USER_NS
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index cbe8f96c3e60..9a2e77505b97 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -30,6 +30,50 @@ static bool new_idmap_permitted(const struct file *file,
struct uid_gid_map *map);
static void free_user_ns(struct work_struct *work);
+struct user_namespace *ns_next_child(struct user_namespace *pos,
+ struct user_namespace *parent)
+{
+ struct user_namespace *next;
+
+ if (!pos)
+ /* Get the first child of the parent. */
+ next = list_entry_rcu(parent->children.next, struct user_namespace, ns_node);
+ else
+ next = list_entry_rcu(pos->ns_node.next, struct user_namespace, ns_node);
+
+ if (&next->ns_node != &parent->children)
+ return next;
+
+ return NULL;
+}
+
+/* Should be called under rcu_read_lock() */
+struct user_namespace *ns_next_child_pre(struct user_namespace *pos,
+ struct user_namespace *root)
+{
+ struct user_namespace *next;
+
+
+ /* if first iteration, visit @root */
+ if (!pos)
+ return root;
+
+ /* visit the first child if exists */
+ next = ns_next_child(NULL, pos);
+ if (next)
+ return next;
+
+ /* no child, visit my or the closest ancestor's next ns_node */
+ while (pos != root) {
+ next = ns_next_child(pos, pos->parent);
+ if (next)
+ return next;
+ pos = pos->parent;
+ }
+
+ return NULL;
+}
+
static struct ucounts *inc_user_namespaces(struct user_namespace *ns, kuid_t uid)
{
return inc_ucount(ns, uid, UCOUNT_USER_NAMESPACES);
--
2.34.1
Powered by blists - more mailing lists