[RFC PATCH v2 18/41] fs: keep UUID and GUID owners off filesystems that can't store them
Jan Koester
jan.koester at tuxist.de
Wed Oct 21 03:15:38 UTC 2026
Filesystems write inode owners with i_uid_read()/i_gid_read(), which
turn a UUID or GUID into -1. Add SB_I_UID_R for filesystems that can
store such owners, and refuse them elsewhere with -EOVERFLOW, the error
already used for ids without a mapping in the filesystem's namespace:
- notify_change() refuses ATTR_UID/ATTR_GID with such an id,
- fsuidgid_has_mapping() is false for a caller whose fsuid or fsgid is
one, so may_create() and friends refuse to create inodes owned by it.
No filesystem sets the flag yet.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Jan Koester <jan.koester at tuxist.de>
---
fs/attr.c | 7 +++++++
include/linux/fs.h | 29 +++++++++++++++++++++++++----
include/linux/fs/super_types.h | 1 +
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/fs/attr.c b/fs/attr.c
index 71888ac903..09d51b1a32 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -526,6 +526,13 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
!vfsgid_has_fsmapping(idmap, inode->i_sb->s_user_ns,
attr->ia_vfsgid))
return -EOVERFLOW;
+ /* and that the filesystem can store a UUID or GUID owner */
+ if (ia_valid & ATTR_UID &&
+ !sb_can_own_kuid(inode->i_sb, vfsuid_into_kuid(attr->ia_vfsuid)))
+ return -EOVERFLOW;
+ if (ia_valid & ATTR_GID &&
+ !sb_can_own_kgid(inode->i_sb, vfsgid_into_kgid(attr->ia_vfsgid)))
+ return -EOVERFLOW;
/* Don't allow modifications of files with invalid uids or
* gids unless those uids & gids are being made valid.
diff --git a/include/linux/fs.h b/include/linux/fs.h
index deb411e866..05c4611c87 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1563,14 +1563,35 @@ static inline void inode_fsgid_set(struct inode *inode,
inode->i_gid = mapped_fsgid(idmap, i_user_ns(inode));
}
+/**
+ * sb_can_own_kuid() - check whether a filesystem can store an owner
+ * @sb: the superblock
+ * @kuid: the owner
+ *
+ * Classic ids fit any filesystem; UUIDs and GUIDs only those that set
+ * SB_I_UID_R. Elsewhere i_uid_read() would turn them into -1.
+ *
+ * Return: true if @sb can store @kuid.
+ */
+static inline bool sb_can_own_kuid(const struct super_block *sb, kuid_t kuid)
+{
+ return uid_is_legacy(kuid) || (sb->s_iflags & SB_I_UID_R);
+}
+
+static inline bool sb_can_own_kgid(const struct super_block *sb, kgid_t kgid)
+{
+ return gid_is_legacy(kgid) || (sb->s_iflags & SB_I_UID_R);
+}
+
/**
* fsuidgid_has_mapping() - check whether caller's fsuid/fsgid is mapped
* @sb: the superblock we want a mapping in
* @idmap: idmap of the relevant mount
*
* Check whether the caller's fsuid and fsgid have a valid mapping in the
- * s_user_ns of the superblock @sb. If the caller is on an idmapped mount map
- * the caller's fsuid and fsgid according to the @idmap first.
+ * s_user_ns of the superblock @sb, and whether @sb can store them as owner
+ * of a new inode. If the caller is on an idmapped mount map the caller's
+ * fsuid and fsgid according to the @idmap first.
*
* Return: true if fsuid and fsgid is mapped, false if not.
*/
@@ -1582,10 +1603,10 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb,
kgid_t kgid;
kuid = mapped_fsuid(idmap, fs_userns);
- if (!uid_valid(kuid))
+ if (!uid_valid(kuid) || !sb_can_own_kuid(sb, kuid))
return false;
kgid = mapped_fsgid(idmap, fs_userns);
- if (!gid_valid(kgid))
+ if (!gid_valid(kgid) || !sb_can_own_kgid(sb, kgid))
return false;
return kuid_has_mapping(fs_userns, kuid) &&
kgid_has_mapping(fs_userns, kgid);
diff --git a/include/linux/fs/super_types.h b/include/linux/fs/super_types.h
index ecd96aeb1c..1f5c596b18 100644
--- a/include/linux/fs/super_types.h
+++ b/include/linux/fs/super_types.h
@@ -352,5 +352,6 @@ struct super_block {
#define SB_I_NOIDMAP 0x00002000 /* No idmapped mounts on this superblock */
#define SB_I_ALLOW_HSM 0x00004000 /* Allow HSM events on this superblock */
#define SB_I_NO_DATA_INTEGRITY 0x00008000 /* fs cannot guarantee data persistence on sync */
+#define SB_I_UID_R 0x00010000 /* fs stores UUID and GUID owners, not just classic ids */
#endif /* _LINUX_FS_SUPER_TYPES_H */
--
2.56.0
More information about the Linux-security-module-archive
mailing list