1 /* 2 * proc sysctl test driver 3 * 4 * Copyright (C) 2017 Luis R. Rodriguez <mcgrof@kernel.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 2 of the License, or at your option any 9 * later version; or, when distributed separately from the Linux kernel or 10 * when incorporated into other software packages, subject to the following 11 * license: 12 * 13 * This program is free software; you can redistribute it and/or modify it 14 * under the terms of copyleft-next (version 0.3.1 or later) as published 15 * at http://copyleft-next.org/. 16 */ 17 18 /* 19 * This module provides an interface to the proc sysctl interfaces. This 20 * driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the 21 * system unless explicitly requested by name. You can also build this driver 22 * into your kernel. 23 */ 24 25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27 #include <linux/init.h> 28 #include <linux/list.h> 29 #include <linux/module.h> 30 #include <linux/printk.h> 31 #include <linux/fs.h> 32 #include <linux/miscdevice.h> 33 #include <linux/slab.h> 34 #include <linux/uaccess.h> 35 #include <linux/async.h> 36 #include <linux/delay.h> 37 #include <linux/vmalloc.h> 38 39 static int i_zero; 40 static int i_one_hundred = 100; 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 = "boot_int", 100 .data = &test_data.boot_int, 101 .maxlen = sizeof(test_data.boot_int), 102 .mode = 0644, 103 .proc_handler = proc_dointvec, 104 .extra1 = SYSCTL_ZERO, 105 .extra2 = SYSCTL_ONE, 106 }, 107 { 108 .procname = "uint_0001", 109 .data = &test_data.uint_0001, 110 .maxlen = sizeof(unsigned int), 111 .mode = 0644, 112 .proc_handler = proc_douintvec, 113 }, 114 { 115 .procname = "string_0001", 116 .data = &test_data.string_0001, 117 .maxlen = sizeof(test_data.string_0001), 118 .mode = 0644, 119 .proc_handler = proc_dostring, 120 }, 121 { 122 .procname = "bitmap_0001", 123 .data = &test_data.bitmap_0001, 124 .maxlen = SYSCTL_TEST_BITMAP_SIZE, 125 .mode = 0644, 126 .proc_handler = proc_do_large_bitmap, 127 }, 128 { } 129 }; 130 131 static struct ctl_table_header *test_sysctl_header; 132 133 static int __init test_sysctl_init(void) 134 { 135 test_data.bitmap_0001 = kzalloc(SYSCTL_TEST_BITMAP_SIZE/8, GFP_KERNEL); 136 if (!test_data.bitmap_0001) 137 return -ENOMEM; 138 test_sysctl_header = register_sysctl("debug/test_sysctl", test_table); 139 if (!test_sysctl_header) { 140 kfree(test_data.bitmap_0001); 141 return -ENOMEM; 142 } 143 return 0; 144 } 145 module_init(test_sysctl_init); 146 147 static void __exit test_sysctl_exit(void) 148 { 149 kfree(test_data.bitmap_0001); 150 if (test_sysctl_header) 151 unregister_sysctl_table(test_sysctl_header); 152 } 153 154 module_exit(test_sysctl_exit); 155 156 MODULE_AUTHOR("Luis R. Rodriguez <mcgrof@kernel.org>"); 157 MODULE_LICENSE("GPL"); 158