From: Wen Yang <wen.yang@linux.dev>
To: Joel Granados <j.granados@samsung.com>,
Luis Chamberlain <mcgrof@kernel.org>,
Kees Cook <keescook@chromium.org>
Cc: "Eric W . Biederman" <ebiederm@xmission.com>,
"Christian Brauner" <brauner@kernel.org>,
"Thomas Weißschuh" <thomas@t-8ch.de>,
linux-kernel@vger.kernel.org, "Wen Yang" <wen.yang@linux.dev>,
"Dave Young" <dyoung@redhat.com>
Subject: [RESEND PATCH v4 3/5] sysctl: add kunit test code to check the min/max encoding of sysctl table entries
Date: Tue, 8 Oct 2024 23:14:06 +0800 [thread overview]
Message-ID: <20241008151444.12453-3-wen.yang@linux.dev> (raw)
In-Reply-To: <cover.1726907948.git.wen.yang@linux.dev>
Add kunit test code to check the impact of encoding the min/max values
directly in table entries on functions such as proc_rointvec,
proc_rou8vectminmax, proc_rouintvectminmax, and proc_roulongvectminmax,
including basic parsing testing and min/max overflow testing.
Signed-off-by: Wen Yang <wen.yang@linux.dev>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Joel Granados <j.granados@samsung.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Dave Young <dyoung@redhat.com>
Cc: linux-kernel@vger.kernel.org
---
kernel/sysctl-test.c | 581 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 581 insertions(+)
diff --git a/kernel/sysctl-test.c b/kernel/sysctl-test.c
index 3ac98bb7fb82..23439ce85f2d 100644
--- a/kernel/sysctl-test.c
+++ b/kernel/sysctl-test.c
@@ -415,6 +415,575 @@ static void sysctl_test_register_sysctl_sz_invalid_extra_value(
KUNIT_EXPECT_NOT_NULL(test, register_sysctl("foo", table_qux));
}
+static void sysctl_test_api_dointvec_write_with_minmax(
+ struct kunit *test)
+{
+ int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MIN | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_dointvec_minmax,
+ .min = -1,
+ .max = 100,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "10";
+ char input2[] = "-5";
+ char input3[] = "200";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+}
+
+static void sysctl_test_api_dointvec_write_with_min(
+ struct kunit *test)
+{
+ int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MIN,
+ .proc_handler = proc_dointvec_minmax,
+ .min = -1,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "10";
+ char input2[] = "-5";
+ char input3[] = "2147483647";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, 2147483647, *((int *)table.data));
+}
+
+static void sysctl_test_api_dointvec_write_with_max(
+ struct kunit *test)
+{
+ int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_dointvec_minmax,
+ .max = 100,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "10";
+ char input2[] = "2147483647";
+ char input3[] = "-2147483648";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 10, *((int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dointvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, -2147483648, *((int *)table.data));
+}
+
+static void sysctl_test_api_douintvec_write_with_minmax(
+ struct kunit *test)
+{
+ unsigned int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MIN | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_douintvec_minmax,
+ .min = 4,
+ .max = 200,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "100";
+ char input2[] = "3";
+ char input3[] = "1000";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 100, *((unsigned int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 100, *((unsigned int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 100, *((unsigned int *)table.data));
+}
+
+static void sysctl_test_api_douintvec_write_with_min(
+ struct kunit *test)
+{
+ unsigned int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MIN,
+ .proc_handler = proc_douintvec_minmax,
+ .min = 4,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "100";
+ char input2[] = "3";
+ char input3[] = "4294967295";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 100, *((unsigned int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 100, *((unsigned int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, 4294967295, *((unsigned int *)table.data));
+}
+
+static void sysctl_test_api_douintvec_write_with_max(
+ struct kunit *test)
+{
+ unsigned int data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(int),
+ .mode = 0644 | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_douintvec_minmax,
+ .max = 1000,
+ };
+ size_t max_len = 32, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "900";
+ char input2[] = "10000";
+ char input3[] = "0";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 900, *((unsigned int *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 900, *((unsigned int *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_douintvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, 0, *((unsigned int *)table.data));
+}
+
+static void sysctl_test_api_dou8vec_write_with_minmax(
+ struct kunit *test)
+{
+ unsigned char data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned char),
+ .mode = 0644 | SYSCTL_FLAG_MIN | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_dou8vec_minmax,
+ .min = 3,
+ .max = 100,
+ };
+ size_t max_len = 8, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "32";
+ char input2[] = "1";
+ char input3[] = "200";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+}
+
+static void sysctl_test_api_dou8vec_write_with_min(
+ struct kunit *test)
+{
+ unsigned char data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned char),
+ .mode = 0644 | SYSCTL_FLAG_MIN,
+ .proc_handler = proc_dou8vec_minmax,
+ .min = 3,
+ };
+ size_t max_len = 8, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "32";
+ char input2[] = "1";
+ char input3[] = "255";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, 255, *((unsigned char *)table.data));
+}
+
+static void sysctl_test_api_dou8vec_write_with_max(
+ struct kunit *test)
+{
+ unsigned char data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned char),
+ .mode = 0644 | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_dou8vec_minmax,
+ .max = 200,
+ };
+ size_t max_len = 8, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "32";
+ char input2[] = "0";
+ char input3[] = "255";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 32, *((unsigned char *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input2) - 1, len);
+ KUNIT_EXPECT_EQ(test, 0, *((unsigned char *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_dou8vec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 0, *((unsigned char *)table.data));
+}
+
+static void sysctl_test_api_doulongvec_write_with_minmax(
+ struct kunit *test)
+{
+ unsigned long data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644 | SYSCTL_FLAG_MIN | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_doulongvec_minmax,
+ .min = 1000,
+ .max = 3000,
+ };
+ size_t max_len = 64, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "1024";
+ char input2[] = "100";
+ char input3[] = "4096";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 1024, *((unsigned long *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 1024, *((unsigned long *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 1024, *((unsigned long *)table.data));
+}
+
+static void sysctl_test_api_doulongvec_write_with_min(
+ struct kunit *test)
+{
+ unsigned long data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644 | SYSCTL_FLAG_MIN,
+ .proc_handler = proc_doulongvec_minmax,
+ .min = 1000,
+ };
+ size_t max_len = 64, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "1000";
+ char input2[] = "10";
+ char input3[64] = {0};
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 1000, *((unsigned long *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 1000, *((unsigned long *)table.data));
+
+ // test for input3
+ snprintf(input3, sizeof(input3), "%lu", ULONG_MAX);
+ len = strlen(input3);
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, strlen(input3), len);
+ KUNIT_EXPECT_EQ(test, ULONG_MAX, *((unsigned long *)table.data));
+}
+
+static void sysctl_test_api_doulongvec_write_with_max(
+ struct kunit *test)
+{
+ unsigned long data = 0;
+ struct ctl_table table = {
+ .procname = "foo",
+ .data = &data,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644 | SYSCTL_FLAG_MAX,
+ .proc_handler = proc_doulongvec_minmax,
+ .max = 3000,
+ };
+ size_t max_len = 64, len = max_len;
+ loff_t pos = 0;
+ char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
+ char __user *user_buffer = (char __user *)buffer;
+ char input1[] = "1024";
+ char input2[] = "4096";
+ char input3[] = "0";
+
+ // test for input1
+ len = sizeof(input1) - 1;
+ memcpy(buffer, input1, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input1) - 1, len);
+ KUNIT_EXPECT_EQ(test, 1024, *((unsigned long *)table.data));
+
+ // test for input2
+ len = sizeof(input2) - 1;
+ pos = 0;
+ memcpy(buffer, input2, len);
+ KUNIT_EXPECT_EQ(test, -EINVAL, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, 0, pos);
+ KUNIT_EXPECT_EQ(test, 1024, *((unsigned long *)table.data));
+
+ // test for input3
+ len = sizeof(input3) - 1;
+ pos = 0;
+ memcpy(buffer, input3, len);
+ KUNIT_EXPECT_EQ(test, 0, proc_doulongvec_minmax(&table, KUNIT_PROC_WRITE,
+ user_buffer, &len, &pos));
+ KUNIT_EXPECT_EQ(test, sizeof(input3) - 1, len);
+ KUNIT_EXPECT_EQ(test, 0, *((unsigned long *)table.data));
+}
+
static struct kunit_case sysctl_test_cases[] = {
KUNIT_CASE(sysctl_test_api_dointvec_null_tbl_data),
KUNIT_CASE(sysctl_test_api_dointvec_table_maxlen_unset),
@@ -427,6 +996,18 @@ static struct kunit_case sysctl_test_cases[] = {
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_register_sysctl_sz_invalid_extra_value),
+ KUNIT_CASE(sysctl_test_api_dointvec_write_with_minmax),
+ KUNIT_CASE(sysctl_test_api_dointvec_write_with_min),
+ KUNIT_CASE(sysctl_test_api_dointvec_write_with_max),
+ KUNIT_CASE(sysctl_test_api_douintvec_write_with_minmax),
+ KUNIT_CASE(sysctl_test_api_douintvec_write_with_min),
+ KUNIT_CASE(sysctl_test_api_douintvec_write_with_max),
+ KUNIT_CASE(sysctl_test_api_dou8vec_write_with_minmax),
+ KUNIT_CASE(sysctl_test_api_dou8vec_write_with_min),
+ KUNIT_CASE(sysctl_test_api_dou8vec_write_with_max),
+ KUNIT_CASE(sysctl_test_api_doulongvec_write_with_minmax),
+ KUNIT_CASE(sysctl_test_api_doulongvec_write_with_min),
+ KUNIT_CASE(sysctl_test_api_doulongvec_write_with_max),
{}
};
--
2.25.1
next prev parent reply other threads:[~2024-10-08 15:15 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-08 15:14 [RESEND PATCH v4 0/5] sysctl: encode the min/max values directly in the table entry Wen Yang
2024-10-08 15:14 ` [RESEND PATCH v4 1/5] sysctl: add helper functions to extract table->extra1/extra2 Wen Yang
2024-10-08 15:14 ` [RESEND PATCH v4 2/5] sysctl: support encoding values directly in the table entry Wen Yang
2024-10-08 15:14 ` Wen Yang [this message]
2024-10-08 15:14 ` [RESEND PATCH v4 4/5] sysctl: delete mmap_rnd_bits_{min/max} and mmap_rnd_compat_bits_{min/max} to save 16 bytes Wen Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241008151444.12453-3-wen.yang@linux.dev \
--to=wen.yang@linux.dev \
--cc=brauner@kernel.org \
--cc=dyoung@redhat.com \
--cc=ebiederm@xmission.com \
--cc=j.granados@samsung.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=thomas@t-8ch.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.