1 /* $NetBSD: netbsd32_sysctl.c,v 1.6 2002/06/14 18:28:19 eeh Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_sysctl.c,v 1.6 2002/06/14 18:28:19 eeh Exp $"); 33 34 #if defined(_KERNEL_OPT) 35 #include "opt_ddb.h" 36 #endif 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/mount.h> 43 #include <sys/stat.h> 44 #include <sys/time.h> 45 #include <sys/vnode.h> 46 #include <sys/syscallargs.h> 47 #include <sys/proc.h> 48 #define __SYSCTL_PRIVATE 49 #include <sys/sysctl.h> 50 51 #include <uvm/uvm_extern.h> 52 53 #include <compat/netbsd32/netbsd32.h> 54 #include <compat/netbsd32/netbsd32_syscall.h> 55 #include <compat/netbsd32/netbsd32_syscallargs.h> 56 #include <compat/netbsd32/netbsd32_conv.h> 57 58 #if defined(DDB) 59 #include <ddb/ddbvar.h> 60 #endif 61 62 int uvm_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 63 int kern_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 64 int hw_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 65 66 /* 67 * uvm_sysctl32: sysctl hook into UVM system, handling special 32-bit 68 * sensitive calls. 69 */ 70 int 71 uvm_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, p) 72 int *name; 73 u_int namelen; 74 void *oldp; 75 size_t *oldlenp; 76 void *newp; 77 size_t newlen; 78 struct proc *p; 79 { 80 struct netbsd32_loadavg av32; 81 82 /* all sysctl names at this level are terminal */ 83 if (namelen != 1) 84 return (ENOTDIR); /* overloaded */ 85 86 switch (name[0]) { 87 case VM_LOADAVG: 88 netbsd32_from_loadavg(&av32, &averunnable); 89 return (sysctl_rdstruct(oldp, oldlenp, newp, &av32, 90 sizeof(av32))); 91 92 default: 93 return (EOPNOTSUPP); 94 } 95 /* NOTREACHED */ 96 } 97 98 /* 99 * kern_sysctl32: sysctl hook into KERN system, handling special 32-bit 100 * sensitive calls. 101 */ 102 int 103 kern_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, p) 104 int *name; 105 u_int namelen; 106 void *oldp; 107 size_t *oldlenp; 108 void *newp; 109 size_t newlen; 110 struct proc *p; 111 { 112 struct netbsd32_timeval bt32; 113 114 /* All sysctl names at this level, except for a few, are terminal. */ 115 switch (name[0]) { 116 #if 0 117 case KERN_PROC: 118 case KERN_PROC2: 119 case KERN_PROF: 120 case KERN_MBUF: 121 case KERN_PROC_ARGS: 122 case KERN_SYSVIPC_INFO: 123 /* Not terminal. */ 124 break; 125 #endif 126 default: 127 if (namelen != 1) 128 return (ENOTDIR); /* overloaded */ 129 } 130 131 switch (name[0]) { 132 case KERN_BOOTTIME: 133 netbsd32_from_timeval(&boottime, &bt32); 134 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt32, 135 sizeof(struct netbsd32_timeval))); 136 137 default: 138 return (EOPNOTSUPP); 139 } 140 /* NOTREACHED */ 141 } 142 143 /* 144 * hardware related system variables. 145 */ 146 int 147 hw_sysctl32(int *name, u_int namelen, void *oldp, size_t *oldlenp, 148 void *newp, size_t newlen, struct proc *p) 149 { 150 extern char machine_arch32[]; 151 152 switch (name[0]) { 153 case HW_MACHINE_ARCH: 154 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch32)); 155 default: 156 return (EOPNOTSUPP); 157 } 158 /* NOTREACHED */ 159 } 160 161 int 162 netbsd32___sysctl(p, v, retval) 163 struct proc *p; 164 void *v; 165 register_t *retval; 166 { 167 struct netbsd32___sysctl_args /* { 168 syscallarg(netbsd32_intp) name; 169 syscallarg(u_int) namelen; 170 syscallarg(netbsd32_voidp) old; 171 syscallarg(netbsd32_size_tp) oldlenp; 172 syscallarg(netbsd32_voidp) new; 173 syscallarg(netbsd32_size_t) newlen; 174 } */ *uap = v; 175 int error; 176 netbsd32_size_t savelen = 0; 177 size_t oldlen = 0; 178 sysctlfn *fn; 179 int name[CTL_MAXNAME]; 180 181 /* 182 * Some of these sysctl functions do their own copyin/copyout. 183 * We need to disable or emulate the ones that need their 184 * arguments converted. 185 */ 186 187 if (SCARG(uap, new) != NULL && 188 (error = suser(p->p_ucred, &p->p_acflag))) 189 return (error); 190 /* 191 * all top-level sysctl names are non-terminal 192 */ 193 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 194 return (EINVAL); 195 error = copyin((caddr_t)(u_long)SCARG(uap, name), &name, 196 SCARG(uap, namelen) * sizeof(int)); 197 if (error) 198 return (error); 199 200 switch (name[0]) { 201 case CTL_KERN: 202 switch (name[1]) { 203 #if 0 204 case KERN_FILE: 205 case KERN_NTPTIME: 206 case KERN_SYSVIPC_INFO: 207 #endif 208 case KERN_BOOTTIME: 209 fn = kern_sysctl32; 210 break; 211 default: 212 fn = kern_sysctl; 213 break; 214 } 215 break; 216 case CTL_HW: 217 switch (name[1]) { 218 case HW_MACHINE_ARCH: 219 fn = hw_sysctl32; 220 break; 221 default: 222 fn = hw_sysctl; 223 break; 224 } 225 break; 226 case CTL_VM: 227 switch (name[1]) { 228 case VM_LOADAVG: 229 fn = uvm_sysctl32; /* need to convert a `long' */ 230 break; 231 default: 232 fn = uvm_sysctl; 233 break; 234 } 235 break; 236 case CTL_NET: 237 fn = net_sysctl; 238 break; 239 case CTL_VFS: 240 fn = vfs_sysctl; 241 break; 242 case CTL_MACHDEP: 243 fn = cpu_sysctl; 244 break; 245 #ifdef DEBUG 246 case CTL_DEBUG: 247 fn = debug_sysctl; 248 break; 249 #endif 250 #ifdef DDB 251 case CTL_DDB: 252 fn = ddb_sysctl; 253 break; 254 #endif 255 case CTL_PROC: 256 fn = proc_sysctl; 257 break; 258 default: 259 return (EOPNOTSUPP); 260 } 261 262 /* 263 * XXX Hey, we wire `old', but what about `new'? 264 */ 265 266 if (SCARG(uap, oldlenp) && 267 (error = copyin((caddr_t)(u_long)SCARG(uap, oldlenp), &savelen, 268 sizeof(savelen)))) 269 return (error); 270 if (SCARG(uap, old) != NULL) { 271 error = lockmgr(&sysctl_memlock, LK_EXCLUSIVE, NULL); 272 if (error) 273 return (error); 274 error = uvm_vslock(p, (void *)(vaddr_t)SCARG(uap, old), savelen, 275 VM_PROT_WRITE); 276 if (error) { 277 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 278 return error; 279 } 280 oldlen = savelen; 281 } 282 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, 283 (void *)(u_long)SCARG(uap, old), &oldlen, 284 (void *)(u_long)SCARG(uap, new), SCARG(uap, newlen), p); 285 if (SCARG(uap, old) != NULL) { 286 uvm_vsunlock(p, (void *)(u_long)SCARG(uap, old), savelen); 287 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 288 } 289 savelen = oldlen; 290 if (error) 291 return (error); 292 if (SCARG(uap, oldlenp)) 293 error = copyout(&savelen, 294 (caddr_t)(u_long)SCARG(uap, oldlenp), sizeof(savelen)); 295 return (error); 296 } 297