1 /* $NetBSD: linux_sysctl.c,v 1.7 2003/01/18 21:21:37 thorpej 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.7 2003/01/18 21:21:37 thorpej 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/sa.h> 55 #include <sys/syscallargs.h> 56 57 #include <compat/linux/common/linux_types.h> 58 #include <compat/linux/common/linux_signal.h> 59 60 #include <compat/linux/linux_syscallargs.h> 61 #include <compat/linux/common/linux_sysctl.h> 62 #include <compat/linux/common/linux_exec.h> 63 64 int linux_kern_sysctl(int *, u_int, void *, size_t *, void *, size_t, 65 struct proc *); 66 int linux_vm_sysctl(int *, u_int, void *, size_t *, void *, size_t, 67 struct proc *); 68 int linux_net_sysctl(int *, u_int, void *, size_t *, void *, size_t, 69 struct proc *); 70 int linux_proc_sysctl(int *, u_int, void *, size_t *, void *, size_t, 71 struct proc *); 72 int linux_fs_sysctl(int *, u_int, void *, size_t *, void *, size_t, 73 struct proc *); 74 #ifdef DEBUG 75 int linux_debug_sysctl(int *, u_int, void *, size_t *, void *, size_t, 76 struct proc *); 77 #endif 78 int linux_dev_sysctl(int *, u_int, void *, size_t *, void *, size_t, 79 struct proc *); 80 int linux_bus_sysctl(int *, u_int, void *, size_t *, void *, size_t, 81 struct proc *); 82 83 int 84 linux_sys___sysctl(struct lwp *l, void *v, register_t *retval) 85 { 86 struct linux_sys___sysctl_args /* { 87 syscallarg(struct linux___sysctl *) lsp; 88 } */ *uap = v; 89 struct proc *p = l->l_proc; 90 struct linux___sysctl ls; 91 int error; 92 size_t savelen = 0, oldlen = 0; 93 sysctlfn *fn; 94 int name[CTL_MAXNAME]; 95 size_t *oldlenp; 96 97 98 if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls))) 99 return error; 100 /* 101 * all top-level sysctl names are non-terminal 102 */ 103 if (ls.nlen > CTL_MAXNAME || ls.nlen < 2) 104 return (EINVAL); 105 error = copyin(ls.name, &name, ls.nlen * sizeof(int)); 106 if (error) 107 return (error); 108 109 /* 110 * For all but CTL_PROC, must be root to change a value. 111 * For CTL_PROC, must be root, or owner of the proc (and not suid), 112 * this is checked in proc_sysctl() (once we know the targer proc). 113 */ 114 if (ls.newval != NULL && name[0] != CTL_PROC && 115 (error = suser(p->p_ucred, &p->p_acflag))) 116 return error; 117 118 switch (name[0]) { 119 case LINUX_CTL_KERN: 120 fn = linux_kern_sysctl; 121 break; 122 case LINUX_CTL_VM: 123 fn = linux_vm_sysctl; 124 break; 125 case LINUX_CTL_NET: 126 fn = linux_net_sysctl; 127 break; 128 case LINUX_CTL_PROC: 129 fn = linux_proc_sysctl; 130 break; 131 case LINUX_CTL_FS: 132 fn = linux_fs_sysctl; 133 break; 134 #ifdef DEBUG 135 case LINUX_CTL_DEBUG: 136 fn = linux_debug_sysctl; 137 break; 138 #endif 139 case LINUX_CTL_DEV: 140 fn = linux_dev_sysctl; 141 break; 142 case LINUX_CTL_BUS: 143 fn = linux_bus_sysctl; 144 break; 145 default: 146 return (EOPNOTSUPP); 147 } 148 149 /* 150 * XXX Hey, we wire `oldval', but what about `newval'? 151 */ 152 oldlenp = ls.oldlenp; 153 if (oldlenp) { 154 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 155 return (error); 156 oldlenp = &oldlen; 157 } 158 if (ls.oldval != NULL) { 159 error = uvm_vslock(p, ls.oldval, oldlen, 160 VM_PROT_READ|VM_PROT_WRITE); 161 savelen = oldlen; 162 } 163 error = (*fn)(name + 1, ls.nlen - 1, ls.oldval, oldlenp, ls.newval, 164 ls.newlen, p); 165 if (ls.oldval != NULL) 166 uvm_vsunlock(p, ls.oldval, savelen); 167 if (error) 168 return (error); 169 if (ls.oldlenp) 170 error = copyout(&oldlen, ls.oldlenp, sizeof(oldlen)); 171 return (error); 172 } 173 174 char linux_sysname[128] = "Linux"; 175 #if defined(__i386__) || defined(__powerpc__) 176 char linux_release[128] = "2.4.18"; 177 char linux_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002"; 178 #else 179 char linux_release[128] = "2.0.38"; 180 char linux_version[128] = "#0 Sun Nov 11 11:11:11 MET 2000"; 181 #endif 182 183 /* 184 * kernel related system variables. 185 */ 186 int 187 linux_kern_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 188 void *newp, size_t newlen, struct proc *p) 189 { 190 /* 191 * Note that we allow writing into this, so that userland 192 * programs can setup things as they see fit. This is suboptimal. 193 */ 194 switch (name[0]) { 195 case LINUX_KERN_OSTYPE: 196 return sysctl_string(oldp, oldlenp, newp, newlen, 197 linux_sysname, sizeof(linux_sysname)); 198 case LINUX_KERN_OSRELEASE: 199 return sysctl_string(oldp, oldlenp, newp, newlen, 200 linux_release, sizeof(linux_release)); 201 case LINUX_KERN_VERSION: 202 return sysctl_string(oldp, oldlenp, newp, newlen, 203 linux_version, sizeof(linux_version)); 204 default: 205 return EOPNOTSUPP; 206 } 207 } 208 209 /* 210 * kernel related system variables. 211 */ 212 int 213 linux_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 214 void *newp, size_t newlen, struct proc *p) 215 { 216 if (nlen != 2 || name[0] != EMUL_LINUX_KERN) 217 return EOPNOTSUPP; 218 219 /* 220 * Note that we allow writing into this, so that userland 221 * programs can setup things as they see fit. This is suboptimal. 222 */ 223 switch (name[1]) { 224 case EMUL_LINUX_KERN_OSTYPE: 225 return sysctl_string(oldp, oldlenp, newp, newlen, 226 linux_sysname, sizeof(linux_sysname)); 227 case EMUL_LINUX_KERN_OSRELEASE: 228 return sysctl_string(oldp, oldlenp, newp, newlen, 229 linux_release, sizeof(linux_release)); 230 case EMUL_LINUX_KERN_VERSION: 231 return sysctl_string(oldp, oldlenp, newp, newlen, 232 linux_version, sizeof(linux_version)); 233 default: 234 return EOPNOTSUPP; 235 } 236 } 237 238 /* 239 * hardware related system variables. 240 */ 241 int 242 linux_vm_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 243 void *newp, size_t newlen, struct proc *p) 244 { 245 return (EOPNOTSUPP); 246 } 247 248 int 249 linux_net_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 250 void *newp, size_t newlen, struct proc *p) 251 { 252 return (EOPNOTSUPP); 253 } 254 255 int 256 linux_proc_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 257 void *newp, size_t newlen, struct proc *p) 258 { 259 return (EOPNOTSUPP); 260 } 261 262 int 263 linux_fs_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 264 void *newp, size_t newlen, struct proc *p) 265 { 266 return (EOPNOTSUPP); 267 } 268 #ifdef DEBUG 269 int 270 linux_debug_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 271 void *newp, size_t newlen, struct proc *p) 272 { 273 return (EOPNOTSUPP); 274 } 275 #endif /* DEBUG */ 276 277 int 278 linux_dev_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 279 void *newp, size_t newlen, struct proc *p) 280 { 281 return (EOPNOTSUPP); 282 } 283 284 int 285 linux_bus_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp, 286 void *newp, size_t newlen, struct proc *p) 287 { 288 return (EOPNOTSUPP); 289 } 290