[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251110102908.3634466-1-tiantao6@hisilicon.com>
Date: Mon, 10 Nov 2025 18:29:08 +0800
From: Tian Tao <tiantao6@...ilicon.com>
To: <brauner@...nel.org>, <jack@...e.cz>, <cyphar@...har.com>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH] userns: use acquire/release semantics for idmap nr_extents
Replace plain loads followed by smp_rmb() with smp_load_acquire() when
reading uid/gid/projid map->nr_extents, and replace the writer side
sequence of smp_wmb(); map->nr_extents = val with an explicit
smp_store_release(&map->nr_extents, val) when installing a new idmap.
Signed-off-by: Tian Tao <tiantao6@...ilicon.com>
---
kernel/user_namespace.c | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 03cb63883d04..213f7814dc45 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -318,8 +318,11 @@ map_id_range_down_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 co
static u32 map_id_range_down(struct uid_gid_map *map, u32 id, u32 count)
{
struct uid_gid_extent *extent;
- unsigned extents = map->nr_extents;
- smp_rmb();
+/* Acquire semantics: pair with the writer's smp_store_release()
+ * when publishing a new map->nr_extents so that readers see the
+ * extent array contents that were written before nr_extents.
+ */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
extent = map_id_range_down_base(extents, map, id, count);
@@ -384,8 +387,11 @@ map_id_range_up_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count
u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count)
{
struct uid_gid_extent *extent;
- unsigned extents = map->nr_extents;
- smp_rmb();
+/* Acquire semantics: pair with the writer's smp_store_release()
+ * when publishing a new map->nr_extents so that readers see the
+ * extent array contents that were written before nr_extents.
+ */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
extent = map_id_range_up_base(extents, map, id, count);
@@ -677,8 +683,11 @@ static void *m_start(struct seq_file *seq, loff_t *ppos,
struct uid_gid_map *map)
{
loff_t pos = *ppos;
- unsigned extents = map->nr_extents;
- smp_rmb();
+/* Acquire semantics: pair with the writer's smp_store_release()
+ * when publishing a new map->nr_extents so that readers see the
+ * extent array contents that were written before nr_extents.
+ */
+ unsigned int extents = smp_load_acquire(&map->nr_extents);
if (pos >= extents)
return NULL;
@@ -1099,8 +1108,12 @@ static ssize_t map_write(struct file *file, const char __user *buf,
map->forward = new_map.forward;
map->reverse = new_map.reverse;
}
- smp_wmb();
- map->nr_extents = new_map.nr_extents;
+ /* Release semantics: publish the extent arrays (map->forward/map->reverse
+ * or map->extent) and then update map->nr_extents. Readers use
+ * smp_load_acquire(&map->nr_extents) so they will see the array contents
+ * written before this store.
+ */
+ smp_store_release(&map->nr_extents, new_map.nr_extents);
*ppos = count;
ret = count;
--
2.33.0
Powered by blists - more mailing lists