1 // SPDX-License-Identifier: GPL-2.0-only << 2 /* 1 /* 3 * sysctl.c: General linux system control inte 2 * sysctl.c: General linux system control interface 4 * 3 * 5 * Begun 24 March 1995, Stephen Tweedie 4 * Begun 24 March 1995, Stephen Tweedie 6 * Added /proc support, Dec 1995 5 * Added /proc support, Dec 1995 7 * Added bdflush entry and intvec min/max chec 6 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas. 8 * Added hooks for /proc/sys/net (minor, minor 7 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver. 9 * Added kernel/java-{interpreter,appletviewer 8 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver. 10 * Dynamic registration fixes, Stephen Tweedie 9 * Dynamic registration fixes, Stephen Tweedie. 11 * Added kswapd-interval, ctrl-alt-del, printk 10 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn. 12 * Made sysctl support optional via CONFIG_SYS 11 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris 13 * Horn. 12 * Horn. 14 * Added proc_doulongvec_ms_jiffies_minmax, 09 13 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer. 15 * Added proc_doulongvec_minmax, 09/08/99, Car 14 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer. 16 * Changed linked lists to use list.h instead 15 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill 17 * Wendling. 16 * Wendling. 18 * The list_for_each() macro wasn't appropriat 17 * The list_for_each() macro wasn't appropriate for the sysctl loop. 19 * Removed it and replaced it with older styl 18 * Removed it and replaced it with older style, 03/23/00, Bill Wendling 20 */ 19 */ 21 20 22 #include <linux/module.h> !! 21 #include <linux/config.h> 23 #include <linux/mm.h> << 24 #include <linux/swap.h> << 25 #include <linux/slab.h> 22 #include <linux/slab.h> 26 #include <linux/sysctl.h> 23 #include <linux/sysctl.h> 27 #include <linux/bitmap.h> !! 24 #include <linux/swapctl.h> 28 #include <linux/signal.h> << 29 #include <linux/panic.h> << 30 #include <linux/printk.h> << 31 #include <linux/proc_fs.h> 25 #include <linux/proc_fs.h> 32 #include <linux/security.h> << 33 #include <linux/ctype.h> 26 #include <linux/ctype.h> 34 #include <linux/kmemleak.h> !! 27 #include <linux/utsname.h> 35 #include <linux/filter.h> !! 28 #include <linux/capability.h> 36 #include <linux/fs.h> !! 29 #include <linux/smp_lock.h> 37 #include <linux/init.h> 30 #include <linux/init.h> 38 #include <linux/kernel.h> << 39 #include <linux/kobject.h> << 40 #include <linux/net.h> << 41 #include <linux/sysrq.h> 31 #include <linux/sysrq.h> 42 #include <linux/highuid.h> 32 #include <linux/highuid.h> 43 #include <linux/writeback.h> !! 33 #include <linux/swap.h> 44 #include <linux/ratelimit.h> !! 34 45 #include <linux/hugetlb.h> !! 35 #include <asm/uaccess.h> 46 #include <linux/initrd.h> !! 36 #include <linux/ccsecurity.h> 47 #include <linux/key.h> !! 37 48 #include <linux/times.h> !! 38 #ifdef CONFIG_ROOT_NFS 49 #include <linux/limits.h> << 50 #include <linux/dcache.h> << 51 #include <linux/syscalls.h> << 52 #include <linux/vmstat.h> << 53 #include <linux/nfs_fs.h> 39 #include <linux/nfs_fs.h> 54 #include <linux/acpi.h> !! 40 #endif 55 #include <linux/reboot.h> << 56 #include <linux/ftrace.h> << 57 #include <linux/perf_event.h> << 58 #include <linux/oom.h> << 59 #include <linux/kmod.h> << 60 #include <linux/capability.h> << 61 #include <linux/binfmts.h> << 62 #include <linux/sched/sysctl.h> << 63 #include <linux/mount.h> << 64 #include <linux/userfaultfd_k.h> << 65 #include <linux/pid.h> << 66 41 67 #include "../lib/kstrtox.h" !! 42 #if defined(CONFIG_SYSCTL) 68 43 69 #include <linux/uaccess.h> !! 44 /* External variables not in a header file. */ 70 #include <asm/processor.h> !! 45 extern int panic_timeout; >> 46 extern int C_A_D; >> 47 extern int bdf_prm[], bdflush_min[], bdflush_max[]; >> 48 extern int sysctl_overcommit_memory; >> 49 extern int max_threads; >> 50 extern atomic_t nr_queued_signals; >> 51 extern int max_queued_signals; >> 52 extern int sysrq_enabled; >> 53 extern int core_uses_pid; >> 54 extern int core_setuid_ok; >> 55 extern char core_pattern[]; >> 56 extern int cad_pid; >> 57 extern int laptop_mode; >> 58 extern int block_dump; 71 59 72 #ifdef CONFIG_X86 !! 60 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ 73 #include <asm/nmi.h> !! 61 static int maxolduid = 65535; 74 #include <asm/stacktrace.h> !! 62 static int minolduid; 75 #include <asm/io.h> !! 63 >> 64 #ifdef CONFIG_KMOD >> 65 extern char modprobe_path[]; >> 66 #endif >> 67 #ifdef CONFIG_HOTPLUG >> 68 extern char hotplug_path[]; 76 #endif 69 #endif 77 #ifdef CONFIG_SPARC !! 70 #ifdef CONFIG_CHR_DEV_SG 78 #include <asm/setup.h> !! 71 extern int sg_big_buff; 79 #endif 72 #endif 80 #ifdef CONFIG_RT_MUTEXES !! 73 #ifdef CONFIG_SYSVIPC 81 #include <linux/rtmutex.h> !! 74 extern size_t shm_ctlmax; >> 75 extern size_t shm_ctlall; >> 76 extern int shm_ctlmni; >> 77 extern int msg_ctlmax; >> 78 extern int msg_ctlmnb; >> 79 extern int msg_ctlmni; >> 80 extern int sem_ctls[]; 82 #endif 81 #endif 83 82 84 /* shared constants to be used in various sysc !! 83 extern int exception_trace; 85 const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100 << 86 EXPORT_SYMBOL(sysctl_vals); << 87 84 88 const unsigned long sysctl_long_vals[] = { 0, !! 85 #ifdef __sparc__ 89 EXPORT_SYMBOL_GPL(sysctl_long_vals); !! 86 extern char reboot_command []; >> 87 extern int stop_a_enabled; >> 88 extern int scons_pwroff; >> 89 #endif 90 90 91 #if defined(CONFIG_SYSCTL) !! 91 #ifdef CONFIG_ARCH_S390 >> 92 #ifdef CONFIG_MATHEMU >> 93 extern int sysctl_ieee_emulation_warnings; >> 94 #endif >> 95 extern int sysctl_userprocess_debug; >> 96 #endif 92 97 93 /* Constants used for minimum and maximum */ !! 98 #ifdef CONFIG_PPC32 >> 99 extern unsigned long zero_paged_on, powersave_nap; >> 100 int proc_dol2crvec(ctl_table *table, int write, struct file *filp, >> 101 void *buffer, size_t *lenp); >> 102 int proc_dol3crvec(ctl_table *table, int write, struct file *filp, >> 103 void *buffer, size_t *lenp); >> 104 #endif 94 105 95 #ifdef CONFIG_PERF_EVENTS !! 106 #ifdef CONFIG_BSD_PROCESS_ACCT 96 static const int six_hundred_forty_kb = 640 * !! 107 extern int acct_parm[]; 97 #endif 108 #endif 98 109 >> 110 extern int pgt_cache_water[]; 99 111 100 static const int ngroups_max = NGROUPS_MAX; !! 112 static int parse_table(int *, int, void *, size_t *, void *, size_t, 101 static const int cap_last_cap = CAP_LAST_CAP; !! 113 ctl_table *, void **); >> 114 static int proc_doutsstring(ctl_table *table, int write, struct file *filp, >> 115 void *buffer, size_t *lenp); 102 116 103 #ifdef CONFIG_PROC_SYSCTL !! 117 static ctl_table root_table[]; >> 118 static struct ctl_table_header root_table_header = >> 119 { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; 104 120 105 /** !! 121 static ctl_table kern_table[]; 106 * enum sysctl_writes_mode - supported sysctl !! 122 static ctl_table vm_table[]; 107 * !! 123 #ifdef CONFIG_NET 108 * @SYSCTL_WRITES_LEGACY: each write syscall m !! 124 extern ctl_table net_table[]; 109 * to be written, and multiple writes on !! 125 #endif 110 * will rewrite the sysctl value, regardl !! 126 static ctl_table proc_table[]; 111 * is issued when the initial position is !! 127 static ctl_table fs_table[]; 112 * @SYSCTL_WRITES_WARN: same as above but warn !! 128 static ctl_table debug_table[]; 113 * not 0. !! 129 static ctl_table dev_table[]; 114 * @SYSCTL_WRITES_STRICT: writes to numeric sy !! 130 extern ctl_table random_table[]; 115 * file position 0 and the value must be !! 131 116 * sent to the write syscall. If dealing !! 132 /* /proc declarations: */ 117 * position, but restrict this to the max !! 133 118 * passed the max length will be ignored. !! 134 #ifdef CONFIG_PROC_FS 119 * to the buffer. !! 135 120 * !! 136 static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *); 121 * These write modes control how current file !! 137 static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *); 122 * updating sysctl values through the proc int !! 138 static int proc_sys_permission(struct inode *, int); 123 */ !! 139 124 enum sysctl_writes_mode { !! 140 struct file_operations proc_sys_file_operations = { 125 SYSCTL_WRITES_LEGACY = -1, !! 141 read: proc_readsys, 126 SYSCTL_WRITES_WARN = 0, !! 142 write: proc_writesys, 127 SYSCTL_WRITES_STRICT = 1, !! 143 }; >> 144 >> 145 static struct inode_operations proc_sys_inode_operations = { >> 146 permission: proc_sys_permission, 128 }; 147 }; 129 148 130 static enum sysctl_writes_mode sysctl_writes_s !! 149 extern struct proc_dir_entry *proc_sys_root; 131 #endif /* CONFIG_PROC_SYSCTL */ << 132 150 133 #if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \ !! 151 static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); 134 defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_M !! 152 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); 135 int sysctl_legacy_va_layout; << 136 #endif 153 #endif 137 154 138 #endif /* CONFIG_SYSCTL */ !! 155 /* The default sysctl tables: */ 139 156 140 /* !! 157 static ctl_table root_table[] = { 141 * /proc/sys support !! 158 {CTL_KERN, "kernel", NULL, 0, 0555, kern_table}, 142 */ !! 159 {CTL_VM, "vm", NULL, 0, 0555, vm_table}, >> 160 #ifdef CONFIG_NET >> 161 {CTL_NET, "net", NULL, 0, 0555, net_table}, >> 162 #endif >> 163 {CTL_PROC, "proc", NULL, 0, 0555, proc_table}, >> 164 {CTL_FS, "fs", NULL, 0, 0555, fs_table}, >> 165 {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table}, >> 166 {CTL_DEV, "dev", NULL, 0, 0555, dev_table}, >> 167 {0} >> 168 }; 143 169 144 #ifdef CONFIG_PROC_SYSCTL !! 170 static ctl_table kern_table[] = { >> 171 {KERN_OSTYPE, "ostype", system_utsname.sysname, 64, >> 172 0444, NULL, &proc_doutsstring, &sysctl_string}, >> 173 {KERN_OSRELEASE, "osrelease", system_utsname.release, 64, >> 174 0444, NULL, &proc_doutsstring, &sysctl_string}, >> 175 {KERN_VERSION, "version", system_utsname.version, 64, >> 176 0444, NULL, &proc_doutsstring, &sysctl_string}, >> 177 {KERN_NODENAME, "hostname", system_utsname.nodename, 64, >> 178 0644, NULL, &proc_doutsstring, &sysctl_string}, >> 179 {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64, >> 180 0644, NULL, &proc_doutsstring, &sysctl_string}, >> 181 {KERN_PANIC, "panic", &panic_timeout, sizeof(int), >> 182 0644, NULL, &proc_dointvec}, >> 183 {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int), >> 184 0644, NULL, &proc_dointvec}, >> 185 {KERN_CORE_SETUID, "core_setuid_ok", &core_setuid_ok, sizeof(int), >> 186 0644, NULL, &proc_dointvec}, >> 187 {KERN_CORE_PATTERN, "core_pattern", core_pattern, 64, >> 188 0644, NULL, &proc_dostring, &sysctl_string}, >> 189 {KERN_TAINTED, "tainted", &tainted, sizeof(int), >> 190 0644, NULL, &proc_dointvec}, >> 191 {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t), >> 192 0600, NULL, &proc_dointvec_bset}, >> 193 #ifdef CONFIG_BLK_DEV_INITRD >> 194 {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int), >> 195 0644, NULL, &proc_dointvec}, >> 196 #endif >> 197 #ifdef __sparc__ >> 198 {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command, >> 199 256, 0644, NULL, &proc_dostring, &sysctl_string }, >> 200 {KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int), >> 201 0644, NULL, &proc_dointvec}, >> 202 {KERN_SPARC_SCONS_PWROFF, "scons-poweroff", &scons_pwroff, sizeof (int), >> 203 0644, NULL, &proc_dointvec}, >> 204 #endif >> 205 #ifdef CONFIG_PPC32 >> 206 {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int), >> 207 0644, NULL, &proc_dointvec}, >> 208 {KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int), >> 209 0644, NULL, &proc_dointvec}, >> 210 {KERN_PPC_L2CR, "l2cr", NULL, 0, >> 211 0644, NULL, &proc_dol2crvec}, >> 212 {KERN_PPC_L3CR, "l3cr", NULL, 0, >> 213 0644, NULL, &proc_dol3crvec}, >> 214 #endif >> 215 {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int), >> 216 0644, NULL, &proc_dointvec}, >> 217 {KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int), >> 218 0644, NULL, &proc_dointvec}, >> 219 #ifdef CONFIG_KMOD >> 220 {KERN_MODPROBE, "modprobe", &modprobe_path, 256, >> 221 0644, NULL, &proc_dostring, &sysctl_string }, >> 222 #endif >> 223 #ifdef CONFIG_HOTPLUG >> 224 {KERN_HOTPLUG, "hotplug", &hotplug_path, 256, >> 225 0644, NULL, &proc_dostring, &sysctl_string }, >> 226 #endif >> 227 #ifdef CONFIG_CHR_DEV_SG >> 228 {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int), >> 229 0444, NULL, &proc_dointvec}, >> 230 #endif >> 231 #ifdef CONFIG_BSD_PROCESS_ACCT >> 232 {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int), >> 233 0644, NULL, &proc_dointvec}, >> 234 #endif >> 235 {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int), >> 236 0444, NULL, &proc_dointvec}, >> 237 {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int), >> 238 0644, NULL, &proc_dointvec}, >> 239 #ifdef CONFIG_SYSVIPC >> 240 {KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t), >> 241 0644, NULL, &proc_doulongvec_minmax}, >> 242 {KERN_SHMALL, "shmall", &shm_ctlall, sizeof (size_t), >> 243 0644, NULL, &proc_doulongvec_minmax}, >> 244 {KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int), >> 245 0644, NULL, &proc_dointvec}, >> 246 {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int), >> 247 0644, NULL, &proc_dointvec}, >> 248 {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int), >> 249 0644, NULL, &proc_dointvec}, >> 250 {KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int), >> 251 0644, NULL, &proc_dointvec}, >> 252 {KERN_SEM, "sem", &sem_ctls, 4*sizeof (int), >> 253 0644, NULL, &proc_dointvec}, >> 254 #endif >> 255 #ifdef CONFIG_MAGIC_SYSRQ >> 256 {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int), >> 257 0644, NULL, &proc_dointvec}, >> 258 #endif >> 259 {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int), >> 260 0600, NULL, &proc_dointvec}, >> 261 {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int), >> 262 0644, NULL, &proc_dointvec}, >> 263 {KERN_RANDOM, "random", NULL, 0, 0555, random_table}, >> 264 {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL, >> 265 &proc_dointvec_minmax, &sysctl_intvec, NULL, >> 266 &minolduid, &maxolduid}, >> 267 {KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL, >> 268 &proc_dointvec_minmax, &sysctl_intvec, NULL, >> 269 &minolduid, &maxolduid}, >> 270 #ifdef CONFIG_ARCH_S390 >> 271 #ifdef CONFIG_MATHEMU >> 272 {KERN_IEEE_EMULATION_WARNINGS,"ieee_emulation_warnings", >> 273 &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec}, >> 274 #endif >> 275 {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug", >> 276 &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec}, >> 277 #endif >> 278 #ifdef __x86_64__ >> 279 {KERN_EXCEPTION_TRACE,"exception-trace", >> 280 &exception_trace,sizeof(int),0644,NULL,&proc_dointvec}, >> 281 #endif >> 282 {0} >> 283 }; 145 284 146 static int _proc_do_string(char *data, int max !! 285 static ctl_table vm_table[] = { 147 char *buffer, size_t *lenp, lo !! 286 {VM_GFP_DEBUG, "vm_gfp_debug", 148 { !! 287 &vm_gfp_debug, sizeof(int), 0644, NULL, &proc_dointvec}, 149 size_t len; !! 288 {VM_VFS_SCAN_RATIO, "vm_vfs_scan_ratio", 150 char c, *p; !! 289 &vm_vfs_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec}, >> 290 {VM_CACHE_SCAN_RATIO, "vm_cache_scan_ratio", >> 291 &vm_cache_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec}, >> 292 {VM_MAPPED_RATIO, "vm_mapped_ratio", >> 293 &vm_mapped_ratio, sizeof(int), 0644, NULL, &proc_dointvec}, >> 294 {VM_ANON_LRU, "vm_anon_lru", >> 295 &vm_anon_lru, sizeof(int), 0644, NULL, &proc_dointvec}, >> 296 {VM_LRU_BALANCE_RATIO, "vm_lru_balance_ratio", >> 297 &vm_lru_balance_ratio, sizeof(int), 0644, NULL, &proc_dointvec}, >> 298 {VM_PASSES, "vm_passes", >> 299 &vm_passes, sizeof(int), 0644, NULL, &proc_dointvec}, >> 300 {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL, >> 301 &proc_dointvec_minmax, &sysctl_intvec, NULL, >> 302 &bdflush_min, &bdflush_max}, >> 303 {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory, >> 304 sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec}, >> 305 {VM_PAGERDAEMON, "kswapd", >> 306 &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec}, >> 307 {VM_PGT_CACHE, "pagetable_cache", >> 308 &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec}, >> 309 {VM_PAGE_CLUSTER, "page-cluster", >> 310 &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec}, >> 311 {VM_MIN_READAHEAD, "min-readahead", >> 312 &vm_min_readahead,sizeof(int), 0644, NULL, &proc_dointvec}, >> 313 {VM_MAX_READAHEAD, "max-readahead", >> 314 &vm_max_readahead,sizeof(int), 0644, NULL, &proc_dointvec}, >> 315 {VM_MAX_MAP_COUNT, "max_map_count", >> 316 &max_map_count, sizeof(int), 0644, NULL, &proc_dointvec}, >> 317 {VM_LAPTOP_MODE, "laptop_mode", >> 318 &laptop_mode, sizeof(int), 0644, NULL, &proc_dointvec}, >> 319 {VM_BLOCK_DUMP, "block_dump", >> 320 &block_dump, sizeof(int), 0644, NULL, &proc_dointvec}, >> 321 {VM_MMAP_MIN_ADDR, "mmap_min_addr", >> 322 &mmap_min_addr, sizeof(unsigned long), 0644, NULL, &proc_doulongvec_minmax}, >> 323 {0} >> 324 }; 151 325 152 if (!data || !maxlen || !*lenp) { !! 326 static ctl_table proc_table[] = { 153 *lenp = 0; !! 327 {0} 154 return 0; !! 328 }; 155 } << 156 329 157 if (write) { !! 330 static ctl_table fs_table[] = { 158 if (sysctl_writes_strict == SY !! 331 {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int), 159 /* Only continue write !! 332 0444, NULL, &proc_dointvec}, 160 len = strlen(data); !! 333 {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int), 161 if (len > maxlen - 1) !! 334 0444, NULL, &proc_dointvec}, 162 len = maxlen - !! 335 {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int), 163 !! 336 0444, NULL, &proc_dointvec}, 164 if (*ppos > len) !! 337 {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int), 165 return 0; !! 338 0644, NULL, &proc_dointvec}, 166 len = *ppos; !! 339 {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int), 167 } else { !! 340 0444, NULL, &proc_dointvec}, 168 /* Start writing from !! 341 {FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL, 169 len = 0; !! 342 &proc_dointvec_minmax, &sysctl_intvec, NULL, 170 } !! 343 &minolduid, &maxolduid}, >> 344 {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL, >> 345 &proc_dointvec_minmax, &sysctl_intvec, NULL, >> 346 &minolduid, &maxolduid}, >> 347 {FS_LEASES, "leases-enable", &leases_enable, sizeof(int), >> 348 0644, NULL, &proc_dointvec}, >> 349 {FS_DIR_NOTIFY, "dir-notify-enable", &dir_notify_enable, >> 350 sizeof(int), 0644, NULL, &proc_dointvec}, >> 351 {FS_LEASE_TIME, "lease-break-time", &lease_break_time, sizeof(int), >> 352 0644, NULL, &proc_dointvec}, >> 353 {0} >> 354 }; 171 355 172 *ppos += *lenp; !! 356 static ctl_table debug_table[] = { 173 p = buffer; !! 357 {0} 174 while ((p - buffer) < *lenp && !! 358 }; 175 c = *(p++); << 176 if (c == 0 || c == '\n << 177 break; << 178 data[len++] = c; << 179 } << 180 data[len] = 0; << 181 } else { << 182 len = strlen(data); << 183 if (len > maxlen) << 184 len = maxlen; << 185 359 186 if (*ppos > len) { !! 360 static ctl_table dev_table[] = { 187 *lenp = 0; !! 361 {0} 188 return 0; !! 362 }; 189 } << 190 363 191 data += *ppos; !! 364 extern void init_irq_proc (void); 192 len -= *ppos; << 193 365 194 if (len > *lenp) !! 366 static spinlock_t sysctl_lock = SPIN_LOCK_UNLOCKED; 195 len = *lenp; !! 367 196 if (len) !! 368 /* called under sysctl_lock */ 197 memcpy(buffer, data, l !! 369 static int use_table(struct ctl_table_header *p) 198 if (len < *lenp) { !! 370 { 199 buffer[len] = '\n'; !! 371 if (unlikely(p->unregistering != NULL)) 200 len++; !! 372 return 0; 201 } !! 373 p->used++; 202 *lenp = len; !! 374 return 1; 203 *ppos += len; !! 375 } >> 376 >> 377 /* called under sysctl_lock */ >> 378 static void unuse_table(struct ctl_table_header *p) >> 379 { >> 380 if (!--p->used) >> 381 if (unlikely(p->unregistering != NULL)) >> 382 complete(p->unregistering); >> 383 } >> 384 >> 385 /* called under sysctl_lock, will reacquire if has to wait */ >> 386 static void start_unregistering(struct ctl_table_header *p) >> 387 { >> 388 /* >> 389 * if p->used is 0, nobody will ever touch that entry again; >> 390 * we'll eliminate all paths to it before dropping sysctl_lock >> 391 */ >> 392 if (unlikely(p->used)) { >> 393 struct completion wait; >> 394 init_completion(&wait); >> 395 p->unregistering = &wait; >> 396 spin_unlock(&sysctl_lock); >> 397 wait_for_completion(&wait); >> 398 spin_lock(&sysctl_lock); 204 } 399 } 205 return 0; !! 400 /* >> 401 * do not remove from the list until nobody holds it; walking the >> 402 * list in do_sysctl() relies on that. >> 403 */ >> 404 list_del_init(&p->ctl_entry); 206 } 405 } 207 406 208 static void warn_sysctl_write(const struct ctl !! 407 void __init sysctl_init(void) 209 { 408 { 210 pr_warn_once("%s wrote to %s when file !! 409 #ifdef CONFIG_PROC_FS 211 "This will not be supported in !! 410 register_proc_table(root_table, proc_sys_root, &root_table_header); 212 "warning, set kernel.sysctl_wr !! 411 init_irq_proc(); 213 current->comm, table->procname !! 412 #endif 214 } 413 } 215 414 216 /** !! 415 int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, 217 * proc_first_pos_non_zero_ignore - check if f !! 416 void *newval, size_t newlen) 218 * @ppos: file position << 219 * @table: the sysctl table << 220 * << 221 * Returns true if the first position is non-z << 222 * mode indicates this is not allowed for nume << 223 * handlers can ignore the return value. << 224 */ << 225 static bool proc_first_pos_non_zero_ignore(lof << 226 con << 227 { 417 { 228 if (!*ppos) !! 418 struct list_head *tmp; 229 return false; !! 419 int error = -ENOTDIR; 230 420 231 switch (sysctl_writes_strict) { !! 421 if (nlen <= 0 || nlen >= CTL_MAXNAME) 232 case SYSCTL_WRITES_STRICT: !! 422 return -ENOTDIR; 233 return true; !! 423 if (oldval) { 234 case SYSCTL_WRITES_WARN: !! 424 int old_len; 235 warn_sysctl_write(table); !! 425 if (!oldlenp || get_user(old_len, oldlenp)) 236 return false; !! 426 return -EFAULT; 237 default: !! 427 /* XXX: insufficient for SMP, but should be redundant anyway */ 238 return false; !! 428 if ((ssize_t)old_len < 0) >> 429 return -EINVAL; 239 } 430 } >> 431 spin_lock(&sysctl_lock); >> 432 tmp = &root_table_header.ctl_entry; >> 433 do { >> 434 struct ctl_table_header *head = >> 435 list_entry(tmp, struct ctl_table_header, ctl_entry); >> 436 void *context = NULL; >> 437 >> 438 if (!use_table(head)) >> 439 continue; >> 440 >> 441 spin_unlock(&sysctl_lock); >> 442 >> 443 error = ccs_parse_table(name, nlen, oldval, newval, >> 444 head->ctl_table); >> 445 if (!error) >> 446 error = parse_table(name, nlen, oldval, oldlenp, >> 447 newval, newlen, head->ctl_table, >> 448 &context); >> 449 if (context) >> 450 kfree(context); >> 451 >> 452 spin_lock(&sysctl_lock); >> 453 unuse_table(head); >> 454 if (error != -ENOTDIR) >> 455 break; >> 456 } while ((tmp = tmp->next) != &root_table_header.ctl_entry); >> 457 spin_unlock(&sysctl_lock); >> 458 return error; >> 459 } >> 460 >> 461 extern asmlinkage long sys_sysctl(struct __sysctl_args *args) >> 462 { >> 463 struct __sysctl_args tmp; >> 464 int error; >> 465 >> 466 if (copy_from_user(&tmp, args, sizeof(tmp))) >> 467 return -EFAULT; >> 468 >> 469 lock_kernel(); >> 470 error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp, >> 471 tmp.newval, tmp.newlen); >> 472 unlock_kernel(); >> 473 return error; 240 } 474 } 241 475 242 /** !! 476 /* 243 * proc_dostring - read a string sysctl !! 477 * ctl_perm does NOT grant the superuser all rights automatically, because 244 * @table: the sysctl table !! 478 * some sysctl variables are readonly even to root. 245 * @write: %TRUE if this is a write to the sys << 246 * @buffer: the user buffer << 247 * @lenp: the size of the user buffer << 248 * @ppos: file position << 249 * << 250 * Reads/writes a string from/to the user buff << 251 * buffer provided is not large enough to hold << 252 * string is truncated. The copied string is % << 253 * If the string is being read by the user pro << 254 * and a newline '\n' is added. It is truncate << 255 * not large enough. << 256 * << 257 * Returns 0 on success. << 258 */ 479 */ 259 int proc_dostring(const struct ctl_table *tabl << 260 void *buffer, size_t *lenp, << 261 { << 262 if (write) << 263 proc_first_pos_non_zero_ignore << 264 480 265 return _proc_do_string(table->data, ta !! 481 static int test_perm(int mode, int op) 266 ppos); !! 482 { >> 483 if (!current->euid) >> 484 mode >>= 6; >> 485 else if (in_egroup_p(0)) >> 486 mode >>= 3; >> 487 if ((mode & op & 0007) == op) >> 488 return 0; >> 489 return -EACCES; 267 } 490 } 268 491 269 static void proc_skip_spaces(char **buf, size_ !! 492 static inline int ctl_perm(ctl_table *table, int op) 270 { 493 { 271 while (*size) { !! 494 return test_perm(table->mode, op); 272 if (!isspace(**buf)) !! 495 } 273 break; !! 496 274 (*size)--; !! 497 static int parse_table(int *name, int nlen, 275 (*buf)++; !! 498 void *oldval, size_t *oldlenp, >> 499 void *newval, size_t newlen, >> 500 ctl_table *table, void **context) >> 501 { >> 502 int n; >> 503 repeat: >> 504 if (!nlen) >> 505 return -ENOTDIR; >> 506 if (get_user(n, name)) >> 507 return -EFAULT; >> 508 for ( ; table->ctl_name; table++) { >> 509 if (n == table->ctl_name || table->ctl_name == CTL_ANY) { >> 510 int error; >> 511 if (table->child) { >> 512 if (ctl_perm(table, 001)) >> 513 return -EPERM; >> 514 if (table->strategy) { >> 515 int op = 0; >> 516 if (oldval) >> 517 op |= 004; >> 518 if (newval) >> 519 op |= 002; >> 520 if (ctl_perm(table, op)) >> 521 return -EPERM; >> 522 error = table->strategy( >> 523 table, name, nlen, >> 524 oldval, oldlenp, >> 525 newval, newlen, context); >> 526 if (error) >> 527 return error; >> 528 } >> 529 name++; >> 530 nlen--; >> 531 table = table->child; >> 532 goto repeat; >> 533 } >> 534 error = do_sysctl_strategy(table, name, nlen, >> 535 oldval, oldlenp, >> 536 newval, newlen, context); >> 537 return error; >> 538 } 276 } 539 } >> 540 return -ENOTDIR; 277 } 541 } 278 542 279 static void proc_skip_char(char **buf, size_t !! 543 /* Perform the actual read/write of a sysctl table entry. */ >> 544 int do_sysctl_strategy (ctl_table *table, >> 545 int *name, int nlen, >> 546 void *oldval, size_t *oldlenp, >> 547 void *newval, size_t newlen, void **context) 280 { 548 { 281 while (*size) { !! 549 int op = 0, rc; 282 if (**buf != v) !! 550 size_t len; 283 break; !! 551 284 (*size)--; !! 552 if (oldval) 285 (*buf)++; !! 553 op |= 004; >> 554 if (newval) >> 555 op |= 002; >> 556 if (ctl_perm(table, op)) >> 557 return -EPERM; >> 558 >> 559 if (table->strategy) { >> 560 rc = table->strategy(table, name, nlen, oldval, oldlenp, >> 561 newval, newlen, context); >> 562 if (rc < 0) >> 563 return rc; >> 564 if (rc > 0) >> 565 return 0; >> 566 } >> 567 >> 568 /* If there is no strategy routine, or if the strategy returns >> 569 * zero, proceed with automatic r/w */ >> 570 if (table->data && table->maxlen) { >> 571 if (oldval && oldlenp) { >> 572 if (get_user(len, oldlenp)) >> 573 return -EFAULT; >> 574 if (len) { >> 575 if (len > table->maxlen) >> 576 len = table->maxlen; >> 577 if(copy_to_user(oldval, table->data, len)) >> 578 return -EFAULT; >> 579 if(put_user(len, oldlenp)) >> 580 return -EFAULT; >> 581 } >> 582 } >> 583 if (newval && newlen) { >> 584 len = newlen; >> 585 if (len > table->maxlen) >> 586 len = table->maxlen; >> 587 if(copy_from_user(table->data, newval, len)) >> 588 return -EFAULT; >> 589 } 286 } 590 } >> 591 return 0; 287 } 592 } 288 593 289 /** 594 /** 290 * strtoul_lenient - parse an ASCII formatted !! 595 * register_sysctl_table - register a sysctl hierarchy 291 * fail on overflow !! 596 * @table: the top-level table structure >> 597 * @insert_at_head: whether the entry should be inserted in front or at the end >> 598 * >> 599 * Register a sysctl table hierarchy. @table should be a filled in ctl_table >> 600 * array. An entry with a ctl_name of 0 terminates the table. 292 * 601 * 293 * @cp: kernel buffer containing the string to !! 602 * The members of the &ctl_table structure are used as follows: 294 * @endp: pointer to store the trailing charac !! 603 * 295 * @base: the base to use !! 604 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number 296 * @res: where the parsed integer will be stor !! 605 * must be unique within that level of sysctl 297 * !! 606 * 298 * In case of success 0 is returned and @res w !! 607 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not 299 * @endp will hold any trailing characters. !! 608 * enter a sysctl file 300 * This function will fail the parse on overfl !! 609 * 301 * the function will defer the decision what c !! 610 * data - a pointer to data for use by proc_handler 302 * caller. !! 611 * >> 612 * maxlen - the maximum size in bytes of the data >> 613 * >> 614 * mode - the file permissions for the /proc/sys file, and for sysctl(2) >> 615 * >> 616 * child - a pointer to the child sysctl table if this entry is a directory, or >> 617 * %NULL. >> 618 * >> 619 * proc_handler - the text handler routine (described below) >> 620 * >> 621 * strategy - the strategy routine (described below) >> 622 * >> 623 * de - for internal use by the sysctl routines >> 624 * >> 625 * extra1, extra2 - extra pointers usable by the proc handler routines >> 626 * >> 627 * Leaf nodes in the sysctl tree will be represented by a single file >> 628 * under /proc; non-leaf nodes will be represented by directories. >> 629 * >> 630 * sysctl(2) can automatically manage read and write requests through >> 631 * the sysctl table. The data and maxlen fields of the ctl_table >> 632 * struct enable minimal validation of the values being written to be >> 633 * performed, and the mode field allows minimal authentication. >> 634 * >> 635 * More sophisticated management can be enabled by the provision of a >> 636 * strategy routine with the table entry. This will be called before >> 637 * any automatic read or write of the data is performed. >> 638 * >> 639 * The strategy routine may return >> 640 * >> 641 * < 0 - Error occurred (error is passed to user process) >> 642 * >> 643 * 0 - OK - proceed with automatic read or write. >> 644 * >> 645 * > 0 - OK - read or write has been done by the strategy routine, so >> 646 * return immediately. >> 647 * >> 648 * There must be a proc_handler routine for any terminal nodes >> 649 * mirrored under /proc/sys (non-terminals are handled by a built-in >> 650 * directory handler). Several default handlers are available to >> 651 * cover common cases - >> 652 * >> 653 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(), >> 654 * proc_dointvec_minmax(), proc_doulongvec_ms_jiffies_minmax(), >> 655 * proc_doulongvec_minmax() >> 656 * >> 657 * It is the handler's job to read the input buffer from user memory >> 658 * and process it. The handler should return 0 on success. >> 659 * >> 660 * This routine returns %NULL on a failure to register, and a pointer >> 661 * to the table header on success. 303 */ 662 */ 304 static int strtoul_lenient(const char *cp, cha !! 663 struct ctl_table_header *register_sysctl_table(ctl_table * table, 305 unsigned long *res) !! 664 int insert_at_head) 306 { 665 { 307 unsigned long long result; !! 666 struct ctl_table_header *tmp; 308 unsigned int rv; !! 667 tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL); 309 !! 668 if (!tmp) 310 cp = _parse_integer_fixup_radix(cp, &b !! 669 return NULL; 311 rv = _parse_integer(cp, base, &result) !! 670 tmp->ctl_table = table; 312 if ((rv & KSTRTOX_OVERFLOW) || (result !! 671 INIT_LIST_HEAD(&tmp->ctl_entry); 313 return -ERANGE; !! 672 tmp->used = 0; 314 !! 673 tmp->unregistering = NULL; 315 cp += rv; !! 674 spin_lock(&sysctl_lock); 316 !! 675 if (insert_at_head) 317 if (endp) !! 676 list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); 318 *endp = (char *)cp; !! 677 else 319 !! 678 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); 320 *res = (unsigned long)result; !! 679 spin_unlock(&sysctl_lock); 321 return 0; !! 680 #ifdef CONFIG_PROC_FS >> 681 register_proc_table(table, proc_sys_root, tmp); >> 682 #endif >> 683 return tmp; 322 } 684 } 323 685 324 #define TMPBUFLEN 22 << 325 /** 686 /** 326 * proc_get_long - reads an ASCII formatted in !! 687 * unregister_sysctl_table - unregister a sysctl table hierarchy >> 688 * @header: the header returned from register_sysctl_table 327 * 689 * 328 * @buf: a kernel buffer !! 690 * Unregisters the sysctl table and all children. proc entries may not 329 * @size: size of the kernel buffer !! 691 * actually be removed until they are no longer used by anyone. 330 * @val: this is where the number will be stor << 331 * @neg: set to %TRUE if number is negative << 332 * @perm_tr: a vector which contains the allow << 333 * @perm_tr_len: size of the perm_tr vector << 334 * @tr: pointer to store the trailer character << 335 * << 336 * In case of success %0 is returned and @buf << 337 * the amount of bytes read. If @tr is non-NUL << 338 * character exists (size is non-zero after re << 339 * function), @tr is updated with the trailing << 340 */ 692 */ 341 static int proc_get_long(char **buf, size_t *s !! 693 void unregister_sysctl_table(struct ctl_table_header * header) 342 unsigned long *val, << 343 const char *perm_tr, << 344 { 694 { 345 char *p, tmp[TMPBUFLEN]; !! 695 spin_lock(&sysctl_lock); 346 ssize_t len = *size; !! 696 start_unregistering(header); >> 697 #ifdef CONFIG_PROC_FS >> 698 unregister_proc_table(header->ctl_table, proc_sys_root); >> 699 #endif >> 700 spin_unlock(&sysctl_lock); >> 701 kfree(header); >> 702 } 347 703 348 if (len <= 0) !! 704 /* 349 return -EINVAL; !! 705 * /proc/sys support >> 706 */ 350 707 351 if (len > TMPBUFLEN - 1) !! 708 #ifdef CONFIG_PROC_FS 352 len = TMPBUFLEN - 1; << 353 709 354 memcpy(tmp, *buf, len); !! 710 /* Scan the sysctl entries in table and add them all into /proc */ >> 711 static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) >> 712 { >> 713 struct proc_dir_entry *de; >> 714 int len; >> 715 mode_t mode; >> 716 >> 717 for (; table->ctl_name; table++) { >> 718 /* Can't do anything without a proc name. */ >> 719 if (!table->procname) >> 720 continue; >> 721 /* Maybe we can't do anything with it... */ >> 722 if (!table->proc_handler && !table->child) { >> 723 printk(KERN_WARNING "SYSCTL: Can't register %s\n", >> 724 table->procname); >> 725 continue; >> 726 } 355 727 356 tmp[len] = 0; !! 728 len = strlen(table->procname); 357 p = tmp; !! 729 mode = table->mode; 358 if (*p == '-' && *size > 1) { << 359 *neg = true; << 360 p++; << 361 } else << 362 *neg = false; << 363 if (!isdigit(*p)) << 364 return -EINVAL; << 365 730 366 if (strtoul_lenient(p, &p, 0, val)) !! 731 de = NULL; 367 return -EINVAL; !! 732 if (table->proc_handler) >> 733 mode |= S_IFREG; >> 734 else { >> 735 mode |= S_IFDIR; >> 736 for (de = root->subdir; de; de = de->next) { >> 737 if (proc_match(len, table->procname, de)) >> 738 break; >> 739 } >> 740 /* If the subdir exists already, de is non-NULL */ >> 741 } 368 742 369 len = p - tmp; !! 743 if (!de) { >> 744 de = create_proc_entry(table->procname, mode, root); >> 745 if (!de) >> 746 continue; >> 747 de->set = set; >> 748 de->data = (void *) table; >> 749 if (table->proc_handler) { >> 750 de->proc_fops = &proc_sys_file_operations; >> 751 de->proc_iops = &proc_sys_inode_operations; >> 752 } >> 753 } >> 754 table->de = de; >> 755 if (de->mode & S_IFDIR) >> 756 register_proc_table(table->child, de, set); >> 757 } >> 758 } 370 759 371 /* We don't know if the next char is w !! 760 /* 372 * invalid integers (e.g. 1234...a) or !! 761 * Unregister a /proc sysctl table and any subdirectories. 373 * (e.g. 123...1). So lets not allow s !! 762 */ 374 if (len == TMPBUFLEN - 1) !! 763 static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root) 375 return -EINVAL; !! 764 { >> 765 struct proc_dir_entry *de; >> 766 for (; table->ctl_name; table++) { >> 767 if (!(de = table->de)) >> 768 continue; >> 769 if (de->mode & S_IFDIR) { >> 770 if (!table->child) { >> 771 printk (KERN_ALERT "Help - malformed sysctl tree on free\n"); >> 772 continue; >> 773 } >> 774 unregister_proc_table(table->child, de); 376 775 377 if (len < *size && perm_tr_len && !mem !! 776 /* Don't unregister directories which still have entries.. */ 378 return -EINVAL; !! 777 if (de->subdir) >> 778 continue; >> 779 } 379 780 380 if (tr && (len < *size)) !! 781 /* 381 *tr = *p; !! 782 * In any case, mark the entry as goner; we'll keep it >> 783 * around if it's busy, but we'll know to do nothing with >> 784 * its fields. We are under sysctl_lock here. >> 785 */ >> 786 de->data = NULL; 382 787 383 *buf += len; !! 788 /* Don't unregister proc entries that are still being used.. */ 384 *size -= len; !! 789 if (atomic_read(&de->count)) >> 790 continue; 385 791 386 return 0; !! 792 table->de = NULL; >> 793 remove_proc_entry(table->procname, root); >> 794 } 387 } 795 } 388 796 389 /** !! 797 static ssize_t do_rw_proc(int write, struct file * file, char * buf, 390 * proc_put_long - converts an integer to a de !! 798 size_t count, loff_t *ppos) 391 * << 392 * @buf: the user buffer << 393 * @size: the size of the user buffer << 394 * @val: the integer to be converted << 395 * @neg: sign of the number, %TRUE for negativ << 396 * << 397 * In case of success @buf and @size are updat << 398 * written. << 399 */ << 400 static void proc_put_long(void **buf, size_t * << 401 { 799 { 402 int len; !! 800 int op; 403 char tmp[TMPBUFLEN], *p = tmp; !! 801 struct proc_dir_entry *de = >> 802 (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip; >> 803 struct ctl_table *table; >> 804 size_t res; >> 805 ssize_t error = -ENOTDIR; >> 806 >> 807 spin_lock(&sysctl_lock); >> 808 if (de && de->data && use_table(de->set)) { >> 809 /* >> 810 * at that point we know that sysctl was not unregistered >> 811 * and won't be until we finish >> 812 */ >> 813 spin_unlock(&sysctl_lock); >> 814 table = (struct ctl_table *) de->data; >> 815 if (!table || !table->proc_handler) >> 816 goto out; >> 817 error = -EPERM; >> 818 op = (write ? 002 : 004); >> 819 if (ctl_perm(table, op)) >> 820 goto out; >> 821 >> 822 /* careful: calling conventions are nasty here */ >> 823 res = count; >> 824 >> 825 /* >> 826 * FIXME: we need to pass on ppos to the handler. >> 827 */ 404 828 405 sprintf(p, "%s%lu", neg ? "-" : "", va !! 829 error = (*table->proc_handler)(table, write, file, 406 len = strlen(tmp); !! 830 buf, &res); 407 if (len > *size) !! 831 if (!error) 408 len = *size; !! 832 error = res; 409 memcpy(*buf, tmp, len); !! 833 out: 410 *size -= len; !! 834 spin_lock(&sysctl_lock); 411 *buf += len; !! 835 unuse_table(de->set); >> 836 } >> 837 spin_unlock(&sysctl_lock); >> 838 return error; 412 } 839 } 413 #undef TMPBUFLEN << 414 840 415 static void proc_put_char(void **buf, size_t * !! 841 static ssize_t proc_readsys(struct file * file, char * buf, >> 842 size_t count, loff_t *ppos) 416 { 843 { 417 if (*size) { !! 844 return do_rw_proc(0, file, buf, count, ppos); 418 char **buffer = (char **)buf; !! 845 } 419 **buffer = c; << 420 846 421 (*size)--; !! 847 static ssize_t proc_writesys(struct file * file, const char * buf, 422 (*buffer)++; !! 848 size_t count, loff_t *ppos) 423 *buf = *buffer; !! 849 { 424 } !! 850 return do_rw_proc(1, file, (char *) buf, count, ppos); 425 } 851 } 426 852 427 static int do_proc_dointvec_conv(bool *negp, u !! 853 static int proc_sys_permission(struct inode *inode, int op) 428 int *valp, << 429 int write, vo << 430 { 854 { 431 if (write) { !! 855 return test_perm(inode->i_mode, op); 432 if (*negp) { << 433 if (*lvalp > (unsigned << 434 return -EINVAL << 435 WRITE_ONCE(*valp, -*lv << 436 } else { << 437 if (*lvalp > (unsigned << 438 return -EINVAL << 439 WRITE_ONCE(*valp, *lva << 440 } << 441 } else { << 442 int val = READ_ONCE(*valp); << 443 if (val < 0) { << 444 *negp = true; << 445 *lvalp = -(unsigned lo << 446 } else { << 447 *negp = false; << 448 *lvalp = (unsigned lon << 449 } << 450 } << 451 return 0; << 452 } 856 } 453 857 454 static int do_proc_douintvec_conv(unsigned lon !! 858 /** 455 unsigned int !! 859 * proc_dostring - read a string sysctl 456 int write, v !! 860 * @table: the sysctl table >> 861 * @write: %TRUE if this is a write to the sysctl file >> 862 * @filp: the file structure >> 863 * @buffer: the user buffer >> 864 * @lenp: the size of the user buffer >> 865 * >> 866 * Reads/writes a string from/to the user buffer. If the kernel >> 867 * buffer provided is not large enough to hold the string, the >> 868 * string is truncated. The copied string is %NULL-terminated. >> 869 * If the string is being read by the user process, it is copied >> 870 * and a newline '\n' is added. It is truncated if the buffer is >> 871 * not large enough. >> 872 * >> 873 * Returns 0 on success. >> 874 */ >> 875 int proc_dostring(ctl_table *table, int write, struct file *filp, >> 876 void *buffer, size_t *lenp) 457 { 877 { >> 878 size_t len; >> 879 char *p, c; >> 880 >> 881 if (!table->data || !table->maxlen || !*lenp || >> 882 (filp->f_pos && !write)) { >> 883 *lenp = 0; >> 884 return 0; >> 885 } >> 886 458 if (write) { 887 if (write) { 459 if (*lvalp > UINT_MAX) !! 888 len = 0; 460 return -EINVAL; !! 889 p = buffer; 461 WRITE_ONCE(*valp, *lvalp); !! 890 while (len < *lenp) { >> 891 if (get_user(c, p++)) >> 892 return -EFAULT; >> 893 if (c == 0 || c == '\n') >> 894 break; >> 895 len++; >> 896 } >> 897 if (len >= table->maxlen) >> 898 len = table->maxlen-1; >> 899 if(copy_from_user(table->data, buffer, len)) >> 900 return -EFAULT; >> 901 ((char *) table->data)[len] = 0; >> 902 filp->f_pos += *lenp; 462 } else { 903 } else { 463 unsigned int val = READ_ONCE(* !! 904 len = strlen(table->data); 464 *lvalp = (unsigned long)val; !! 905 if (len > table->maxlen) >> 906 len = table->maxlen; >> 907 if (len > *lenp) >> 908 len = *lenp; >> 909 if (len) >> 910 if(copy_to_user(buffer, table->data, len)) >> 911 return -EFAULT; >> 912 if (len < *lenp) { >> 913 if(put_user('\n', ((char *) buffer) + len)) >> 914 return -EFAULT; >> 915 len++; >> 916 } >> 917 *lenp = len; >> 918 filp->f_pos += len; 465 } 919 } 466 return 0; 920 return 0; 467 } 921 } 468 922 469 static const char proc_wspace_sep[] = { ' ', ' !! 923 /* 470 !! 924 * Special case of dostring for the UTS structure. This has locks 471 static int __do_proc_dointvec(void *tbl_data, !! 925 * to observe. Should this be in kernel/sys.c ???? 472 int write, void *buffer, !! 926 */ 473 size_t *lenp, loff_t *ppos, !! 927 474 int (*conv)(bool *negp, unsi !! 928 static int proc_doutsstring(ctl_table *table, int write, struct file *filp, 475 int write, void !! 929 void *buffer, size_t *lenp) 476 void *data) !! 930 { 477 { !! 931 int r; 478 int *i, vleft, first = 1, err = 0; << 479 size_t left; << 480 char *p; << 481 932 482 if (!tbl_data || !table->maxlen || !*l !! 933 if (!write) { >> 934 down_read(&uts_sem); >> 935 r=proc_dostring(table,0,filp,buffer,lenp); >> 936 up_read(&uts_sem); >> 937 } else { >> 938 down_write(&uts_sem); >> 939 r=proc_dostring(table,1,filp,buffer,lenp); >> 940 up_write(&uts_sem); >> 941 } >> 942 return r; >> 943 } >> 944 >> 945 #define OP_SET 0 >> 946 #define OP_AND 1 >> 947 #define OP_OR 2 >> 948 #define OP_MAX 3 >> 949 #define OP_MIN 4 >> 950 >> 951 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp, >> 952 void *buffer, size_t *lenp, int conv, int op) >> 953 { >> 954 int *i, vleft, first=1, neg, val; >> 955 size_t left, len; >> 956 >> 957 #define TMPBUFLEN 20 >> 958 char buf[TMPBUFLEN], *p; >> 959 >> 960 if (!table->data || !table->maxlen || !*lenp || >> 961 (filp->f_pos && !write)) { 483 *lenp = 0; 962 *lenp = 0; 484 return 0; 963 return 0; 485 } 964 } 486 !! 965 487 i = (int *) tbl_data; !! 966 i = (int *) table->data; 488 vleft = table->maxlen / sizeof(*i); !! 967 vleft = table->maxlen / sizeof(int); 489 left = *lenp; 968 left = *lenp; 490 !! 969 491 if (!conv) << 492 conv = do_proc_dointvec_conv; << 493 << 494 if (write) { << 495 if (proc_first_pos_non_zero_ig << 496 goto out; << 497 << 498 if (left > PAGE_SIZE - 1) << 499 left = PAGE_SIZE - 1; << 500 p = buffer; << 501 } << 502 << 503 for (; left && vleft--; i++, first=0) 970 for (; left && vleft--; i++, first=0) { 504 unsigned long lval; << 505 bool neg; << 506 << 507 if (write) { 971 if (write) { 508 proc_skip_spaces(&p, & !! 972 while (left) { 509 !! 973 char c; >> 974 if (get_user(c, (char *) buffer)) >> 975 return -EFAULT; >> 976 if (!isspace(c)) >> 977 break; >> 978 left--; >> 979 buffer++; >> 980 } 510 if (!left) 981 if (!left) 511 break; 982 break; 512 err = proc_get_long(&p !! 983 neg = 0; 513 p !! 984 len = left; 514 s !! 985 if (len > TMPBUFLEN-1) 515 if (err) !! 986 len = TMPBUFLEN-1; >> 987 if(copy_from_user(buf, buffer, len)) >> 988 return -EFAULT; >> 989 buf[len] = 0; >> 990 p = buf; >> 991 if (*p == '-' && left > 1) { >> 992 neg = 1; >> 993 left--, p++; >> 994 } >> 995 if (*p < '' || *p > '9') 516 break; 996 break; 517 if (conv(&neg, &lval, !! 997 val = simple_strtoul(p, &p, 0) * conv; 518 err = -EINVAL; !! 998 len = p-buf; >> 999 if ((len < left) && *p && !isspace(*p)) 519 break; 1000 break; >> 1001 if (neg) >> 1002 val = -val; >> 1003 buffer += len; >> 1004 left -= len; >> 1005 switch(op) { >> 1006 case OP_SET: *i = val; break; >> 1007 case OP_AND: *i &= val; break; >> 1008 case OP_OR: *i |= val; break; >> 1009 case OP_MAX: if(*i < val) >> 1010 *i = val; >> 1011 break; >> 1012 case OP_MIN: if(*i > val) >> 1013 *i = val; >> 1014 break; 520 } 1015 } 521 } else { 1016 } else { 522 if (conv(&neg, &lval, !! 1017 p = buf; 523 err = -EINVAL; << 524 break; << 525 } << 526 if (!first) 1018 if (!first) 527 proc_put_char( !! 1019 *p++ = '\t'; 528 proc_put_long(&buffer, !! 1020 sprintf(p, "%d", (*i) / conv); >> 1021 len = strlen(buf); >> 1022 if (len > left) >> 1023 len = left; >> 1024 if(copy_to_user(buffer, buf, len)) >> 1025 return -EFAULT; >> 1026 left -= len; >> 1027 buffer += len; 529 } 1028 } 530 } 1029 } 531 1030 532 if (!write && !first && left && !err) !! 1031 if (!write && !first && left) { 533 proc_put_char(&buffer, &left, !! 1032 if(put_user('\n', (char *) buffer)) 534 if (write && !err && left) !! 1033 return -EFAULT; 535 proc_skip_spaces(&p, &left); !! 1034 left--, buffer++; 536 if (write && first) << 537 return err ? : -EINVAL; << 538 *lenp -= left; << 539 out: << 540 *ppos += *lenp; << 541 return err; << 542 } << 543 << 544 static int do_proc_dointvec(const struct ctl_t << 545 void *buffer, size_t *lenp, << 546 int (*conv)(bool *negp, unsi << 547 int write, void << 548 void *data) << 549 { << 550 return __do_proc_dointvec(table->data, << 551 buffer, lenp, ppos, co << 552 } << 553 << 554 static int do_proc_douintvec_w(unsigned int *t << 555 const struct ct << 556 void *buffer, << 557 size_t *lenp, l << 558 int (*conv)(uns << 559 uns << 560 int << 561 void *data) << 562 { << 563 unsigned long lval; << 564 int err = 0; << 565 size_t left; << 566 bool neg; << 567 char *p = buffer; << 568 << 569 left = *lenp; << 570 << 571 if (proc_first_pos_non_zero_ignore(ppo << 572 goto bail_early; << 573 << 574 if (left > PAGE_SIZE - 1) << 575 left = PAGE_SIZE - 1; << 576 << 577 proc_skip_spaces(&p, &left); << 578 if (!left) { << 579 err = -EINVAL; << 580 goto out_free; << 581 } << 582 << 583 err = proc_get_long(&p, &left, &lval, << 584 proc_wspace_sep, << 585 sizeof(proc_wspac << 586 if (err || neg) { << 587 err = -EINVAL; << 588 goto out_free; << 589 } 1035 } 590 !! 1036 if (write) { 591 if (conv(&lval, tbl_data, 1, data)) { !! 1037 p = (char *) buffer; 592 err = -EINVAL; !! 1038 while (left) { 593 goto out_free; !! 1039 char c; >> 1040 if (get_user(c, p++)) >> 1041 return -EFAULT; >> 1042 if (!isspace(c)) >> 1043 break; >> 1044 left--; >> 1045 } 594 } 1046 } 595 !! 1047 if (write && first) 596 if (!err && left) << 597 proc_skip_spaces(&p, &left); << 598 << 599 out_free: << 600 if (err) << 601 return -EINVAL; 1048 return -EINVAL; 602 << 603 return 0; << 604 << 605 /* This is in keeping with old __do_pr << 606 bail_early: << 607 *ppos += *lenp; << 608 return err; << 609 } << 610 << 611 static int do_proc_douintvec_r(unsigned int *t << 612 size_t *lenp, l << 613 int (*conv)(uns << 614 uns << 615 int << 616 void *data) << 617 { << 618 unsigned long lval; << 619 int err = 0; << 620 size_t left; << 621 << 622 left = *lenp; << 623 << 624 if (conv(&lval, tbl_data, 0, data)) { << 625 err = -EINVAL; << 626 goto out; << 627 } << 628 << 629 proc_put_long(&buffer, &left, lval, fa << 630 if (!left) << 631 goto out; << 632 << 633 proc_put_char(&buffer, &left, '\n'); << 634 << 635 out: << 636 *lenp -= left; 1049 *lenp -= left; 637 *ppos += *lenp; !! 1050 filp->f_pos += *lenp; 638 << 639 return err; << 640 } << 641 << 642 static int __do_proc_douintvec(void *tbl_data, << 643 int write, void << 644 size_t *lenp, l << 645 int (*conv)(uns << 646 uns << 647 int << 648 void *data) << 649 { << 650 unsigned int *i, vleft; << 651 << 652 if (!tbl_data || !table->maxlen || !*l << 653 *lenp = 0; << 654 return 0; << 655 } << 656 << 657 i = (unsigned int *) tbl_data; << 658 vleft = table->maxlen / sizeof(*i); << 659 << 660 /* << 661 * Arrays are not supported, keep this << 662 * support for them. << 663 */ << 664 if (vleft != 1) { << 665 *lenp = 0; << 666 return -EINVAL; << 667 } << 668 << 669 if (!conv) << 670 conv = do_proc_douintvec_conv; << 671 << 672 if (write) << 673 return do_proc_douintvec_w(i, << 674 con << 675 return do_proc_douintvec_r(i, buffer, << 676 } << 677 << 678 int do_proc_douintvec(const struct ctl_table * << 679 void *buffer, size_t *le << 680 int (*conv)(unsigned lon << 681 unsigned int << 682 int write, v << 683 void *data) << 684 { << 685 return __do_proc_douintvec(table->data << 686 buffer, len << 687 } << 688 << 689 /** << 690 * proc_dobool - read/write a bool << 691 * @table: the sysctl table << 692 * @write: %TRUE if this is a write to the sys << 693 * @buffer: the user buffer << 694 * @lenp: the size of the user buffer << 695 * @ppos: file position << 696 * << 697 * Reads/writes one integer value from/to the << 698 * treated as an ASCII string. << 699 * << 700 * table->data must point to a bool variable a << 701 * be sizeof(bool). << 702 * << 703 * Returns 0 on success. << 704 */ << 705 int proc_dobool(const struct ctl_table *table, << 706 size_t *lenp, loff_t *ppos) << 707 { << 708 struct ctl_table tmp; << 709 bool *data = table->data; << 710 int res, val; << 711 << 712 /* Do not support arrays yet. */ << 713 if (table->maxlen != sizeof(bool)) << 714 return -EINVAL; << 715 << 716 tmp = *table; << 717 tmp.maxlen = sizeof(val); << 718 tmp.data = &val; << 719 << 720 val = READ_ONCE(*data); << 721 res = proc_dointvec(&tmp, write, buffe << 722 if (res) << 723 return res; << 724 if (write) << 725 WRITE_ONCE(*data, val); << 726 return 0; 1051 return 0; 727 } 1052 } 728 1053 729 /** 1054 /** 730 * proc_dointvec - read a vector of integers 1055 * proc_dointvec - read a vector of integers 731 * @table: the sysctl table 1056 * @table: the sysctl table 732 * @write: %TRUE if this is a write to the sys 1057 * @write: %TRUE if this is a write to the sysctl file >> 1058 * @filp: the file structure 733 * @buffer: the user buffer 1059 * @buffer: the user buffer 734 * @lenp: the size of the user buffer 1060 * @lenp: the size of the user buffer 735 * @ppos: file position << 736 * 1061 * 737 * Reads/writes up to table->maxlen/sizeof(uns 1062 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 738 * values from/to the user buffer, treated as !! 1063 * values from/to the user buffer, treated as an ASCII string. 739 * << 740 * Returns 0 on success. << 741 */ << 742 int proc_dointvec(const struct ctl_table *tabl << 743 size_t *lenp, loff_t *ppos) << 744 { << 745 return do_proc_dointvec(table, write, << 746 } << 747 << 748 /** << 749 * proc_douintvec - read a vector of unsigned << 750 * @table: the sysctl table << 751 * @write: %TRUE if this is a write to the sys << 752 * @buffer: the user buffer << 753 * @lenp: the size of the user buffer << 754 * @ppos: file position << 755 * << 756 * Reads/writes up to table->maxlen/sizeof(uns << 757 * values from/to the user buffer, treated as << 758 * 1064 * 759 * Returns 0 on success. 1065 * Returns 0 on success. 760 */ 1066 */ 761 int proc_douintvec(const struct ctl_table *tab !! 1067 int proc_dointvec(ctl_table *table, int write, struct file *filp, 762 size_t *lenp, loff_t *ppos) !! 1068 void *buffer, size_t *lenp) 763 { 1069 { 764 return do_proc_douintvec(table, write, !! 1070 return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET); 765 do_proc_douin << 766 } 1071 } 767 1072 768 /* 1073 /* 769 * Taint values can only be increased !! 1074 * init may raise the set. 770 * This means we can safely use a temporary. << 771 */ 1075 */ 772 static int proc_taint(const struct ctl_table * !! 1076 773 void *buffer, s !! 1077 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, >> 1078 void *buffer, size_t *lenp) 774 { 1079 { 775 struct ctl_table t; !! 1080 if (!capable(CAP_SYS_MODULE)) { 776 unsigned long tmptaint = get_taint(); << 777 int err; << 778 << 779 if (write && !capable(CAP_SYS_ADMIN)) << 780 return -EPERM; 1081 return -EPERM; 781 << 782 t = *table; << 783 t.data = &tmptaint; << 784 err = proc_doulongvec_minmax(&t, write << 785 if (err < 0) << 786 return err; << 787 << 788 if (write) { << 789 int i; << 790 << 791 /* << 792 * If we are relying on panic_ << 793 * false positives due to user << 794 * before setting the requeste << 795 */ << 796 if (panic_on_taint_nousertaint << 797 return -EINVAL; << 798 << 799 /* << 800 * Poor man's atomic or. Not w << 801 * to everyone's atomic.h for << 802 */ << 803 for (i = 0; i < TAINT_FLAGS_CO << 804 if ((1UL << i) & tmpta << 805 add_taint(i, L << 806 } << 807 << 808 return err; << 809 } << 810 << 811 /** << 812 * struct do_proc_dointvec_minmax_conv_param - << 813 * @min: pointer to minimum allowable value << 814 * @max: pointer to maximum allowable value << 815 * << 816 * The do_proc_dointvec_minmax_conv_param stru << 817 * minimum and maximum values for doing range << 818 * parameters that use the proc_dointvec_minma << 819 */ << 820 struct do_proc_dointvec_minmax_conv_param { << 821 int *min; << 822 int *max; << 823 }; << 824 << 825 static int do_proc_dointvec_minmax_conv(bool * << 826 int *v << 827 int wr << 828 { << 829 int tmp, ret; << 830 struct do_proc_dointvec_minmax_conv_pa << 831 /* << 832 * If writing, first do so via a tempo << 833 * bounds-check it before touching *va << 834 */ << 835 int *ip = write ? &tmp : valp; << 836 << 837 ret = do_proc_dointvec_conv(negp, lval << 838 if (ret) << 839 return ret; << 840 << 841 if (write) { << 842 if ((param->min && *param->min << 843 (param->max && *param->max << 844 return -EINVAL; << 845 WRITE_ONCE(*valp, tmp); << 846 } 1082 } 847 !! 1083 return do_proc_dointvec(table,write,filp,buffer,lenp,1, 848 return 0; !! 1084 (current->pid == 1) ? OP_SET : OP_AND); 849 } 1085 } 850 1086 851 /** 1087 /** 852 * proc_dointvec_minmax - read a vector of int 1088 * proc_dointvec_minmax - read a vector of integers with min/max values 853 * @table: the sysctl table 1089 * @table: the sysctl table 854 * @write: %TRUE if this is a write to the sys 1090 * @write: %TRUE if this is a write to the sysctl file >> 1091 * @filp: the file structure 855 * @buffer: the user buffer 1092 * @buffer: the user buffer 856 * @lenp: the size of the user buffer 1093 * @lenp: the size of the user buffer 857 * @ppos: file position << 858 * 1094 * 859 * Reads/writes up to table->maxlen/sizeof(uns 1095 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 860 * values from/to the user buffer, treated as 1096 * values from/to the user buffer, treated as an ASCII string. 861 * 1097 * 862 * This routine will ensure the values are wit 1098 * This routine will ensure the values are within the range specified by 863 * table->extra1 (min) and table->extra2 (max) 1099 * table->extra1 (min) and table->extra2 (max). 864 * 1100 * 865 * Returns 0 on success or -EINVAL on write wh !! 1101 * Returns 0 on success. 866 */ 1102 */ 867 int proc_dointvec_minmax(const struct ctl_tabl !! 1103 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, 868 void *buffer, size_t *lenp, !! 1104 void *buffer, size_t *lenp) 869 { 1105 { 870 struct do_proc_dointvec_minmax_conv_pa !! 1106 int *i, *min, *max, vleft, first=1, neg, val; 871 .min = (int *) table->extra1, !! 1107 size_t len, left; 872 .max = (int *) table->extra2, !! 1108 #define TMPBUFLEN 20 873 }; !! 1109 char buf[TMPBUFLEN], *p; 874 return do_proc_dointvec(table, write, !! 1110 875 do_proc_dointv !! 1111 if (!table->data || !table->maxlen || !*lenp || 876 } !! 1112 (filp->f_pos && !write)) { 877 !! 1113 *lenp = 0; 878 /** !! 1114 return 0; 879 * struct do_proc_douintvec_minmax_conv_param !! 1115 } 880 * @min: pointer to minimum allowable value !! 1116 881 * @max: pointer to maximum allowable value !! 1117 i = (int *) table->data; 882 * !! 1118 min = (int *) table->extra1; 883 * The do_proc_douintvec_minmax_conv_param str !! 1119 max = (int *) table->extra2; 884 * minimum and maximum values for doing range !! 1120 vleft = table->maxlen / sizeof(int); 885 * parameters that use the proc_douintvec_minm !! 1121 left = *lenp; 886 */ !! 1122 887 struct do_proc_douintvec_minmax_conv_param { !! 1123 for (; left && vleft--; i++, min++, max++, first=0) { 888 unsigned int *min; !! 1124 if (write) { 889 unsigned int *max; !! 1125 while (left) { 890 }; !! 1126 char c; 891 !! 1127 if (get_user(c, (char *) buffer)) 892 static int do_proc_douintvec_minmax_conv(unsig !! 1128 return -EFAULT; 893 unsig !! 1129 if (!isspace(c)) 894 int w !! 1130 break; 895 { !! 1131 left--; 896 int ret; !! 1132 buffer++; 897 unsigned int tmp; !! 1133 } 898 struct do_proc_douintvec_minmax_conv_p !! 1134 if (!left) 899 /* write via temporary local uint for !! 1135 break; 900 unsigned int *up = write ? &tmp : valp !! 1136 neg = 0; 901 !! 1137 len = left; 902 ret = do_proc_douintvec_conv(lvalp, up !! 1138 if (len > TMPBUFLEN-1) 903 if (ret) !! 1139 len = TMPBUFLEN-1; 904 return ret; !! 1140 if(copy_from_user(buf, buffer, len)) >> 1141 return -EFAULT; >> 1142 buf[len] = 0; >> 1143 p = buf; >> 1144 if (*p == '-' && left > 1) { >> 1145 neg = 1; >> 1146 left--, p++; >> 1147 } >> 1148 if (*p < '' || *p > '9') >> 1149 break; >> 1150 val = simple_strtoul(p, &p, 0); >> 1151 len = p-buf; >> 1152 if ((len < left) && *p && !isspace(*p)) >> 1153 break; >> 1154 if (neg) >> 1155 val = -val; >> 1156 buffer += len; >> 1157 left -= len; >> 1158 >> 1159 if ((min && val < *min) || (max && val > *max)) >> 1160 continue; >> 1161 *i = val; >> 1162 } else { >> 1163 p = buf; >> 1164 if (!first) >> 1165 *p++ = '\t'; >> 1166 sprintf(p, "%d", *i); >> 1167 len = strlen(buf); >> 1168 if (len > left) >> 1169 len = left; >> 1170 if(copy_to_user(buffer, buf, len)) >> 1171 return -EFAULT; >> 1172 left -= len; >> 1173 buffer += len; >> 1174 } >> 1175 } 905 1176 >> 1177 if (!write && !first && left) { >> 1178 if(put_user('\n', (char *) buffer)) >> 1179 return -EFAULT; >> 1180 left--, buffer++; >> 1181 } 906 if (write) { 1182 if (write) { 907 if ((param->min && *param->min !! 1183 p = (char *) buffer; 908 (param->max && *param->max !! 1184 while (left) { 909 return -ERANGE; !! 1185 char c; 910 !! 1186 if (get_user(c, p++)) 911 WRITE_ONCE(*valp, tmp); !! 1187 return -EFAULT; >> 1188 if (!isspace(c)) >> 1189 break; >> 1190 left--; >> 1191 } 912 } 1192 } 913 !! 1193 if (write && first) 914 return 0; << 915 } << 916 << 917 /** << 918 * proc_douintvec_minmax - read a vector of un << 919 * @table: the sysctl table << 920 * @write: %TRUE if this is a write to the sys << 921 * @buffer: the user buffer << 922 * @lenp: the size of the user buffer << 923 * @ppos: file position << 924 * << 925 * Reads/writes up to table->maxlen/sizeof(uns << 926 * values from/to the user buffer, treated as << 927 * strings are not allowed. << 928 * << 929 * This routine will ensure the values are wit << 930 * table->extra1 (min) and table->extra2 (max) << 931 * check for UINT_MAX to avoid having to suppo << 932 * userspace. << 933 * << 934 * Returns 0 on success or -ERANGE on write wh << 935 */ << 936 int proc_douintvec_minmax(const struct ctl_tab << 937 void *buffer, size_t << 938 { << 939 struct do_proc_douintvec_minmax_conv_p << 940 .min = (unsigned int *) table- << 941 .max = (unsigned int *) table- << 942 }; << 943 return do_proc_douintvec(table, write, << 944 do_proc_douin << 945 } << 946 << 947 /** << 948 * proc_dou8vec_minmax - read a vector of unsi << 949 * @table: the sysctl table << 950 * @write: %TRUE if this is a write to the sys << 951 * @buffer: the user buffer << 952 * @lenp: the size of the user buffer << 953 * @ppos: file position << 954 * << 955 * Reads/writes up to table->maxlen/sizeof(u8) << 956 * values from/to the user buffer, treated as << 957 * strings are not allowed. << 958 * << 959 * This routine will ensure the values are wit << 960 * table->extra1 (min) and table->extra2 (max) << 961 * << 962 * Returns 0 on success or an error on write w << 963 */ << 964 int proc_dou8vec_minmax(const struct ctl_table << 965 void *buffer, size_t * << 966 { << 967 struct ctl_table tmp; << 968 unsigned int min = 0, max = 255U, val; << 969 u8 *data = table->data; << 970 struct do_proc_douintvec_minmax_conv_p << 971 .min = &min, << 972 .max = &max, << 973 }; << 974 int res; << 975 << 976 /* Do not support arrays yet. */ << 977 if (table->maxlen != sizeof(u8)) << 978 return -EINVAL; 1194 return -EINVAL; 979 !! 1195 *lenp -= left; 980 if (table->extra1) !! 1196 filp->f_pos += *lenp; 981 min = *(unsigned int *) table- << 982 if (table->extra2) << 983 max = *(unsigned int *) table- << 984 << 985 tmp = *table; << 986 << 987 tmp.maxlen = sizeof(val); << 988 tmp.data = &val; << 989 val = READ_ONCE(*data); << 990 res = do_proc_douintvec(&tmp, write, b << 991 do_proc_douint << 992 if (res) << 993 return res; << 994 if (write) << 995 WRITE_ONCE(*data, val); << 996 return 0; << 997 } << 998 EXPORT_SYMBOL_GPL(proc_dou8vec_minmax); << 999 << 1000 #ifdef CONFIG_MAGIC_SYSRQ << 1001 static int sysrq_sysctl_handler(const struct << 1002 void *buffer, << 1003 { << 1004 int tmp, ret; << 1005 << 1006 tmp = sysrq_mask(); << 1007 << 1008 ret = __do_proc_dointvec(&tmp, table, << 1009 lenp, ppos, NU << 1010 if (ret || !write) << 1011 return ret; << 1012 << 1013 if (write) << 1014 sysrq_toggle_support(tmp); << 1015 << 1016 return 0; 1197 return 0; 1017 } 1198 } 1018 #endif << 1019 << 1020 static int __do_proc_doulongvec_minmax(void * << 1021 const struct ctl_table *table << 1022 void *buffer, size_t *lenp, l << 1023 unsigned long convmul, unsign << 1024 { << 1025 unsigned long *i, *min, *max; << 1026 int vleft, first = 1, err = 0; << 1027 size_t left; << 1028 char *p; << 1029 1199 1030 if (!data || !table->maxlen || !*lenp !! 1200 static int do_proc_doulongvec_minmax(ctl_table *table, int write, >> 1201 struct file *filp, >> 1202 void *buffer, size_t *lenp, >> 1203 unsigned long convmul, >> 1204 unsigned long convdiv) >> 1205 { >> 1206 #define TMPBUFLEN 20 >> 1207 unsigned long *i, *min, *max, val; >> 1208 int vleft, first=1, neg; >> 1209 size_t len, left; >> 1210 char buf[TMPBUFLEN], *p; >> 1211 >> 1212 if (!table->data || !table->maxlen || !*lenp || >> 1213 (filp->f_pos && !write)) { 1031 *lenp = 0; 1214 *lenp = 0; 1032 return 0; 1215 return 0; 1033 } 1216 } 1034 !! 1217 1035 i = data; !! 1218 i = (unsigned long *) table->data; 1036 min = table->extra1; !! 1219 min = (unsigned long *) table->extra1; 1037 max = table->extra2; !! 1220 max = (unsigned long *) table->extra2; 1038 vleft = table->maxlen / sizeof(unsign 1221 vleft = table->maxlen / sizeof(unsigned long); 1039 left = *lenp; 1222 left = *lenp; 1040 !! 1223 1041 if (write) { !! 1224 for (; left && vleft--; i++, first=0) { 1042 if (proc_first_pos_non_zero_i << 1043 goto out; << 1044 << 1045 if (left > PAGE_SIZE - 1) << 1046 left = PAGE_SIZE - 1; << 1047 p = buffer; << 1048 } << 1049 << 1050 for (; left && vleft--; i++, first = << 1051 unsigned long val; << 1052 << 1053 if (write) { 1225 if (write) { 1054 bool neg; !! 1226 while (left) { 1055 !! 1227 char c; 1056 proc_skip_spaces(&p, !! 1228 if (get_user(c, (char *) buffer)) >> 1229 return -EFAULT; >> 1230 if (!isspace(c)) >> 1231 break; >> 1232 left--; >> 1233 buffer++; >> 1234 } 1057 if (!left) 1235 if (!left) 1058 break; 1236 break; 1059 !! 1237 neg = 0; 1060 err = proc_get_long(& !! 1238 len = left; 1061 !! 1239 if (len > TMPBUFLEN-1) 1062 !! 1240 len = TMPBUFLEN-1; 1063 if (err || neg) { !! 1241 if(copy_from_user(buf, buffer, len)) 1064 err = -EINVAL !! 1242 return -EFAULT; 1065 break; !! 1243 buf[len] = 0; >> 1244 p = buf; >> 1245 if (*p == '-' && left > 1) { >> 1246 neg = 1; >> 1247 left--, p++; 1066 } 1248 } 1067 !! 1249 if (*p < '' || *p > '9') 1068 val = convmul * val / << 1069 if ((min && val < *mi << 1070 err = -EINVAL << 1071 break; 1250 break; 1072 } !! 1251 val = simple_strtoul(p, &p, 0) * convmul / convdiv ; 1073 WRITE_ONCE(*i, val); !! 1252 len = p-buf; >> 1253 if ((len < left) && *p && !isspace(*p)) >> 1254 break; >> 1255 if (neg) >> 1256 val = -val; >> 1257 buffer += len; >> 1258 left -= len; >> 1259 >> 1260 if(neg) >> 1261 continue; >> 1262 if (min && val < *min++) >> 1263 continue; >> 1264 if (max && val > *max++) >> 1265 continue; >> 1266 *i = val; 1074 } else { 1267 } else { 1075 val = convdiv * READ_ !! 1268 p = buf; 1076 if (!first) 1269 if (!first) 1077 proc_put_char !! 1270 *p++ = '\t'; 1078 proc_put_long(&buffer !! 1271 sprintf(p, "%lu", convdiv * (*i) / convmul); >> 1272 len = strlen(buf); >> 1273 if (len > left) >> 1274 len = left; >> 1275 if(copy_to_user(buffer, buf, len)) >> 1276 return -EFAULT; >> 1277 left -= len; >> 1278 buffer += len; 1079 } 1279 } 1080 } 1280 } 1081 1281 1082 if (!write && !first && left && !err) !! 1282 if (!write && !first && left) { 1083 proc_put_char(&buffer, &left, !! 1283 if(put_user('\n', (char *) buffer)) 1084 if (write && !err) !! 1284 return -EFAULT; 1085 proc_skip_spaces(&p, &left); !! 1285 left--, buffer++; >> 1286 } >> 1287 if (write) { >> 1288 p = (char *) buffer; >> 1289 while (left) { >> 1290 char c; >> 1291 if (get_user(c, p++)) >> 1292 return -EFAULT; >> 1293 if (!isspace(c)) >> 1294 break; >> 1295 left--; >> 1296 } >> 1297 } 1086 if (write && first) 1298 if (write && first) 1087 return err ? : -EINVAL; !! 1299 return -EINVAL; 1088 *lenp -= left; 1300 *lenp -= left; 1089 out: !! 1301 filp->f_pos += *lenp; 1090 *ppos += *lenp; !! 1302 return 0; 1091 return err; !! 1303 #undef TMPBUFLEN 1092 } << 1093 << 1094 static int do_proc_doulongvec_minmax(const st << 1095 void *buffer, size_t *lenp, l << 1096 unsigned long convdiv) << 1097 { << 1098 return __do_proc_doulongvec_minmax(ta << 1099 buffer, lenp, ppos, c << 1100 } 1304 } 1101 1305 1102 /** 1306 /** 1103 * proc_doulongvec_minmax - read a vector of 1307 * proc_doulongvec_minmax - read a vector of long integers with min/max values 1104 * @table: the sysctl table 1308 * @table: the sysctl table 1105 * @write: %TRUE if this is a write to the sy 1309 * @write: %TRUE if this is a write to the sysctl file >> 1310 * @filp: the file structure 1106 * @buffer: the user buffer 1311 * @buffer: the user buffer 1107 * @lenp: the size of the user buffer 1312 * @lenp: the size of the user buffer 1108 * @ppos: file position << 1109 * 1313 * 1110 * Reads/writes up to table->maxlen/sizeof(un 1314 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long 1111 * values from/to the user buffer, treated as 1315 * values from/to the user buffer, treated as an ASCII string. 1112 * 1316 * 1113 * This routine will ensure the values are wi 1317 * This routine will ensure the values are within the range specified by 1114 * table->extra1 (min) and table->extra2 (max 1318 * table->extra1 (min) and table->extra2 (max). 1115 * 1319 * 1116 * Returns 0 on success. 1320 * Returns 0 on success. 1117 */ 1321 */ 1118 int proc_doulongvec_minmax(const struct ctl_t !! 1322 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, 1119 void *buffer, size !! 1323 void *buffer, size_t *lenp) 1120 { 1324 { 1121 return do_proc_doulongvec_minmax(table, w !! 1325 return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l); 1122 } 1326 } 1123 1327 1124 /** 1328 /** 1125 * proc_doulongvec_ms_jiffies_minmax - read a 1329 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values 1126 * @table: the sysctl table 1330 * @table: the sysctl table 1127 * @write: %TRUE if this is a write to the sy 1331 * @write: %TRUE if this is a write to the sysctl file >> 1332 * @filp: the file structure 1128 * @buffer: the user buffer 1333 * @buffer: the user buffer 1129 * @lenp: the size of the user buffer 1334 * @lenp: the size of the user buffer 1130 * @ppos: file position << 1131 * 1335 * 1132 * Reads/writes up to table->maxlen/sizeof(un 1336 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long 1133 * values from/to the user buffer, treated as 1337 * values from/to the user buffer, treated as an ASCII string. The values 1134 * are treated as milliseconds, and converted 1338 * are treated as milliseconds, and converted to jiffies when they are stored. 1135 * 1339 * 1136 * This routine will ensure the values are wi 1340 * This routine will ensure the values are within the range specified by 1137 * table->extra1 (min) and table->extra2 (max 1341 * table->extra1 (min) and table->extra2 (max). 1138 * 1342 * 1139 * Returns 0 on success. 1343 * Returns 0 on success. 1140 */ 1344 */ 1141 int proc_doulongvec_ms_jiffies_minmax(const s !! 1345 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, 1142 void *b !! 1346 struct file *filp, >> 1347 void *buffer, size_t *lenp) 1143 { 1348 { 1144 return do_proc_doulongvec_minmax(table, w !! 1349 return do_proc_doulongvec_minmax(table, write, filp, buffer, 1145 lenp, pp !! 1350 lenp, HZ, 1000l); 1146 } 1351 } 1147 1352 1148 1353 1149 static int do_proc_dointvec_jiffies_conv(bool << 1150 int << 1151 int << 1152 { << 1153 if (write) { << 1154 if (*lvalp > INT_MAX / HZ) << 1155 return 1; << 1156 if (*negp) << 1157 WRITE_ONCE(*valp, -*l << 1158 else << 1159 WRITE_ONCE(*valp, *lv << 1160 } else { << 1161 int val = READ_ONCE(*valp); << 1162 unsigned long lval; << 1163 if (val < 0) { << 1164 *negp = true; << 1165 lval = -(unsigned lon << 1166 } else { << 1167 *negp = false; << 1168 lval = (unsigned long << 1169 } << 1170 *lvalp = lval / HZ; << 1171 } << 1172 return 0; << 1173 } << 1174 << 1175 static int do_proc_dointvec_userhz_jiffies_co << 1176 << 1177 << 1178 { << 1179 if (write) { << 1180 if (USER_HZ < HZ && *lvalp > << 1181 return 1; << 1182 *valp = clock_t_to_jiffies(*n << 1183 } else { << 1184 int val = *valp; << 1185 unsigned long lval; << 1186 if (val < 0) { << 1187 *negp = true; << 1188 lval = -(unsigned lon << 1189 } else { << 1190 *negp = false; << 1191 lval = (unsigned long << 1192 } << 1193 *lvalp = jiffies_to_clock_t(l << 1194 } << 1195 return 0; << 1196 } << 1197 << 1198 static int do_proc_dointvec_ms_jiffies_conv(b << 1199 i << 1200 i << 1201 { << 1202 if (write) { << 1203 unsigned long jif = msecs_to_ << 1204 << 1205 if (jif > INT_MAX) << 1206 return 1; << 1207 WRITE_ONCE(*valp, (int)jif); << 1208 } else { << 1209 int val = READ_ONCE(*valp); << 1210 unsigned long lval; << 1211 if (val < 0) { << 1212 *negp = true; << 1213 lval = -(unsigned lon << 1214 } else { << 1215 *negp = false; << 1216 lval = (unsigned long << 1217 } << 1218 *lvalp = jiffies_to_msecs(lva << 1219 } << 1220 return 0; << 1221 } << 1222 << 1223 static int do_proc_dointvec_ms_jiffies_minmax << 1224 << 1225 { << 1226 int tmp, ret; << 1227 struct do_proc_dointvec_minmax_conv_p << 1228 /* << 1229 * If writing, first do so via a temp << 1230 * bounds-check it before touching *v << 1231 */ << 1232 int *ip = write ? &tmp : valp; << 1233 << 1234 ret = do_proc_dointvec_ms_jiffies_con << 1235 if (ret) << 1236 return ret; << 1237 << 1238 if (write) { << 1239 if ((param->min && *param->mi << 1240 (param->max & << 1241 return -EINVAL; << 1242 *valp = tmp; << 1243 } << 1244 return 0; << 1245 } << 1246 << 1247 /** 1354 /** 1248 * proc_dointvec_jiffies - read a vector of i 1355 * proc_dointvec_jiffies - read a vector of integers as seconds 1249 * @table: the sysctl table 1356 * @table: the sysctl table 1250 * @write: %TRUE if this is a write to the sy 1357 * @write: %TRUE if this is a write to the sysctl file >> 1358 * @filp: the file structure 1251 * @buffer: the user buffer 1359 * @buffer: the user buffer 1252 * @lenp: the size of the user buffer 1360 * @lenp: the size of the user buffer 1253 * @ppos: file position << 1254 * 1361 * 1255 * Reads/writes up to table->maxlen/sizeof(un 1362 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 1256 * values from/to the user buffer, treated as !! 1363 * values from/to the user buffer, treated as an ASCII string. 1257 * The values read are assumed to be in secon 1364 * The values read are assumed to be in seconds, and are converted into 1258 * jiffies. 1365 * jiffies. 1259 * 1366 * 1260 * Returns 0 on success. 1367 * Returns 0 on success. 1261 */ 1368 */ 1262 int proc_dointvec_jiffies(const struct ctl_ta !! 1369 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, 1263 void *buffer, size_ !! 1370 void *buffer, size_t *lenp) 1264 { 1371 { 1265 return do_proc_dointvec(table,write,buffe !! 1372 return do_proc_dointvec(table,write,filp,buffer,lenp,HZ,OP_SET); 1266 do_proc_dointvec_ << 1267 } 1373 } 1268 1374 1269 int proc_dointvec_ms_jiffies_minmax(const str !! 1375 #else /* CONFIG_PROC_FS */ 1270 void *buffer, size_ << 1271 { << 1272 struct do_proc_dointvec_minmax_conv_p << 1273 .min = (int *) table->extra1, << 1274 .max = (int *) table->extra2, << 1275 }; << 1276 return do_proc_dointvec(table, write, << 1277 do_proc_dointvec_ms_j << 1278 } << 1279 1376 1280 /** !! 1377 int proc_dostring(ctl_table *table, int write, struct file *filp, 1281 * proc_dointvec_userhz_jiffies - read a vect !! 1378 void *buffer, size_t *lenp) 1282 * @table: the sysctl table << 1283 * @write: %TRUE if this is a write to the sy << 1284 * @buffer: the user buffer << 1285 * @lenp: the size of the user buffer << 1286 * @ppos: pointer to the file position << 1287 * << 1288 * Reads/writes up to table->maxlen/sizeof(un << 1289 * values from/to the user buffer, treated as << 1290 * The values read are assumed to be in 1/USE << 1291 * are converted into jiffies. << 1292 * << 1293 * Returns 0 on success. << 1294 */ << 1295 int proc_dointvec_userhz_jiffies(const struct << 1296 void *buffer << 1297 { 1379 { 1298 return do_proc_dointvec(table, write, !! 1380 return -ENOSYS; 1299 do_proc_doint << 1300 } 1381 } 1301 1382 1302 /** !! 1383 static int proc_doutsstring(ctl_table *table, int write, struct file *filp, 1303 * proc_dointvec_ms_jiffies - read a vector o !! 1384 void *buffer, size_t *lenp) 1304 * @table: the sysctl table << 1305 * @write: %TRUE if this is a write to the sy << 1306 * @buffer: the user buffer << 1307 * @lenp: the size of the user buffer << 1308 * @ppos: file position << 1309 * @ppos: the current position in the file << 1310 * << 1311 * Reads/writes up to table->maxlen/sizeof(un << 1312 * values from/to the user buffer, treated as << 1313 * The values read are assumed to be in 1/100 << 1314 * are converted into jiffies. << 1315 * << 1316 * Returns 0 on success. << 1317 */ << 1318 int proc_dointvec_ms_jiffies(const struct ctl << 1319 size_t *lenp, loff_t *ppos) << 1320 { 1385 { 1321 return do_proc_dointvec(table, write, !! 1386 return -ENOSYS; 1322 do_proc_doint << 1323 } 1387 } 1324 1388 1325 static int proc_do_cad_pid(const struct ctl_t !! 1389 int proc_dointvec(ctl_table *table, int write, struct file *filp, 1326 size_t *lenp, loff_t *ppos) !! 1390 void *buffer, size_t *lenp) 1327 { 1391 { 1328 struct pid *new_pid; !! 1392 return -ENOSYS; 1329 pid_t tmp; << 1330 int r; << 1331 << 1332 tmp = pid_vnr(cad_pid); << 1333 << 1334 r = __do_proc_dointvec(&tmp, table, w << 1335 lenp, ppos, NU << 1336 if (r || !write) << 1337 return r; << 1338 << 1339 new_pid = find_get_pid(tmp); << 1340 if (!new_pid) << 1341 return -ESRCH; << 1342 << 1343 put_pid(xchg(&cad_pid, new_pid)); << 1344 return 0; << 1345 } 1393 } 1346 1394 1347 /** !! 1395 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, 1348 * proc_do_large_bitmap - read/write from/to !! 1396 void *buffer, size_t *lenp) 1349 * @table: the sysctl table << 1350 * @write: %TRUE if this is a write to the sy << 1351 * @buffer: the user buffer << 1352 * @lenp: the size of the user buffer << 1353 * @ppos: file position << 1354 * << 1355 * The bitmap is stored at table->data and th << 1356 * in table->maxlen. << 1357 * << 1358 * We use a range comma separated format (e.g << 1359 * large bitmaps may be represented in a comp << 1360 * the file will clear the bitmap then update << 1361 * << 1362 * Returns 0 on success. << 1363 */ << 1364 int proc_do_large_bitmap(const struct ctl_tab << 1365 void *buffer, size_t << 1366 { 1397 { 1367 int err = 0; !! 1398 return -ENOSYS; 1368 size_t left = *lenp; !! 1399 } 1369 unsigned long bitmap_len = table->max << 1370 unsigned long *bitmap = *(unsigned lo << 1371 unsigned long *tmp_bitmap = NULL; << 1372 char tr_a[] = { '-', ',', '\n' }, tr_ << 1373 1400 1374 if (!bitmap || !bitmap_len || !left | !! 1401 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, 1375 *lenp = 0; !! 1402 void *buffer, size_t *lenp) 1376 return 0; !! 1403 { 1377 } !! 1404 return -ENOSYS; >> 1405 } 1378 1406 1379 if (write) { !! 1407 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, 1380 char *p = buffer; !! 1408 void *buffer, size_t *lenp) 1381 size_t skipped = 0; !! 1409 { >> 1410 return -ENOSYS; >> 1411 } 1382 1412 1383 if (left > PAGE_SIZE - 1) { !! 1413 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, 1384 left = PAGE_SIZE - 1; !! 1414 void *buffer, size_t *lenp) 1385 /* How much of the bu !! 1415 { 1386 skipped = *lenp - lef !! 1416 return -ENOSYS; 1387 } !! 1417 } 1388 1418 1389 tmp_bitmap = bitmap_zalloc(bi !! 1419 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, 1390 if (!tmp_bitmap) !! 1420 struct file *filp, 1391 return -ENOMEM; !! 1421 void *buffer, size_t *lenp) 1392 proc_skip_char(&p, &left, '\n !! 1422 { 1393 while (!err && left) { !! 1423 return -ENOSYS; 1394 unsigned long val_a, !! 1424 } 1395 bool neg; << 1396 size_t saved_left; << 1397 << 1398 /* In case we stop pa << 1399 saved_left = left; << 1400 err = proc_get_long(& << 1401 << 1402 /* << 1403 * If we consumed the << 1404 * only one char is l << 1405 * reset, & come back << 1406 */ << 1407 if ((left <= 1) && sk << 1408 left = saved_ << 1409 break; << 1410 } << 1411 1425 1412 if (err) << 1413 break; << 1414 if (val_a >= bitmap_l << 1415 err = -EINVAL << 1416 break; << 1417 } << 1418 1426 1419 val_b = val_a; !! 1427 #endif /* CONFIG_PROC_FS */ 1420 if (left) { << 1421 p++; << 1422 left--; << 1423 } << 1424 1428 1425 if (c == '-') { << 1426 err = proc_ge << 1427 << 1428 << 1429 /* << 1430 * If we cons << 1431 * then stop << 1432 */ << 1433 if (!left && << 1434 left << 1435 break << 1436 } << 1437 1429 1438 if (err) !! 1430 /* 1439 break !! 1431 * General sysctl support routines 1440 if (val_b >= !! 1432 */ 1441 val_a > v << 1442 err = << 1443 break << 1444 } << 1445 if (left) { << 1446 p++; << 1447 left- << 1448 } << 1449 } << 1450 1433 1451 bitmap_set(tmp_bitmap !! 1434 /* The generic string strategy routine: */ 1452 proc_skip_char(&p, &l !! 1435 int sysctl_string(ctl_table *table, int *name, int nlen, >> 1436 void *oldval, size_t *oldlenp, >> 1437 void *newval, size_t newlen, void **context) >> 1438 { >> 1439 size_t l, len; >> 1440 >> 1441 if (!table->data || !table->maxlen) >> 1442 return -ENOTDIR; >> 1443 >> 1444 if (oldval && oldlenp) { >> 1445 if (get_user(len, oldlenp)) >> 1446 return -EFAULT; >> 1447 if (len) { >> 1448 l = strlen(table->data); >> 1449 if (len > l) len = l; >> 1450 if (len >= table->maxlen) >> 1451 len = table->maxlen; >> 1452 if(copy_to_user(oldval, table->data, len)) >> 1453 return -EFAULT; >> 1454 if(put_user(0, ((char *) oldval) + len)) >> 1455 return -EFAULT; >> 1456 if(put_user(len, oldlenp)) >> 1457 return -EFAULT; 1453 } 1458 } 1454 left += skipped; !! 1459 } 1455 } else { !! 1460 if (newval && newlen) { 1456 unsigned long bit_a, bit_b = !! 1461 len = newlen; 1457 bool first = 1; !! 1462 if (len > table->maxlen) >> 1463 len = table->maxlen; >> 1464 if(copy_from_user(table->data, newval, len)) >> 1465 return -EFAULT; >> 1466 if (len == table->maxlen) >> 1467 len--; >> 1468 ((char *) table->data)[len] = 0; >> 1469 } >> 1470 return 1; >> 1471 } 1458 1472 1459 while (left) { !! 1473 /* 1460 bit_a = find_next_bit !! 1474 * This function makes sure that all of the integers in the vector 1461 if (bit_a >= bitmap_l !! 1475 * are between the minimum and maximum values given in the arrays 1462 break; !! 1476 * table->extra1 and table->extra2, respectively. 1463 bit_b = find_next_zer !! 1477 */ 1464 !! 1478 int sysctl_intvec(ctl_table *table, int *name, int nlen, >> 1479 void *oldval, size_t *oldlenp, >> 1480 void *newval, size_t newlen, void **context) >> 1481 { >> 1482 int i, *vec, *min, *max; >> 1483 size_t length; 1465 1484 1466 if (!first) !! 1485 if (newval && newlen) { 1467 proc_put_char !! 1486 if (newlen % sizeof(int) != 0) 1468 proc_put_long(&buffer !! 1487 return -EINVAL; 1469 if (bit_a != bit_b) { << 1470 proc_put_char << 1471 proc_put_long << 1472 } << 1473 1488 1474 first = 0; bit_b++; !! 1489 if (!table->extra1 && !table->extra2) >> 1490 return 0; >> 1491 >> 1492 if (newlen > table->maxlen) >> 1493 newlen = table->maxlen; >> 1494 length = newlen / sizeof(int); >> 1495 >> 1496 vec = (int *) newval; >> 1497 min = (int *) table->extra1; >> 1498 max = (int *) table->extra2; >> 1499 >> 1500 for (i = 0; i < length; i++) { >> 1501 int value; >> 1502 if (get_user(value, vec + i)) >> 1503 return -EFAULT; >> 1504 if (min && value < min[i]) >> 1505 return -EINVAL; >> 1506 if (max && value > max[i]) >> 1507 return -EINVAL; 1475 } 1508 } 1476 proc_put_char(&buffer, &left, << 1477 } 1509 } >> 1510 return 0; >> 1511 } 1478 1512 1479 if (!err) { !! 1513 /* Strategy function to convert jiffies to seconds */ 1480 if (write) { !! 1514 int sysctl_jiffies(ctl_table *table, int *name, int nlen, 1481 if (*ppos) !! 1515 void *oldval, size_t *oldlenp, 1482 bitmap_or(bit !! 1516 void *newval, size_t newlen, void **context) 1483 else !! 1517 { 1484 bitmap_copy(b !! 1518 if (oldval) { >> 1519 size_t olen; >> 1520 if (oldlenp) { >> 1521 if (get_user(olen, oldlenp)) >> 1522 return -EFAULT; >> 1523 if (olen!=sizeof(int)) >> 1524 return -EINVAL; 1485 } 1525 } 1486 *lenp -= left; !! 1526 if (put_user(*(int *)(table->data) / HZ, (int *)oldval) || 1487 *ppos += *lenp; !! 1527 (oldlenp && put_user(sizeof(int),oldlenp))) >> 1528 return -EFAULT; 1488 } 1529 } 1489 !! 1530 if (newval && newlen) { 1490 bitmap_free(tmp_bitmap); !! 1531 int new; 1491 return err; !! 1532 if (newlen != sizeof(int)) >> 1533 return -EINVAL; >> 1534 if (get_user(new, (int *)newval)) >> 1535 return -EFAULT; >> 1536 *(int *)(table->data) = new*HZ; >> 1537 } >> 1538 return 1; 1492 } 1539 } 1493 1540 1494 #else /* CONFIG_PROC_SYSCTL */ << 1495 1541 1496 int proc_dostring(const struct ctl_table *tab !! 1542 #else /* CONFIG_SYSCTL */ 1497 void *buffer, size_t *lenp, << 1498 { << 1499 return -ENOSYS; << 1500 } << 1501 1543 1502 int proc_dobool(const struct ctl_table *table << 1503 void *buffer, size_t *lenp, l << 1504 { << 1505 return -ENOSYS; << 1506 } << 1507 1544 1508 int proc_dointvec(const struct ctl_table *tab !! 1545 extern asmlinkage long sys_sysctl(struct __sysctl_args *args) 1509 void *buffer, size_t *lenp, << 1510 { 1546 { 1511 return -ENOSYS; 1547 return -ENOSYS; 1512 } 1548 } 1513 1549 1514 int proc_douintvec(const struct ctl_table *ta !! 1550 int sysctl_string(ctl_table *table, int *name, int nlen, 1515 void *buffer, size_t *lenp, !! 1551 void *oldval, size_t *oldlenp, >> 1552 void *newval, size_t newlen, void **context) 1516 { 1553 { 1517 return -ENOSYS; 1554 return -ENOSYS; 1518 } 1555 } 1519 1556 1520 int proc_dointvec_minmax(const struct ctl_tab !! 1557 int sysctl_intvec(ctl_table *table, int *name, int nlen, 1521 void *buffer, size_t *len !! 1558 void *oldval, size_t *oldlenp, >> 1559 void *newval, size_t newlen, void **context) 1522 { 1560 { 1523 return -ENOSYS; 1561 return -ENOSYS; 1524 } 1562 } 1525 1563 1526 int proc_douintvec_minmax(const struct ctl_ta !! 1564 int sysctl_jiffies(ctl_table *table, int *name, int nlen, 1527 void *buffer, size_ !! 1565 void *oldval, size_t *oldlenp, >> 1566 void *newval, size_t newlen, void **context) 1528 { 1567 { 1529 return -ENOSYS; 1568 return -ENOSYS; 1530 } 1569 } 1531 1570 1532 int proc_dou8vec_minmax(const struct ctl_tabl !! 1571 int proc_dostring(ctl_table *table, int write, struct file *filp, 1533 void *buffer, size_t !! 1572 void *buffer, size_t *lenp) 1534 { 1573 { 1535 return -ENOSYS; 1574 return -ENOSYS; 1536 } 1575 } 1537 1576 1538 int proc_dointvec_jiffies(const struct ctl_ta !! 1577 int proc_dointvec(ctl_table *table, int write, struct file *filp, 1539 void *buffer, size_t *len !! 1578 void *buffer, size_t *lenp) 1540 { 1579 { 1541 return -ENOSYS; 1580 return -ENOSYS; 1542 } 1581 } 1543 1582 1544 int proc_dointvec_ms_jiffies_minmax(const str !! 1583 int proc_dointvec_bset(ctl_table *table, int write, struct file *filp, 1545 void *buf !! 1584 void *buffer, size_t *lenp) 1546 { 1585 { 1547 return -ENOSYS; 1586 return -ENOSYS; 1548 } 1587 } 1549 1588 1550 int proc_dointvec_userhz_jiffies(const struct !! 1589 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp, 1551 void *buffer, size_t *len !! 1590 void *buffer, size_t *lenp) 1552 { 1591 { 1553 return -ENOSYS; 1592 return -ENOSYS; 1554 } 1593 } 1555 1594 1556 int proc_dointvec_ms_jiffies(const struct ctl !! 1595 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp, 1557 void *buffer, si !! 1596 void *buffer, size_t *lenp) 1558 { 1597 { 1559 return -ENOSYS; 1598 return -ENOSYS; 1560 } 1599 } 1561 1600 1562 int proc_doulongvec_minmax(const struct ctl_t !! 1601 int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, 1563 void *buffer, size_t *len !! 1602 void *buffer, size_t *lenp) 1564 { 1603 { 1565 return -ENOSYS; 1604 return -ENOSYS; 1566 } 1605 } 1567 1606 1568 int proc_doulongvec_ms_jiffies_minmax(const s !! 1607 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write, 1569 void *b !! 1608 struct file *filp, >> 1609 void *buffer, size_t *lenp) 1570 { 1610 { 1571 return -ENOSYS; !! 1611 return -ENOSYS; 1572 } 1612 } 1573 1613 1574 int proc_do_large_bitmap(const struct ctl_tab !! 1614 struct ctl_table_header * register_sysctl_table(ctl_table * table, 1575 void *buffer, size_t !! 1615 int insert_at_head) 1576 { 1616 { 1577 return -ENOSYS; !! 1617 return 0; 1578 } 1618 } 1579 1619 1580 #endif /* CONFIG_PROC_SYSCTL */ !! 1620 void unregister_sysctl_table(struct ctl_table_header * table) 1581 << 1582 #if defined(CONFIG_SYSCTL) << 1583 int proc_do_static_key(const struct ctl_table << 1584 void *buffer, size_t * << 1585 { 1621 { 1586 struct static_key *key = (struct stat << 1587 static DEFINE_MUTEX(static_key_mutex) << 1588 int val, ret; << 1589 struct ctl_table tmp = { << 1590 .data = &val, << 1591 .maxlen = sizeof(val), << 1592 .mode = table->mode, << 1593 .extra1 = SYSCTL_ZERO, << 1594 .extra2 = SYSCTL_ONE, << 1595 }; << 1596 << 1597 if (write && !capable(CAP_SYS_ADMIN)) << 1598 return -EPERM; << 1599 << 1600 mutex_lock(&static_key_mutex); << 1601 val = static_key_enabled(key); << 1602 ret = proc_dointvec_minmax(&tmp, writ << 1603 if (write && !ret) { << 1604 if (val) << 1605 static_key_enable(key << 1606 else << 1607 static_key_disable(ke << 1608 } << 1609 mutex_unlock(&static_key_mutex); << 1610 return ret; << 1611 } << 1612 << 1613 static struct ctl_table kern_table[] = { << 1614 { << 1615 .procname = "panic", << 1616 .data = &panic_time << 1617 .maxlen = sizeof(int) << 1618 .mode = 0644, << 1619 .proc_handler = proc_dointv << 1620 }, << 1621 #ifdef CONFIG_PROC_SYSCTL << 1622 { << 1623 .procname = "tainted", << 1624 .maxlen = sizeof(long << 1625 .mode = 0644, << 1626 .proc_handler = proc_taint, << 1627 }, << 1628 { << 1629 .procname = "sysctl_wri << 1630 .data = &sysctl_wri << 1631 .maxlen = sizeof(int) << 1632 .mode = 0644, << 1633 .proc_handler = proc_dointv << 1634 .extra1 = SYSCTL_NEG_ << 1635 .extra2 = SYSCTL_ONE, << 1636 }, << 1637 #endif << 1638 { << 1639 .procname = "print-fata << 1640 .data = &print_fata << 1641 .maxlen = sizeof(int) << 1642 .mode = 0644, << 1643 .proc_handler = proc_dointv << 1644 }, << 1645 #ifdef CONFIG_SPARC << 1646 { << 1647 .procname = "reboot-cmd << 1648 .data = reboot_comm << 1649 .maxlen = 256, << 1650 .mode = 0644, << 1651 .proc_handler = proc_dostri << 1652 }, << 1653 { << 1654 .procname = "stop-a", << 1655 .data = &stop_a_ena << 1656 .maxlen = sizeof (int << 1657 .mode = 0644, << 1658 .proc_handler = proc_dointv << 1659 }, << 1660 { << 1661 .procname = "scons-powe << 1662 .data = &scons_pwro << 1663 .maxlen = sizeof (int << 1664 .mode = 0644, << 1665 .proc_handler = proc_dointv << 1666 }, << 1667 #endif << 1668 #ifdef CONFIG_SPARC64 << 1669 { << 1670 .procname = "tsb-ratio" << 1671 .data = &sysctl_tsb << 1672 .maxlen = sizeof (int << 1673 .mode = 0644, << 1674 .proc_handler = proc_dointv << 1675 }, << 1676 #endif << 1677 #ifdef CONFIG_PARISC << 1678 { << 1679 .procname = "soft-power << 1680 .data = &pwrsw_enab << 1681 .maxlen = sizeof (int << 1682 .mode = 0644, << 1683 .proc_handler = proc_dointv << 1684 }, << 1685 #endif << 1686 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW << 1687 { << 1688 .procname = "unaligned- << 1689 .data = &unaligned_ << 1690 .maxlen = sizeof (int << 1691 .mode = 0644, << 1692 .proc_handler = proc_dointv << 1693 }, << 1694 #endif << 1695 #ifdef CONFIG_STACK_TRACER << 1696 { << 1697 .procname = "stack_trac << 1698 .data = &stack_trac << 1699 .maxlen = sizeof(int) << 1700 .mode = 0644, << 1701 .proc_handler = stack_trace << 1702 }, << 1703 #endif << 1704 #ifdef CONFIG_TRACING << 1705 { << 1706 .procname = "ftrace_dum << 1707 .data = &ftrace_dum << 1708 .maxlen = MAX_TRACER_ << 1709 .mode = 0644, << 1710 .proc_handler = proc_dostri << 1711 }, << 1712 { << 1713 .procname = "traceoff_o << 1714 .data = &__disable_ << 1715 .maxlen = sizeof(__di << 1716 .mode = 0644, << 1717 .proc_handler = proc_dointv << 1718 }, << 1719 { << 1720 .procname = "tracepoint << 1721 .data = &tracepoint << 1722 .maxlen = sizeof(trac << 1723 .mode = 0644, << 1724 .proc_handler = tracepoint_ << 1725 }, << 1726 #endif << 1727 #ifdef CONFIG_MODULES << 1728 { << 1729 .procname = "modprobe", << 1730 .data = &modprobe_p << 1731 .maxlen = KMOD_PATH_L << 1732 .mode = 0644, << 1733 .proc_handler = proc_dostri << 1734 }, << 1735 { << 1736 .procname = "modules_di << 1737 .data = &modules_di << 1738 .maxlen = sizeof(int) << 1739 .mode = 0644, << 1740 /* only handle a transition f << 1741 .proc_handler = proc_dointv << 1742 .extra1 = SYSCTL_ONE, << 1743 .extra2 = SYSCTL_ONE, << 1744 }, << 1745 #endif << 1746 #ifdef CONFIG_UEVENT_HELPER << 1747 { << 1748 .procname = "hotplug", << 1749 .data = &uevent_hel << 1750 .maxlen = UEVENT_HELP << 1751 .mode = 0644, << 1752 .proc_handler = proc_dostri << 1753 }, << 1754 #endif << 1755 #ifdef CONFIG_MAGIC_SYSRQ << 1756 { << 1757 .procname = "sysrq", << 1758 .data = NULL, << 1759 .maxlen = sizeof (int << 1760 .mode = 0644, << 1761 .proc_handler = sysrq_sysct << 1762 }, << 1763 #endif << 1764 #ifdef CONFIG_PROC_SYSCTL << 1765 { << 1766 .procname = "cad_pid", << 1767 .data = NULL, << 1768 .maxlen = sizeof (int << 1769 .mode = 0600, << 1770 .proc_handler = proc_do_cad << 1771 }, << 1772 #endif << 1773 { << 1774 .procname = "threads-ma << 1775 .data = NULL, << 1776 .maxlen = sizeof(int) << 1777 .mode = 0644, << 1778 .proc_handler = sysctl_max_ << 1779 }, << 1780 { << 1781 .procname = "overflowui << 1782 .data = &overflowui << 1783 .maxlen = sizeof(int) << 1784 .mode = 0644, << 1785 .proc_handler = proc_dointv << 1786 .extra1 = SYSCTL_ZERO << 1787 .extra2 = SYSCTL_MAXO << 1788 }, << 1789 { << 1790 .procname = "overflowgi << 1791 .data = &overflowgi << 1792 .maxlen = sizeof(int) << 1793 .mode = 0644, << 1794 .proc_handler = proc_dointv << 1795 .extra1 = SYSCTL_ZERO << 1796 .extra2 = SYSCTL_MAXO << 1797 }, << 1798 #ifdef CONFIG_S390 << 1799 { << 1800 .procname = "userproces << 1801 .data = &show_unhan << 1802 .maxlen = sizeof(int) << 1803 .mode = 0644, << 1804 .proc_handler = proc_dointv << 1805 }, << 1806 #endif << 1807 { << 1808 .procname = "pid_max", << 1809 .data = &pid_max, << 1810 .maxlen = sizeof (int << 1811 .mode = 0644, << 1812 .proc_handler = proc_dointv << 1813 .extra1 = &pid_max_mi << 1814 .extra2 = &pid_max_ma << 1815 }, << 1816 { << 1817 .procname = "panic_on_o << 1818 .data = &panic_on_o << 1819 .maxlen = sizeof(int) << 1820 .mode = 0644, << 1821 .proc_handler = proc_dointv << 1822 }, << 1823 { << 1824 .procname = "panic_prin << 1825 .data = &panic_prin << 1826 .maxlen = sizeof(unsi << 1827 .mode = 0644, << 1828 .proc_handler = proc_doulon << 1829 }, << 1830 { << 1831 .procname = "ngroups_ma << 1832 .data = (void *)&ng << 1833 .maxlen = sizeof (int << 1834 .mode = 0444, << 1835 .proc_handler = proc_dointv << 1836 }, << 1837 { << 1838 .procname = "cap_last_c << 1839 .data = (void *)&ca << 1840 .maxlen = sizeof(int) << 1841 .mode = 0444, << 1842 .proc_handler = proc_dointv << 1843 }, << 1844 #if defined(CONFIG_X86_LOCAL_APIC) && defined << 1845 { << 1846 .procname = "unknown_nm << 1847 .data = &unknown_nm << 1848 .maxlen = sizeof (int << 1849 .mode = 0644, << 1850 .proc_handler = proc_dointv << 1851 }, << 1852 #endif << 1853 << 1854 #if (defined(CONFIG_X86_32) || defined(CONFIG << 1855 defined(CONFIG_DEBUG_STACKOVERFLOW) << 1856 { << 1857 .procname = "panic_on_s << 1858 .data = &sysctl_pan << 1859 .maxlen = sizeof(int) << 1860 .mode = 0644, << 1861 .proc_handler = proc_dointv << 1862 }, << 1863 #endif << 1864 #if defined(CONFIG_X86) << 1865 { << 1866 .procname = "panic_on_u << 1867 .data = &panic_on_u << 1868 .maxlen = sizeof(int) << 1869 .mode = 0644, << 1870 .proc_handler = proc_dointv << 1871 }, << 1872 { << 1873 .procname = "panic_on_i << 1874 .data = &panic_on_i << 1875 .maxlen = sizeof(int) << 1876 .mode = 0644, << 1877 .proc_handler = proc_dointv << 1878 }, << 1879 { << 1880 .procname = "bootloader << 1881 .data = &bootloader << 1882 .maxlen = sizeof (int << 1883 .mode = 0444, << 1884 .proc_handler = proc_dointv << 1885 }, << 1886 { << 1887 .procname = "bootloader << 1888 .data = &bootloader << 1889 .maxlen = sizeof (int << 1890 .mode = 0444, << 1891 .proc_handler = proc_dointv << 1892 }, << 1893 { << 1894 .procname = "io_delay_t << 1895 .data = &io_delay_t << 1896 .maxlen = sizeof(int) << 1897 .mode = 0644, << 1898 .proc_handler = proc_dointv << 1899 }, << 1900 #endif << 1901 #if defined(CONFIG_MMU) << 1902 { << 1903 .procname = "randomize_ << 1904 .data = &randomize_ << 1905 .maxlen = sizeof(int) << 1906 .mode = 0644, << 1907 .proc_handler = proc_dointv << 1908 }, << 1909 #endif << 1910 #if defined(CONFIG_S390) && defined(CONFIG_SM << 1911 { << 1912 .procname = "spin_retry << 1913 .data = &spin_retry << 1914 .maxlen = sizeof (int << 1915 .mode = 0644, << 1916 .proc_handler = proc_dointv << 1917 }, << 1918 #endif << 1919 #if defined(CONFIG_ACPI_SLEEP) && defined << 1920 { << 1921 .procname = "acpi_video << 1922 .data = &acpi_realm << 1923 .maxlen = sizeof (uns << 1924 .mode = 0644, << 1925 .proc_handler = proc_doulon << 1926 }, << 1927 #endif << 1928 #ifdef CONFIG_SYSCTL_ARCH_UNALIGN_NO_WARN << 1929 { << 1930 .procname = "ignore-una << 1931 .data = &no_unalign << 1932 .maxlen = sizeof (int << 1933 .mode = 0644, << 1934 .proc_handler = proc_dointv << 1935 }, << 1936 #endif << 1937 #ifdef CONFIG_RT_MUTEXES << 1938 { << 1939 .procname = "max_lock_d << 1940 .data = &max_lock_d << 1941 .maxlen = sizeof(int) << 1942 .mode = 0644, << 1943 .proc_handler = proc_dointv << 1944 }, << 1945 #endif << 1946 #ifdef CONFIG_PERF_EVENTS << 1947 /* << 1948 * User-space scripts rely on the exi << 1949 * as a feature check for perf_events << 1950 * << 1951 * So it's an ABI, do not remove! << 1952 */ << 1953 { << 1954 .procname = "perf_event << 1955 .data = &sysctl_per << 1956 .maxlen = sizeof(sysc << 1957 .mode = 0644, << 1958 .proc_handler = proc_dointv << 1959 }, << 1960 { << 1961 .procname = "perf_event << 1962 .data = &sysctl_per << 1963 .maxlen = sizeof(sysc << 1964 .mode = 0644, << 1965 .proc_handler = proc_dointv << 1966 }, << 1967 { << 1968 .procname = "perf_event << 1969 .data = &sysctl_per << 1970 .maxlen = sizeof(sysc << 1971 .mode = 0644, << 1972 .proc_handler = perf_event_ << 1973 .extra1 = SYSCTL_ONE, << 1974 }, << 1975 { << 1976 .procname = "perf_cpu_t << 1977 .data = &sysctl_per << 1978 .maxlen = sizeof(sysc << 1979 .mode = 0644, << 1980 .proc_handler = perf_cpu_ti << 1981 .extra1 = SYSCTL_ZERO << 1982 .extra2 = SYSCTL_ONE_ << 1983 }, << 1984 { << 1985 .procname = "perf_event << 1986 .data = &sysctl_per << 1987 .maxlen = sizeof(sysc << 1988 .mode = 0644, << 1989 .proc_handler = perf_event_ << 1990 .extra1 = SYSCTL_ZERO << 1991 .extra2 = (void *)&si << 1992 }, << 1993 { << 1994 .procname = "perf_event << 1995 .data = &sysctl_per << 1996 .maxlen = sizeof(sysc << 1997 .mode = 0644, << 1998 .proc_handler = perf_event_ << 1999 .extra1 = SYSCTL_ZERO << 2000 .extra2 = SYSCTL_ONE_ << 2001 }, << 2002 #endif << 2003 { << 2004 .procname = "panic_on_w << 2005 .data = &panic_on_w << 2006 .maxlen = sizeof(int) << 2007 .mode = 0644, << 2008 .proc_handler = proc_dointv << 2009 .extra1 = SYSCTL_ZERO << 2010 .extra2 = SYSCTL_ONE, << 2011 }, << 2012 #ifdef CONFIG_TREE_RCU << 2013 { << 2014 .procname = "panic_on_r << 2015 .data = &sysctl_pan << 2016 .maxlen = sizeof(sysc << 2017 .mode = 0644, << 2018 .proc_handler = proc_dointv << 2019 .extra1 = SYSCTL_ZERO << 2020 .extra2 = SYSCTL_ONE, << 2021 }, << 2022 { << 2023 .procname = "max_rcu_st << 2024 .data = &sysctl_max << 2025 .maxlen = sizeof(sysc << 2026 .mode = 0644, << 2027 .proc_handler = proc_dointv << 2028 .extra1 = SYSCTL_ONE, << 2029 .extra2 = SYSCTL_INT_ << 2030 }, << 2031 #endif << 2032 }; << 2033 << 2034 static struct ctl_table vm_table[] = { << 2035 { << 2036 .procname = "overcommit << 2037 .data = &sysctl_ove << 2038 .maxlen = sizeof(sysc << 2039 .mode = 0644, << 2040 .proc_handler = overcommit_ << 2041 .extra1 = SYSCTL_ZERO << 2042 .extra2 = SYSCTL_TWO, << 2043 }, << 2044 { << 2045 .procname = "overcommit << 2046 .data = &sysctl_ove << 2047 .maxlen = sizeof(sysc << 2048 .mode = 0644, << 2049 .proc_handler = overcommit_ << 2050 }, << 2051 { << 2052 .procname = "overcommit << 2053 .data = &sysctl_ove << 2054 .maxlen = sizeof(sysc << 2055 .mode = 0644, << 2056 .proc_handler = overcommit_ << 2057 }, << 2058 { << 2059 .procname = "page-clust << 2060 .data = &page_clust << 2061 .maxlen = sizeof(int) << 2062 .mode = 0644, << 2063 .proc_handler = proc_dointv << 2064 .extra1 = SYSCTL_ZERO << 2065 .extra2 = (void *)&pa << 2066 }, << 2067 { << 2068 .procname = "dirtytime_ << 2069 .data = &dirtytime_ << 2070 .maxlen = sizeof(dirt << 2071 .mode = 0644, << 2072 .proc_handler = dirtytime_i << 2073 .extra1 = SYSCTL_ZERO << 2074 }, << 2075 { << 2076 .procname = "swappiness << 2077 .data = &vm_swappin << 2078 .maxlen = sizeof(vm_s << 2079 .mode = 0644, << 2080 .proc_handler = proc_dointv << 2081 .extra1 = SYSCTL_ZERO << 2082 .extra2 = SYSCTL_TWO_ << 2083 }, << 2084 #ifdef CONFIG_NUMA << 2085 { << 2086 .procname = "numa_stat" << 2087 .data = &sysctl_vm_ << 2088 .maxlen = sizeof(int) << 2089 .mode = 0644, << 2090 .proc_handler = sysctl_vm_n << 2091 .extra1 = SYSCTL_ZERO << 2092 .extra2 = SYSCTL_ONE, << 2093 }, << 2094 #endif << 2095 { << 2096 .procname = "drop_cache << 2097 .data = &sysctl_dro << 2098 .maxlen = sizeof(int) << 2099 .mode = 0200, << 2100 .proc_handler = drop_caches << 2101 .extra1 = SYSCTL_ONE, << 2102 .extra2 = SYSCTL_FOUR << 2103 }, << 2104 { << 2105 .procname = "page_lock_ << 2106 .data = &sysctl_pag << 2107 .maxlen = sizeof(sysc << 2108 .mode = 0644, << 2109 .proc_handler = proc_dointv << 2110 .extra1 = SYSCTL_ZERO << 2111 }, << 2112 #ifdef CONFIG_MMU << 2113 { << 2114 .procname = "max_map_co << 2115 .data = &sysctl_max << 2116 .maxlen = sizeof(sysc << 2117 .mode = 0644, << 2118 .proc_handler = proc_dointv << 2119 .extra1 = SYSCTL_ZERO << 2120 }, << 2121 #else << 2122 { << 2123 .procname = "nr_trim_pa << 2124 .data = &sysctl_nr_ << 2125 .maxlen = sizeof(sysc << 2126 .mode = 0644, << 2127 .proc_handler = proc_dointv << 2128 .extra1 = SYSCTL_ZERO << 2129 }, << 2130 #endif << 2131 { << 2132 .procname = "vfs_cache_ << 2133 .data = &sysctl_vfs << 2134 .maxlen = sizeof(sysc << 2135 .mode = 0644, << 2136 .proc_handler = proc_dointv << 2137 .extra1 = SYSCTL_ZERO << 2138 }, << 2139 #if defined(HAVE_ARCH_PICK_MMAP_LAYOUT) || \ << 2140 defined(CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_ << 2141 { << 2142 .procname = "legacy_va_ << 2143 .data = &sysctl_leg << 2144 .maxlen = sizeof(sysc << 2145 .mode = 0644, << 2146 .proc_handler = proc_dointv << 2147 .extra1 = SYSCTL_ZERO << 2148 }, << 2149 #endif << 2150 #ifdef CONFIG_NUMA << 2151 { << 2152 .procname = "zone_recla << 2153 .data = &node_recla << 2154 .maxlen = sizeof(node << 2155 .mode = 0644, << 2156 .proc_handler = proc_dointv << 2157 .extra1 = SYSCTL_ZERO << 2158 }, << 2159 #endif << 2160 #ifdef CONFIG_SMP << 2161 { << 2162 .procname = "stat_inter << 2163 .data = &sysctl_sta << 2164 .maxlen = sizeof(sysc << 2165 .mode = 0644, << 2166 .proc_handler = proc_dointv << 2167 }, << 2168 { << 2169 .procname = "stat_refre << 2170 .data = NULL, << 2171 .maxlen = 0, << 2172 .mode = 0600, << 2173 .proc_handler = vmstat_refr << 2174 }, << 2175 #endif << 2176 #ifdef CONFIG_MMU << 2177 { << 2178 .procname = "mmap_min_a << 2179 .data = &dac_mmap_m << 2180 .maxlen = sizeof(unsi << 2181 .mode = 0644, << 2182 .proc_handler = mmap_min_ad << 2183 }, << 2184 #endif << 2185 #if (defined(CONFIG_X86_32) && !defined(CONFI << 2186 (defined(CONFIG_SUPERH) && defined(CONFIG_ << 2187 { << 2188 .procname = "vdso_enabl << 2189 #ifdef CONFIG_X86_32 << 2190 .data = &vdso32_ena << 2191 .maxlen = sizeof(vdso << 2192 #else << 2193 .data = &vdso_enabl << 2194 .maxlen = sizeof(vdso << 2195 #endif << 2196 .mode = 0644, << 2197 .proc_handler = proc_dointv << 2198 .extra1 = SYSCTL_ZERO << 2199 }, << 2200 #endif << 2201 { << 2202 .procname = "user_reser << 2203 .data = &sysctl_use << 2204 .maxlen = sizeof(sysc << 2205 .mode = 0644, << 2206 .proc_handler = proc_doulon << 2207 }, << 2208 { << 2209 .procname = "admin_rese << 2210 .data = &sysctl_adm << 2211 .maxlen = sizeof(sysc << 2212 .mode = 0644, << 2213 .proc_handler = proc_doulon << 2214 }, << 2215 #ifdef CONFIG_HAVE_ARCH_MMAP_RND_BITS << 2216 { << 2217 .procname = "mmap_rnd_b << 2218 .data = &mmap_rnd_b << 2219 .maxlen = sizeof(mmap << 2220 .mode = 0600, << 2221 .proc_handler = proc_dointv << 2222 .extra1 = (void *)&mm << 2223 .extra2 = (void *)&mm << 2224 }, << 2225 #endif << 2226 #ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS << 2227 { << 2228 .procname = "mmap_rnd_c << 2229 .data = &mmap_rnd_c << 2230 .maxlen = sizeof(mmap << 2231 .mode = 0600, << 2232 .proc_handler = proc_dointv << 2233 .extra1 = (void *)&mm << 2234 .extra2 = (void *)&mm << 2235 }, << 2236 #endif << 2237 }; << 2238 << 2239 int __init sysctl_init_bases(void) << 2240 { << 2241 register_sysctl_init("kernel", kern_t << 2242 register_sysctl_init("vm", vm_table); << 2243 << 2244 return 0; << 2245 } 1622 } >> 1623 2246 #endif /* CONFIG_SYSCTL */ 1624 #endif /* CONFIG_SYSCTL */ 2247 /* << 2248 * No sense putting this after each symbol de << 2249 * exception granted :-) << 2250 */ << 2251 EXPORT_SYMBOL(proc_dobool); << 2252 EXPORT_SYMBOL(proc_dointvec); << 2253 EXPORT_SYMBOL(proc_douintvec); << 2254 EXPORT_SYMBOL(proc_dointvec_jiffies); << 2255 EXPORT_SYMBOL(proc_dointvec_minmax); << 2256 EXPORT_SYMBOL_GPL(proc_douintvec_minmax); << 2257 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); << 2258 EXPORT_SYMBOL(proc_dointvec_ms_jiffies); << 2259 EXPORT_SYMBOL(proc_dostring); << 2260 EXPORT_SYMBOL(proc_doulongvec_minmax); << 2261 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minm << 2262 EXPORT_SYMBOL(proc_do_large_bitmap); << 2263 1625
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.