1 /* $NetBSD: linux_sysctl.c,v 1.5 2002/04/04 09:32:11 tron Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 39 */ 40 41 /* 42 * sysctl system call. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.5 2002/04/04 09:32:11 tron Exp $"); 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/errno.h> 51 #include <sys/proc.h> 52 #include <sys/mount.h> 53 #include <sys/sysctl.h> 54 #include <sys/syscallargs.h> 55 56 #include <compat/linux/common/linux_types.h> 57 #include <compat/linux/common/linux_signal.h> 58 59 #include <compat/linux/linux_syscallargs.h> 60 #include <compat/linux/common/linux_sysctl.h> 61 #include <compat/linux/common/linux_exec.h> 62 63 int linux_kern_sysctl(int *, u_int, void *, size_t *, void *, size_t, 64 struct proc *); 65 int linux_vm_sysctl(int *, u_int, void *, size_t *, void *, size_t, 66 struct proc *); 67 int linux_net_sysctl(int *, u_int, void *, size_t *, void *, size_t, 68 struct proc *); 69 int linux_proc_sysctl(int *, u_int, void *, size_t *, void *, size_t, 70 struct proc *); 71 int linux_fs_sysctl(int *, u_int, void *, size_t *, void *, size_t, 72 struct proc *); 73 #ifdef DEBUG 74 int linux_debug_sysctl(int *, u_int, void *, size_t *, void *, size_t, 75 struct proc *); 76 #endif 77 int linux_dev_sysctl(int *, u_int, void *, size_t *, void *, size_t, 78 struct proc *); 79 int linux_bus_sysctl(int *, u_int, void *, size_t *, void *, size_t, 80 struct proc *); 81 82 int 83 linux_sys___sysctl(struct proc *p, void *v, register_t *retval) 84 { 85 struct linux_sys___sysctl_args /* { 86 syscallarg(struct linux___sysctl *) lsp; 87 } */ *uap = v; 88 struct linux___sysctl ls; 89 int error; 90 size_t savelen = 0, oldlen = 0; 91 sysctlfn *fn; 92 int name[CTL_MAXNAME]; 93 size_t *oldlenp; 94 95 96 if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls))) 97 return error; 98 /* 99 * all top-level sysctl names are non-terminal 100 */ 101 if (ls.nlen > CTL_MAXNAME || ls.nlen < 2) 102 return (EINVAL); 103 error = copyin(ls.name, &name, ls.nlen * sizeof(int)); 104 if (error) 105 return (error); 106 107 /* 108 * For all but CTL_PROC, must be root to change a value. 109 * For CTL_PROC, must be root, or owner of the proc (and not suid), 110 * this is checked in proc_sysctl() (once we know the targer proc). 111 */ 112 if (ls.newval != NULL && name[0] != CTL_PROC && 113 (error = suser(p->p_ucred, &p->p_acflag))) 114 return error; 115 116 switch (name[0]) { 117 case LINUX_CTL_KERN: 118 fn = linux_kern_sysctl; 119 break; 120 case LINUX_CTL_VM: 121 fn = linux_vm_sysctl; 122 break; 123 case LINUX_CTL_NET: 124 fn = linux_net_sysctl; 125 break; 126 case LINUX_CTL_PROC: 127 fn = linux_proc_sysctl; 128 break; 129 case LINUX_CTL_FS: 130 fn = linux_fs_sysctl; 131 break; 132 #ifdef DEBUG 133 case LINUX_CTL_DEBUG: 134 fn = linux_debug_sysctl; 135 break; 136 #endif 137 case LINUX_CTL_DEV: 138 fn = linux_dev_sysctl; 139 break; 140 case LINUX_CTL_BUS: 141 fn = linux_bus_sysctl; 142 break; 143 default: 144 return (EOPNOTSUPP); 145 } 146 147 /* 148 * XXX Hey, we wire `oldval', but what about `newval'? 149 */ 150 oldlenp = ls.oldlenp; 151 if (oldlenp) { 152 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 153 return (error); 154 oldlenp = &oldlen; 155 } 156 if (ls.oldval != NULL) { 157 error = uvm_vslock(p, ls.oldval, oldlen, 158 VM_PROT_READ|VM_PROT_WRITE); 159 savelen = oldlen; 160 } 161 error = (*fn)(name + 1, ls.nlen - 1, ls.oldval, oldlenp, ls.newval, 162 ls.newlen, p); 163 if (ls.oldval != NULL) 164 uvm_vsunlock(p, ls.oldval, savelen); 165 if (error) 166 return (error); 167 if (ls.oldlenp) 168 error = copyout(&oldlen, ls.oldlenp, sizeof(oldlen)); 169 return (error); 170 } 171 172 char linux_sysname[128] = "Linux"; 173 #ifdef __i386__ 174 char linux_release[128] = "2.4.18"; 175 char linux_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002"; 176 #else 177 char linux_release[128] = "2.0.38"; 178 char linux_version[128] = "#0 Sun Nov 11 11:11:11 MET 2000"; 179 #endif 180 181 /* 182 * kernel related system variables. 183 */ 184 int 185 linux_kern_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 186 void *newp, size_t newlen, struct proc *p) 187 { 188 /* 189 * Note that we allow writing into this, so that userland 190 * programs can setup things as they see fit. This is suboptimal. 191 */ 192 switch (name[0]) { 193 case LINUX_KERN_OSTYPE: 194 return sysctl_string(oldp, oldlenp, newp, newlen, 195 linux_sysname, sizeof(linux_sysname)); 196 case LINUX_KERN_OSRELEASE: 197 return sysctl_string(oldp, oldlenp, newp, newlen, 198 linux_release, sizeof(linux_release)); 199 case LINUX_KERN_VERSION: 200 return sysctl_string(oldp, oldlenp, newp, newlen, 201 linux_version, sizeof(linux_version)); 202 default: 203 return EOPNOTSUPP; 204 } 205 } 206 207 /* 208 * kernel related system variables. 209 */ 210 int 211 linux_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 212 void *newp, size_t newlen, struct proc *p) 213 { 214 if (nlen != 2 || name[0] != EMUL_LINUX_KERN) 215 return EOPNOTSUPP; 216 217 /* 218 * Note that we allow writing into this, so that userland 219 * programs can setup things as they see fit. This is suboptimal. 220 */ 221 switch (name[1]) { 222 case EMUL_LINUX_KERN_OSTYPE: 223 return sysctl_string(oldp, oldlenp, newp, newlen, 224 linux_sysname, sizeof(linux_sysname)); 225 case EMUL_LINUX_KERN_OSRELEASE: 226 return sysctl_string(oldp, oldlenp, newp, newlen, 227 linux_release, sizeof(linux_release)); 228 case EMUL_LINUX_KERN_VERSION: 229 return sysctl_string(oldp, oldlenp, newp, newlen, 230 linux_version, sizeof(linux_version)); 231 default: 232 return EOPNOTSUPP; 233 } 234 } 235 236 /* 237 * hardware related system variables. 238 */ 239 int 240 linux_vm_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 241 void *newp, size_t newlen, struct proc *p) 242 { 243 return (EOPNOTSUPP); 244 } 245 246 int 247 linux_net_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 248 void *newp, size_t newlen, struct proc *p) 249 { 250 return (EOPNOTSUPP); 251 } 252 253 int 254 linux_proc_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 255 void *newp, size_t newlen, struct proc *p) 256 { 257 return (EOPNOTSUPP); 258 } 259 260 int 261 linux_fs_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 262 void *newp, size_t newlen, struct proc *p) 263 { 264 return (EOPNOTSUPP); 265 } 266 #ifdef DEBUG 267 int 268 linux_debug_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 269 void *newp, size_t newlen, struct proc *p) 270 { 271 return (EOPNOTSUPP); 272 } 273 #endif /* DEBUG */ 274 275 int 276 linux_dev_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 277 void *newp, size_t newlen, struct proc *p) 278 { 279 return (EOPNOTSUPP); 280 } 281 282 int 283 linux_bus_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 284 void *newp, size_t newlen, struct proc *p) 285 { 286 return (EOPNOTSUPP); 287 } 288