Skip to content

Commit

Permalink
uidgid: add map_id_range_up()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christian Brauner committed Feb 12, 2025
1 parent 3129946 commit 784ed43
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
6 changes: 6 additions & 0 deletions include/linux/uidgid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down
26 changes: 17 additions & 9 deletions kernel/user_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/*
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit 784ed43

Please sign in to comment.