]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
uidgid: add map_id_range_up()
authorChristian Brauner <brauner@kernel.org>
Tue, 4 Feb 2025 11:27:46 +0000 (12:27 +0100)
committerChristian Brauner <brauner@kernel.org>
Wed, 12 Feb 2025 11:12:27 +0000 (12:12 +0100)
Add map_id_range_up() to verify that the full kernel id range can be
mapped up in a given idmapping. This will be used in follow-up patches.

Link: https://lore.kernel.org/r/20250204-work-mnt_idmap-statmount-v2-1-007720f39f2e@kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
include/linux/uidgid.h
kernel/user_namespace.c

index f85ec5613721fe1b4fc6c51b80c9a32cc617c19b..2dc767e08f54475df50e782a83e01dbc86e494a5 100644 (file)
@@ -132,6 +132,7 @@ static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid)
 
 u32 map_id_down(struct uid_gid_map *map, u32 id);
 u32 map_id_up(struct uid_gid_map *map, u32 id);
+u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count);
 
 #else
 
@@ -186,6 +187,11 @@ static inline u32 map_id_down(struct uid_gid_map *map, u32 id)
        return id;
 }
 
+static inline u32 map_id_range_up(struct uid_gid_map *map, u32 id, u32 count)
+{
+       return id;
+}
+
 static inline u32 map_id_up(struct uid_gid_map *map, u32 id)
 {
        return id;
index aa0b2e47f2f21bef96c45e09aaa4bc05dc5216b9..682f40d5632d44b983f8b2322fdfd1f7d1d47d2c 100644 (file)
@@ -238,7 +238,7 @@ EXPORT_SYMBOL(__put_user_ns);
 struct idmap_key {
        bool map_up; /* true  -> id from kid; false -> kid from id */
        u32 id; /* id to find */
-       u32 count; /* == 0 unless used with map_id_range_down() */
+       u32 count;
 };
 
 /*
@@ -343,16 +343,19 @@ u32 map_id_down(struct uid_gid_map *map, u32 id)
  * UID_GID_MAP_MAX_BASE_EXTENTS.
  */
 static struct uid_gid_extent *
-map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
+map_id_range_up_base(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
 {
        unsigned idx;
-       u32 first, last;
+       u32 first, last, id2;
+
+       id2 = id + count - 1;
 
        /* Find the matching extent */
        for (idx = 0; idx < extents; idx++) {
                first = map->extent[idx].lower_first;
                last = first + map->extent[idx].count - 1;
-               if (id >= first && id <= last)
+               if (id >= first && id <= last &&
+                   (id2 >= first && id2 <= last))
                        return &map->extent[idx];
        }
        return NULL;
@@ -363,28 +366,28 @@ map_id_up_base(unsigned extents, struct uid_gid_map *map, u32 id)
  * Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
  */
 static struct uid_gid_extent *
-map_id_up_max(unsigned extents, struct uid_gid_map *map, u32 id)
+map_id_range_up_max(unsigned extents, struct uid_gid_map *map, u32 id, u32 count)
 {
        struct idmap_key key;
 
        key.map_up = true;
-       key.count = 1;
+       key.count = count;
        key.id = id;
 
        return bsearch(&key, map->reverse, extents,
                       sizeof(struct uid_gid_extent), cmp_map_id);
 }
 
-u32 map_id_up(struct uid_gid_map *map, u32 id)
+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();
 
        if (extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
-               extent = map_id_up_base(extents, map, id);
+               extent = map_id_range_up_base(extents, map, id, count);
        else
-               extent = map_id_up_max(extents, map, id);
+               extent = map_id_range_up_max(extents, map, id, count);
 
        /* Map the id or note failure */
        if (extent)
@@ -395,6 +398,11 @@ u32 map_id_up(struct uid_gid_map *map, u32 id)
        return id;
 }
 
+u32 map_id_up(struct uid_gid_map *map, u32 id)
+{
+       return map_id_range_up(map, id, 1);
+}
+
 /**
  *     make_kuid - Map a user-namespace uid pair into a kuid.
  *     @ns:  User namespace that the uid is in