mirror of
https://github.com/torvalds/linux.git
synced 2026-10-23 23:51:02 +02:00
Merge patch series "userns: Add __counted_by_ptr attribute to struct uid_gid_map"
Add kunit tests for user namespace idmappings. * patches from https://patch.msgid.link/20260908222734.3048684-1-morbo@google.com: userns: Add KUnit test suite for uid_gid_map userns: Add __counted_by_ptr attribute to struct uid_gid_map Link: https://patch.msgid.link/20260908222734.3048684-1-morbo@google.com Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
commit
34a496d638
|
|
@ -29,8 +29,8 @@ struct uid_gid_map { /* 64 bytes -- 1 cache line */
|
|||
u32 nr_extents;
|
||||
};
|
||||
struct {
|
||||
struct uid_gid_extent *forward;
|
||||
struct uid_gid_extent *reverse;
|
||||
struct uid_gid_extent *forward __counted_by_ptr(nr_extents);
|
||||
struct uid_gid_extent *reverse __counted_by_ptr(nr_extents);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -207,6 +207,12 @@ extern bool in_userns(const struct user_namespace *ancestor,
|
|||
const struct user_namespace *child);
|
||||
extern bool current_in_userns(const struct user_namespace *target_ns);
|
||||
struct ns_common *ns_get_owner(struct ns_common *ns);
|
||||
|
||||
#if IS_ENABLED(CONFIG_USER_NS_MAP_KUNIT_TEST)
|
||||
extern int insert_extent(struct uid_gid_map *map, struct uid_gid_extent *extent);
|
||||
extern int sort_idmaps(struct uid_gid_map *map);
|
||||
#endif /* CONFIG_USER_NS_MAP_KUNIT_TEST */
|
||||
|
||||
#else
|
||||
|
||||
static inline struct user_namespace *get_user_ns(struct user_namespace *ns)
|
||||
|
|
|
|||
11
init/Kconfig
11
init/Kconfig
|
|
@ -1457,6 +1457,17 @@ config USER_NS
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config USER_NS_MAP_KUNIT_TEST
|
||||
tristate "KUint test for user namespace map insertion" if !KUNIT_ALL_TESTS
|
||||
depends on USER_NS && KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This builds the KUnit test for user namespace uid/gid map insertion.
|
||||
It validates map insertion, limits, dynamic allocation of the
|
||||
extended extents array, and mapping sorting functions.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PID_NS
|
||||
bool "PID Namespaces"
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o
|
|||
|
||||
obj-$(CONFIG_RESOURCE_KUNIT_TEST) += resource_kunit.o
|
||||
obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
|
||||
obj-$(CONFIG_USER_NS_MAP_KUNIT_TEST) += tests/user_ns_map_kunit.o
|
||||
|
||||
CFLAGS_kstack_erase.o += $(DISABLE_KSTACK_ERASE)
|
||||
CFLAGS_kstack_erase.o += $(call cc-option,-mgeneral-regs-only)
|
||||
|
|
|
|||
4
kernel/tests/.kunitconfig
Normal file
4
kernel/tests/.kunitconfig
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
CONFIG_KUNIT=y
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_USER_NS_MAP_KUNIT_TEST=y
|
||||
98
kernel/tests/user_ns_map_kunit.c
Normal file
98
kernel/tests/user_ns_map_kunit.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* KUnit test for user namespace map insertion and sorting.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "user_namespace: " fmt
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/user_namespace.h>
|
||||
|
||||
#define NR_EXTENTS (UID_GID_MAP_MAX_BASE_EXTENTS + 5)
|
||||
|
||||
static void user_ns_map_insert(struct kunit *test)
|
||||
{
|
||||
struct uid_gid_map map;
|
||||
struct uid_gid_extent extent;
|
||||
int i, ret;
|
||||
|
||||
memset(&map, 0, sizeof(map));
|
||||
|
||||
/* Insert up to UID_GID_MAP_MAX_BASE_EXTENTS elements */
|
||||
for (i = 0; i < UID_GID_MAP_MAX_BASE_EXTENTS; i++) {
|
||||
extent.first = i * 10;
|
||||
extent.lower_first = i * 100;
|
||||
extent.count = 5;
|
||||
|
||||
ret = insert_extent(&map, &extent);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, map.nr_extents, UID_GID_MAP_MAX_BASE_EXTENTS);
|
||||
|
||||
/* Verify the elements ended up in the 'extent' array */
|
||||
for (i = 0; i < UID_GID_MAP_MAX_BASE_EXTENTS; i++) {
|
||||
KUNIT_EXPECT_EQ(test, map.extent[i].first, i * 10);
|
||||
KUNIT_EXPECT_EQ(test, map.extent[i].lower_first, i * 100);
|
||||
KUNIT_EXPECT_EQ(test, map.extent[i].count, 5);
|
||||
}
|
||||
}
|
||||
|
||||
static void user_ns_map_insert_extended(struct kunit *test)
|
||||
{
|
||||
struct uid_gid_map map;
|
||||
struct uid_gid_extent extent;
|
||||
int i, ret;
|
||||
|
||||
memset(&map, 0, sizeof(map));
|
||||
|
||||
/* Insert more than UID_GID_MAP_MAX_BASE_EXTENTS elements */
|
||||
for (i = 0; i < NR_EXTENTS; i++) {
|
||||
int value = 9 - i;
|
||||
|
||||
extent.first = value * 10;
|
||||
extent.lower_first = value * 100;
|
||||
extent.count = 5;
|
||||
|
||||
ret = insert_extent(&map, &extent);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
KUNIT_EXPECT_EQ(test, map.nr_extents, NR_EXTENTS);
|
||||
|
||||
/* Now sort the map to set up reverse mapping */
|
||||
ret = sort_idmaps(&map);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, map.reverse);
|
||||
|
||||
/* Verify the elements are in 'forward' and that sorting is correct */
|
||||
for (i = 0; i < map.nr_extents; i++) {
|
||||
KUNIT_EXPECT_EQ(test, map.forward[i].first, i * 10);
|
||||
KUNIT_EXPECT_EQ(test, map.forward[i].lower_first, i * 100);
|
||||
KUNIT_EXPECT_EQ(test, map.forward[i].count, 5);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, map.reverse[i].first, i * 10);
|
||||
KUNIT_EXPECT_EQ(test, map.reverse[i].lower_first, i * 100);
|
||||
KUNIT_EXPECT_EQ(test, map.reverse[i].count, 5);
|
||||
}
|
||||
|
||||
kfree(map.forward);
|
||||
kfree(map.reverse);
|
||||
}
|
||||
|
||||
static struct kunit_case user_ns_map_test_cases[] = {
|
||||
KUNIT_CASE(user_ns_map_insert),
|
||||
KUNIT_CASE(user_ns_map_insert_extended),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite user_ns_map_test_suite = {
|
||||
.name = "user_ns_map",
|
||||
.test_cases = user_ns_map_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(user_ns_map_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("KUnit test for user namespace map insertion");
|
||||
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
#include <kunit/visibility.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -783,7 +784,8 @@ static bool mappings_overlap(struct uid_gid_map *new_map,
|
|||
* Takes care to allocate a 4K block of memory if the number of mappings exceeds
|
||||
* UID_GID_MAP_MAX_BASE_EXTENTS.
|
||||
*/
|
||||
static int insert_extent(struct uid_gid_map *map, struct uid_gid_extent *extent)
|
||||
VISIBLE_IF_KUNIT int insert_extent(struct uid_gid_map *map,
|
||||
struct uid_gid_extent *extent)
|
||||
{
|
||||
struct uid_gid_extent *dest;
|
||||
|
||||
|
|
@ -806,15 +808,20 @@ static int insert_extent(struct uid_gid_map *map, struct uid_gid_extent *extent)
|
|||
map->reverse = NULL;
|
||||
}
|
||||
|
||||
if (map->nr_extents < UID_GID_MAP_MAX_BASE_EXTENTS)
|
||||
dest = &map->extent[map->nr_extents];
|
||||
/*
|
||||
* nr_extents must be updated before the extent and forward arrays are
|
||||
* accessed, otherwise KSAN will assert an out-of-bounds error.
|
||||
*/
|
||||
map->nr_extents++;
|
||||
if (map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
|
||||
dest = &map->extent[map->nr_extents - 1];
|
||||
else
|
||||
dest = &map->forward[map->nr_extents];
|
||||
dest = &map->forward[map->nr_extents - 1];
|
||||
|
||||
*dest = *extent;
|
||||
map->nr_extents++;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(insert_extent);
|
||||
|
||||
/* cmp function to sort() forward mappings */
|
||||
static int cmp_extents_forward(const void *a, const void *b)
|
||||
|
|
@ -850,7 +857,7 @@ static int cmp_extents_reverse(const void *a, const void *b)
|
|||
* sort_idmaps - Sorts an array of idmap entries.
|
||||
* Can only be called if number of mappings exceeds UID_GID_MAP_MAX_BASE_EXTENTS.
|
||||
*/
|
||||
static int sort_idmaps(struct uid_gid_map *map)
|
||||
VISIBLE_IF_KUNIT int sort_idmaps(struct uid_gid_map *map)
|
||||
{
|
||||
if (map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS)
|
||||
return 0;
|
||||
|
|
@ -871,6 +878,7 @@ static int sort_idmaps(struct uid_gid_map *map)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(sort_idmaps);
|
||||
|
||||
/**
|
||||
* verify_root_map() - check the uid 0 mapping
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user