1 // SPDX-License-Identifier: GPL-2.0-or-later OR copyleft-next-0.3.1
3 * proc sysctl test driver
5 * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
9 * This module provides an interface to the proc sysctl interfaces. This
10 * driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the
11 * system unless explicitly requested by name. You can also build this driver
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 #include <linux/init.h>
18 #include <linux/list.h>
19 #include <linux/module.h>
20 #include <linux/printk.h>
22 #include <linux/miscdevice.h>
23 #include <linux/slab.h>
24 #include <linux/uaccess.h>
25 #include <linux/async.h>
26 #include <linux/delay.h>
27 #include <linux/vmalloc.h>
30 static int i_one_hundred
= 100;
31 static int match_int_ok
= 1;
35 struct ctl_table_header
*test_h_setup_node
;
36 struct ctl_table_header
*test_h_mnt
;
37 struct ctl_table_header
*test_h_mnterror
;
38 struct ctl_table_header
*empty_add
;
39 struct ctl_table_header
*empty
;
40 } sysctl_test_headers
;
42 struct test_sysctl_data
{
49 unsigned int uint_0001
;
53 #define SYSCTL_TEST_BITMAP_SIZE 65536
54 unsigned long *bitmap_0001
;
57 static struct test_sysctl_data test_data
= {
70 .string_0001
= "(none)",
73 /* These are all under /proc/sys/debug/test_sysctl/ */
74 static struct ctl_table test_table
[] = {
76 .procname
= "int_0001",
77 .data
= &test_data
.int_0001
,
78 .maxlen
= sizeof(int),
80 .proc_handler
= proc_dointvec_minmax
,
82 .extra2
= &i_one_hundred
,
85 .procname
= "int_0002",
86 .data
= &test_data
.int_0002
,
87 .maxlen
= sizeof(int),
89 .proc_handler
= proc_dointvec
,
92 .procname
= "int_0003",
93 .data
= &test_data
.int_0003
,
94 .maxlen
= sizeof(test_data
.int_0003
),
96 .proc_handler
= proc_dointvec
,
99 .procname
= "match_int",
100 .data
= &match_int_ok
,
101 .maxlen
= sizeof(match_int_ok
),
103 .proc_handler
= proc_dointvec
,
106 .procname
= "boot_int",
107 .data
= &test_data
.boot_int
,
108 .maxlen
= sizeof(test_data
.boot_int
),
110 .proc_handler
= proc_dointvec
,
111 .extra1
= SYSCTL_ZERO
,
112 .extra2
= SYSCTL_ONE
,
115 .procname
= "uint_0001",
116 .data
= &test_data
.uint_0001
,
117 .maxlen
= sizeof(unsigned int),
119 .proc_handler
= proc_douintvec
,
122 .procname
= "string_0001",
123 .data
= &test_data
.string_0001
,
124 .maxlen
= sizeof(test_data
.string_0001
),
126 .proc_handler
= proc_dostring
,
129 .procname
= "bitmap_0001",
130 .data
= &test_data
.bitmap_0001
,
131 .maxlen
= SYSCTL_TEST_BITMAP_SIZE
,
133 .proc_handler
= proc_do_large_bitmap
,
137 static void test_sysctl_calc_match_int_ok(void)
145 {.defined
= *(int *)SYSCTL_ZERO
, .wanted
= 0},
146 {.defined
= *(int *)SYSCTL_ONE
, .wanted
= 1},
147 {.defined
= *(int *)SYSCTL_TWO
, .wanted
= 2},
148 {.defined
= *(int *)SYSCTL_THREE
, .wanted
= 3},
149 {.defined
= *(int *)SYSCTL_FOUR
, .wanted
= 4},
150 {.defined
= *(int *)SYSCTL_ONE_HUNDRED
, .wanted
= 100},
151 {.defined
= *(int *)SYSCTL_TWO_HUNDRED
, .wanted
= 200},
152 {.defined
= *(int *)SYSCTL_ONE_THOUSAND
, .wanted
= 1000},
153 {.defined
= *(int *)SYSCTL_THREE_THOUSAND
, .wanted
= 3000},
154 {.defined
= *(int *)SYSCTL_INT_MAX
, .wanted
= INT_MAX
},
155 {.defined
= *(int *)SYSCTL_MAXOLDUID
, .wanted
= 65535},
156 {.defined
= *(int *)SYSCTL_NEG_ONE
, .wanted
= -1},
159 for (i
= 0; i
< ARRAY_SIZE(match_int
); i
++)
160 if (match_int
[i
].defined
!= match_int
[i
].wanted
)
164 static int test_sysctl_setup_node_tests(void)
166 test_sysctl_calc_match_int_ok();
167 test_data
.bitmap_0001
= kzalloc(SYSCTL_TEST_BITMAP_SIZE
/8, GFP_KERNEL
);
168 if (!test_data
.bitmap_0001
)
170 sysctl_test_headers
.test_h_setup_node
= register_sysctl("debug/test_sysctl", test_table
);
171 if (!sysctl_test_headers
.test_h_setup_node
) {
172 kfree(test_data
.bitmap_0001
);
179 /* Used to test that unregister actually removes the directory */
180 static struct ctl_table test_table_unregister
[] = {
182 .procname
= "unregister_error",
183 .data
= &test_data
.int_0001
,
184 .maxlen
= sizeof(int),
186 .proc_handler
= proc_dointvec_minmax
,
190 static int test_sysctl_run_unregister_nested(void)
192 struct ctl_table_header
*unregister
;
194 unregister
= register_sysctl("debug/test_sysctl/unregister_error",
195 test_table_unregister
);
199 unregister_sysctl_table(unregister
);
203 static int test_sysctl_run_register_mount_point(void)
205 sysctl_test_headers
.test_h_mnt
206 = register_sysctl_mount_point("debug/test_sysctl/mnt");
207 if (!sysctl_test_headers
.test_h_mnt
)
210 sysctl_test_headers
.test_h_mnterror
211 = register_sysctl("debug/test_sysctl/mnt/mnt_error",
212 test_table_unregister
);
214 * Don't check the result.:
215 * If it fails (expected behavior), return 0.
216 * If successful (missbehavior of register mount point), we want to see
217 * mnt_error when we run the sysctl test script
223 static struct ctl_table test_table_empty
[] = { };
225 static int test_sysctl_run_register_empty(void)
227 /* Tets that an empty dir can be created */
228 sysctl_test_headers
.empty_add
229 = register_sysctl("debug/test_sysctl/empty_add", test_table_empty
);
230 if (!sysctl_test_headers
.empty_add
)
233 /* Test that register on top of an empty dir works */
234 sysctl_test_headers
.empty
235 = register_sysctl("debug/test_sysctl/empty_add/empty", test_table_empty
);
236 if (!sysctl_test_headers
.empty
)
242 static int __init
test_sysctl_init(void)
246 err
= test_sysctl_setup_node_tests();
250 err
= test_sysctl_run_unregister_nested();
254 err
= test_sysctl_run_register_mount_point();
258 err
= test_sysctl_run_register_empty();
263 module_init(test_sysctl_init
);
265 static void __exit
test_sysctl_exit(void)
267 kfree(test_data
.bitmap_0001
);
268 if (sysctl_test_headers
.test_h_setup_node
)
269 unregister_sysctl_table(sysctl_test_headers
.test_h_setup_node
);
270 if (sysctl_test_headers
.test_h_mnt
)
271 unregister_sysctl_table(sysctl_test_headers
.test_h_mnt
);
272 if (sysctl_test_headers
.test_h_mnterror
)
273 unregister_sysctl_table(sysctl_test_headers
.test_h_mnterror
);
274 if (sysctl_test_headers
.empty
)
275 unregister_sysctl_table(sysctl_test_headers
.empty
);
276 if (sysctl_test_headers
.empty_add
)
277 unregister_sysctl_table(sysctl_test_headers
.empty_add
);
280 module_exit(test_sysctl_exit
);
282 MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
283 MODULE_DESCRIPTION("proc sysctl test driver");
284 MODULE_LICENSE("GPL");