[PATCH RFC v3 14/90] fs: take no id of a cell for a mount option
From: Josef Bacik
Date: Thu Nov 05 2026 - 10:04:50 EST
Most filesystems with a uid= or gid= mount option assign that id to some
or all of their files, without checking whether they may hold it. For an
id of the window this has the same effect as a chown to it: the files
would belong to whichever cell is lent the block next.
Only root in the initial user namespace can name such an id, because no
other user namespace maps it. But the rule is about the value of the id,
not about the caller. Nobody is supposed to name the ids of a cell, not
even its builder.
Refuse ids of the window in fs_param_is_uid() and fs_param_is_gid(). About
two dozen filesystems parse their options with these.
Not covered are filesystems that parse the number themselves, such as udf,
ntfs, zonefs, functionfs, hypfs and spufs, the access= option of 9p, and
the anonymous ids of an nfsd export. The design document lists them.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
fs/fs_parser.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/fs_parser.c b/fs/fs_parser.c
index b4cc4cce518a..0e8c84459c45 100644
--- a/fs/fs_parser.c
+++ b/fs/fs_parser.c
@@ -5,6 +5,7 @@
* Written by David Howells (dhowells@xxxxxxxxxx)
*/
+#include <linux/cell_ids.h>
#include <linux/export.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
@@ -331,6 +332,9 @@ int fs_param_is_uid(struct p_log *log, const struct fs_parameter_spec *p,
uid = make_kuid(current_user_ns(), result->uint_32);
if (!uid_valid(uid))
return inval_plog(log, "Invalid uid '%s'", param->string);
+ /* Nobody names an id that is lent to a cell, see kuid_storable(). */
+ if (cell_id_in_window(__kuid_val(uid)))
+ return inval_plog(log, "Invalid uid '%s'", param->string);
result->uid = uid;
return 0;
@@ -348,6 +352,9 @@ int fs_param_is_gid(struct p_log *log, const struct fs_parameter_spec *p,
gid = make_kgid(current_user_ns(), result->uint_32);
if (!gid_valid(gid))
return inval_plog(log, "Invalid gid '%s'", param->string);
+ /* See fs_param_is_uid(). */
+ if (cell_id_in_window(__kgid_val(gid)))
+ return inval_plog(log, "Invalid gid '%s'", param->string);
result->gid = gid;
return 0;
--
2.55.0