[PATCH RFC v3 15/90] fs: let an idmapping pin the ids of a cell
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:05:13 EST
A struct mnt_idmap holds a copy of the id maps of the user namespace it
was created from. The copy does not pin the namespace.
So a mount that was idmapped for a cell can outlive the cell. It would
keep translating on-disk ids into the ids of the block after the block has
been lent to another cell. A set-uid file on that mount would then run as
the root of the new cell.
Let an idmapping that was created from the user namespace of a cell hold a
reference on that namespace. The block is released when the namespace is
freed, so it cannot be lent again while such a mount exists.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
fs/mnt_idmapping.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/fs/mnt_idmapping.c b/fs/mnt_idmapping.c
index bed57094cef0..93a34bc93efd 100644
--- a/fs/mnt_idmapping.c
+++ b/fs/mnt_idmapping.c
@@ -21,6 +21,14 @@ struct mnt_idmap {
struct uid_gid_map uid_map;
struct uid_gid_map gid_map;
refcount_t count;
+#ifdef CONFIG_CELLS
+ /*
+ * The maps are a copy, and a copy pins nothing. The ids of a cell are
+ * only lent to it, until its user namespace is freed, so an idmapping
+ * that names them holds on to that.
+ */
+ struct user_namespace *cell_ns;
+#endif
};
/*
@@ -281,6 +289,9 @@ static void free_mnt_idmap(struct mnt_idmap *idmap)
kfree(idmap->gid_map.forward);
kfree(idmap->gid_map.reverse);
}
+#ifdef CONFIG_CELLS
+ put_user_ns(idmap->cell_ns);
+#endif
kfree(idmap);
}
@@ -294,6 +305,10 @@ struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns)
return ERR_PTR(-ENOMEM);
refcount_set(&idmap->count, 1);
+#ifdef CONFIG_CELLS
+ if (userns_is_cell(mnt_userns))
+ idmap->cell_ns = get_user_ns(mnt_userns);
+#endif
ret = copy_mnt_idmap(&mnt_userns->uid_map, &idmap->uid_map);
if (!ret)
ret = copy_mnt_idmap(&mnt_userns->gid_map, &idmap->gid_map);
--
2.55.0