From: Wen Yang Add KUnit cases for priv: a standard handler must ignore it, registration must reject priv with a standard handler, and a re-registered table must keep both the value pointer and the context. Move the debug module's dynamic-value entry to the same shape so it exercises data-as-value and priv-as-context. Signed-off-by: Wen Yang --- kernel/sysctl-test.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ lib/test_sysctl.c | 9 +++--- 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c index dd658ca18793..f9efc146f219 100644 --- a/kernel/sysctl-test.c +++ b/kernel/sysctl-test.c @@ -699,10 +699,56 @@ static int sysctl_test_entry_write(struct kunit *test, const struct ctl_table *t * entry must not change what is stored, so a stray context pointer cannot * redirect a write to the wrong address. */ +static void sysctl_test_priv_standard_handler(struct kunit *test) +{ + int value = 0; + struct sysctl_test_demo_ctx { + int marker; + } ctx = { .marker = -1 }; + const struct ctl_table table = { + .procname = "standard", + .data = &value, + .maxlen = sizeof(value), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .min = 0, + .max = 100, + .priv = &ctx, + }; + + sysctl_test_entry_roundtrip(test, &table, "42"); + KUNIT_EXPECT_EQ(test, value, 42); + KUNIT_EXPECT_EQ(test, ctx.marker, -1); + KUNIT_EXPECT_PTR_EQ(test, table.data, &value); + KUNIT_EXPECT_PTR_EQ(test, table.priv, &ctx); +} + /* * Registration refuses priv on a standard handler: the context would be * silently ignored, which is always a configuration mistake. */ +static void sysctl_test_priv_standard_handler_reject(struct kunit *test) +{ + int value = 0; + struct sysctl_test_demo_ctx { + int marker; + } ctx = { .marker = -1 }; + const struct ctl_table table = { + .procname = "invalid_priv", + .data = &value, + .maxlen = sizeof(value), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .min = 0, + .max = 100, + .priv = &ctx, + }; + + KUNIT_EXPECT_PTR_EQ(test, NULL, + register_sysctl_sz("sysctl_kunit_priv_invalid", + &table, 1)); +} + /* * A dynamic range wrapper reads its related limit through priv on each call @@ -1159,6 +1205,29 @@ static void sysctl_test_context_registration_lifecycle(struct kunit *test) * at the caller-owned objects; the handler resolves storage through data and * context through priv on every call. */ +static void sysctl_test_priv_registration_lifecycle(struct kunit *test) +{ + struct sysctl_test_lifecycle ctx = {}; + struct ctl_table table = SYSCTL_TEST_CTX(ctx.value, "priv_lifecycle", + 0644, + sysctl_test_lifecycle_handler, ctx); + struct ctl_table_header *header; + + header = register_sysctl_sz("sysctl_kunit_priv", &table, 1); + KUNIT_ASSERT_NOT_NULL(test, header); + kunit_add_action(test, sysctl_test_unregister_table, header); + + sysctl_test_entry_roundtrip(test, &table, "23"); + KUNIT_EXPECT_EQ(test, ctx.value, 23); + KUNIT_EXPECT_PTR_EQ(test, table.priv, &ctx); + KUNIT_EXPECT_PTR_EQ(test, table.data, &ctx.value); + + kunit_release_action(test, sysctl_test_unregister_table, header); + sysctl_test_entry_roundtrip(test, &table, "17"); + KUNIT_EXPECT_EQ(test, ctx.value, 17); + KUNIT_EXPECT_PTR_EQ(test, table.priv, &ctx); +} + /* Registration rejects numeric bounds that cannot represent the element type. */ static void sysctl_test_context_registration_reject(struct kunit *test) { @@ -1381,6 +1450,9 @@ static struct kunit_case sysctl_test_cases[] = { KUNIT_CASE(sysctl_test_dointvec_write_happy_single_negative), KUNIT_CASE(sysctl_test_api_dointvec_write_single_less_int_min), KUNIT_CASE(sysctl_test_api_dointvec_write_single_greater_int_max), + KUNIT_CASE(sysctl_test_priv_standard_handler), + KUNIT_CASE(sysctl_test_priv_standard_handler_reject), + KUNIT_CASE(sysctl_test_priv_registration_lifecycle), KUNIT_CASE(sysctl_test_entry_null_handler), KUNIT_CASE(sysctl_test_entry_explicit_handler), KUNIT_CASE(sysctl_test_entry_int_limits), diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c index 1411896fdbd0..64c82fd53975 100644 --- a/lib/test_sysctl.c +++ b/lib/test_sysctl.c @@ -97,7 +97,7 @@ static struct test_sysctl_data test_data = { static int test_sysctl_dynamic_value(const struct ctl_table *table, int dir, void *buffer, size_t *lenp, loff_t *ppos) { - struct test_sysctl_range_context *context = table->data; + struct test_sysctl_range_context *context = table->priv; struct ctl_table resolved = *table; resolved.data = &context->value; @@ -215,12 +215,11 @@ static const struct ctl_table test_table[] = { }, { .procname = "dynamic_value", - .data = &test_data.dynamic, - .maxlen = sizeof(test_data.dynamic), + .data = &test_data.dynamic.value, + .maxlen = sizeof(test_data.dynamic.value), .mode = 0644, .proc_handler = test_sysctl_dynamic_value, - .min = 0, - .max = ULONG_MAX, + .priv = &test_data.dynamic, }, { .procname = "int_zero", -- 2.25.1