~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/test_sysctl.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later OR copyleft-next-0.3.1
  2 /*
  3  * proc sysctl test driver
  4  *
  5  * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org>
  6  */
  7 
  8 /*
  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
 12  * into your kernel.
 13  */
 14 
 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 16 
 17 #include <linux/init.h>
 18 #include <linux/list.h>
 19 #include <linux/module.h>
 20 #include <linux/printk.h>
 21 #include <linux/fs.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>
 28 
 29 static int i_zero;
 30 static int i_one_hundred = 100;
 31 static int match_int_ok = 1;
 32 
 33 
 34 static struct {
 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;
 41 
 42 struct test_sysctl_data {
 43         int int_0001;
 44         int int_0002;
 45         int int_0003[4];
 46 
 47         int boot_int;
 48 
 49         unsigned int uint_0001;
 50 
 51         char string_0001[65];
 52 
 53 #define SYSCTL_TEST_BITMAP_SIZE 65536
 54         unsigned long *bitmap_0001;
 55 };
 56 
 57 static struct test_sysctl_data test_data = {
 58         .int_0001 = 60,
 59         .int_0002 = 1,
 60 
 61         .int_0003[0] = 0,
 62         .int_0003[1] = 1,
 63         .int_0003[2] = 2,
 64         .int_0003[3] = 3,
 65 
 66         .boot_int = 0,
 67 
 68         .uint_0001 = 314,
 69 
 70         .string_0001 = "(none)",
 71 };
 72 
 73 /* These are all under /proc/sys/debug/test_sysctl/ */
 74 static struct ctl_table test_table[] = {
 75         {
 76                 .procname       = "int_0001",
 77                 .data           = &test_data.int_0001,
 78                 .maxlen         = sizeof(int),
 79                 .mode           = 0644,
 80                 .proc_handler   = proc_dointvec_minmax,
 81                 .extra1         = &i_zero,
 82                 .extra2         = &i_one_hundred,
 83         },
 84         {
 85                 .procname       = "int_0002",
 86                 .data           = &test_data.int_0002,
 87                 .maxlen         = sizeof(int),
 88                 .mode           = 0644,
 89                 .proc_handler   = proc_dointvec,
 90         },
 91         {
 92                 .procname       = "int_0003",
 93                 .data           = &test_data.int_0003,
 94                 .maxlen         = sizeof(test_data.int_0003),
 95                 .mode           = 0644,
 96                 .proc_handler   = proc_dointvec,
 97         },
 98         {
 99                 .procname       = "match_int",
100                 .data           = &match_int_ok,
101                 .maxlen         = sizeof(match_int_ok),
102                 .mode           = 0444,
103                 .proc_handler   = proc_dointvec,
104         },
105         {
106                 .procname       = "boot_int",
107                 .data           = &test_data.boot_int,
108                 .maxlen         = sizeof(test_data.boot_int),
109                 .mode           = 0644,
110                 .proc_handler   = proc_dointvec,
111                 .extra1         = SYSCTL_ZERO,
112                 .extra2         = SYSCTL_ONE,
113         },
114         {
115                 .procname       = "uint_0001",
116                 .data           = &test_data.uint_0001,
117                 .maxlen         = sizeof(unsigned int),
118                 .mode           = 0644,
119                 .proc_handler   = proc_douintvec,
120         },
121         {
122                 .procname       = "string_0001",
123                 .data           = &test_data.string_0001,
124                 .maxlen         = sizeof(test_data.string_0001),
125                 .mode           = 0644,
126                 .proc_handler   = proc_dostring,
127         },
128         {
129                 .procname       = "bitmap_0001",
130                 .data           = &test_data.bitmap_0001,
131                 .maxlen         = SYSCTL_TEST_BITMAP_SIZE,
132                 .mode           = 0644,
133                 .proc_handler   = proc_do_large_bitmap,
134         },
135 };
136 
137 static void test_sysctl_calc_match_int_ok(void)
138 {
139         int i;
140 
141         struct {
142                 int defined;
143                 int wanted;
144         } match_int[] = {
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},
157         };
158 
159         for (i = 0; i < ARRAY_SIZE(match_int); i++)
160                 if (match_int[i].defined != match_int[i].wanted)
161                         match_int_ok = 0;
162 }
163 
164 static int test_sysctl_setup_node_tests(void)
165 {
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)
169                 return -ENOMEM;
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);
173                 return -ENOMEM;
174         }
175 
176         return 0;
177 }
178 
179 /* Used to test that unregister actually removes the directory */
180 static struct ctl_table test_table_unregister[] = {
181         {
182                 .procname       = "unregister_error",
183                 .data           = &test_data.int_0001,
184                 .maxlen         = sizeof(int),
185                 .mode           = 0644,
186                 .proc_handler   = proc_dointvec_minmax,
187         },
188 };
189 
190 static int test_sysctl_run_unregister_nested(void)
191 {
192         struct ctl_table_header *unregister;
193 
194         unregister = register_sysctl("debug/test_sysctl/unregister_error",
195                                    test_table_unregister);
196         if (!unregister)
197                 return -ENOMEM;
198 
199         unregister_sysctl_table(unregister);
200         return 0;
201 }
202 
203 static int test_sysctl_run_register_mount_point(void)
204 {
205         sysctl_test_headers.test_h_mnt
206                 = register_sysctl_mount_point("debug/test_sysctl/mnt");
207         if (!sysctl_test_headers.test_h_mnt)
208                 return -ENOMEM;
209 
210         sysctl_test_headers.test_h_mnterror
211                 = register_sysctl("debug/test_sysctl/mnt/mnt_error",
212                                   test_table_unregister);
213         /*
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
218          */
219 
220         return 0;
221 }
222 
223 static struct ctl_table test_table_empty[] = { };
224 
225 static int test_sysctl_run_register_empty(void)
226 {
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)
231                 return -ENOMEM;
232 
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)
237                 return -ENOMEM;
238 
239         return 0;
240 }
241 
242 static int __init test_sysctl_init(void)
243 {
244         int err;
245 
246         err = test_sysctl_setup_node_tests();
247         if (err)
248                 goto out;
249 
250         err = test_sysctl_run_unregister_nested();
251         if (err)
252                 goto out;
253 
254         err = test_sysctl_run_register_mount_point();
255         if (err)
256                 goto out;
257 
258         err = test_sysctl_run_register_empty();
259 
260 out:
261         return err;
262 }
263 module_init(test_sysctl_init);
264 
265 static void __exit test_sysctl_exit(void)
266 {
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);
278 }
279 
280 module_exit(test_sysctl_exit);
281 
282 MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>");
283 MODULE_DESCRIPTION("proc sysctl test driver");
284 MODULE_LICENSE("GPL");
285 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php