1 /* $NetBSD: netbsd32_sysctl.c,v 1.10 2003/06/29 22:29:40 fvdl 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.10 2003/06/29 22:29:40 fvdl 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/sa.h> 47 #include <sys/syscallargs.h> 48 #include <sys/proc.h> 49 #define __SYSCTL_PRIVATE 50 #include <sys/sysctl.h> 51 52 #include <uvm/uvm_extern.h> 53 54 #include <compat/netbsd32/netbsd32.h> 55 #include <compat/netbsd32/netbsd32_syscall.h> 56 #include <compat/netbsd32/netbsd32_syscallargs.h> 57 #include <compat/netbsd32/netbsd32_conv.h> 58 59 #if defined(DDB) 60 #include <ddb/ddbvar.h> 61 #endif 62 63 int uvm_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 64 int kern_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 65 int hw_sysctl32(int *, u_int, void *, size_t *, void *, size_t, struct proc *); 66 67 /* 68 * uvm_sysctl32: sysctl hook into UVM system, handling special 32-bit 69 * sensitive calls. 70 */ 71 int 72 uvm_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, p) 73 int *name; 74 u_int namelen; 75 void *oldp; 76 size_t *oldlenp; 77 void *newp; 78 size_t newlen; 79 struct proc *p; 80 { 81 struct netbsd32_loadavg av32; 82 83 /* all sysctl names at this level are terminal */ 84 if (namelen != 1) 85 return (ENOTDIR); /* overloaded */ 86 87 switch (name[0]) { 88 case VM_LOADAVG: 89 netbsd32_from_loadavg(&av32, &averunnable); 90 return (sysctl_rdstruct(oldp, oldlenp, newp, &av32, 91 sizeof(av32))); 92 93 default: 94 return (EOPNOTSUPP); 95 } 96 /* NOTREACHED */ 97 } 98 99 /* 100 * kern_sysctl32: sysctl hook into KERN system, handling special 32-bit 101 * sensitive calls. 102 */ 103 int 104 kern_sysctl32(name, namelen, oldp, oldlenp, newp, newlen, p) 105 int *name; 106 u_int namelen; 107 void *oldp; 108 size_t *oldlenp; 109 void *newp; 110 size_t newlen; 111 struct proc *p; 112 { 113 struct netbsd32_timeval bt32; 114 115 /* All sysctl names at this level, except for a few, are terminal. */ 116 switch (name[0]) { 117 #if 0 118 case KERN_PROC: 119 case KERN_PROC2: 120 case KERN_PROF: 121 case KERN_MBUF: 122 case KERN_PROC_ARGS: 123 case KERN_SYSVIPC_INFO: 124 /* Not terminal. */ 125 break; 126 #endif 127 default: 128 if (namelen != 1) 129 return (ENOTDIR); /* overloaded */ 130 } 131 132 switch (name[0]) { 133 case KERN_BOOTTIME: 134 netbsd32_from_timeval(&boottime, &bt32); 135 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt32, 136 sizeof(struct netbsd32_timeval))); 137 138 default: 139 return (EOPNOTSUPP); 140 } 141 /* NOTREACHED */ 142 } 143 144 /* 145 * hardware related system variables. 146 */ 147 int 148 hw_sysctl32(int *name, u_int namelen, void *oldp, size_t *oldlenp, 149 void *newp, size_t newlen, struct proc *p) 150 { 151 extern char machine_arch32[]; 152 153 switch (name[0]) { 154 case HW_MACHINE_ARCH: 155 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch32)); 156 default: 157 return (EOPNOTSUPP); 158 } 159 /* NOTREACHED */ 160 } 161 162 int 163 netbsd32___sysctl(l, v, retval) 164 struct lwp *l; 165 void *v; 166 register_t *retval; 167 { 168 struct netbsd32___sysctl_args /* { 169 syscallarg(netbsd32_intp) name; 170 syscallarg(u_int) namelen; 171 syscallarg(netbsd32_voidp) old; 172 syscallarg(netbsd32_size_tp) oldlenp; 173 syscallarg(netbsd32_voidp) new; 174 syscallarg(netbsd32_size_t) newlen; 175 } */ *uap = v; 176 int error; 177 netbsd32_size_t savelen = 0; 178 size_t oldlen = 0; 179 sysctlfn *fn; 180 struct proc *p = l->l_proc; 181 int name[CTL_MAXNAME]; 182 183 /* 184 * Some of these sysctl functions do their own copyin/copyout. 185 * We need to disable or emulate the ones that need their 186 * arguments converted. 187 */ 188 189 if (SCARG(uap, new) != NULL && 190 (error = suser(p->p_ucred, &p->p_acflag))) 191 return (error); 192 /* 193 * all top-level sysctl names are non-terminal 194 */ 195 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 196 return (EINVAL); 197 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, name)), &name, 198 SCARG(uap, namelen) * sizeof(int)); 199 if (error) 200 return (error); 201 202 switch (name[0]) { 203 case CTL_KERN: 204 switch (name[1]) { 205 #if 0 206 case KERN_FILE: 207 case KERN_NTPTIME: 208 case KERN_SYSVIPC_INFO: 209 #endif 210 case KERN_BOOTTIME: 211 fn = kern_sysctl32; 212 break; 213 default: 214 fn = kern_sysctl; 215 break; 216 } 217 break; 218 case CTL_HW: 219 switch (name[1]) { 220 case HW_MACHINE_ARCH: 221 fn = hw_sysctl32; 222 break; 223 default: 224 fn = hw_sysctl; 225 break; 226 } 227 break; 228 case CTL_VM: 229 switch (name[1]) { 230 case VM_LOADAVG: 231 fn = uvm_sysctl32; /* need to convert a `long' */ 232 break; 233 default: 234 fn = uvm_sysctl; 235 break; 236 } 237 break; 238 case CTL_NET: 239 fn = net_sysctl; 240 break; 241 case CTL_VFS: 242 fn = vfs_sysctl; 243 break; 244 case CTL_MACHDEP: 245 fn = cpu_sysctl; 246 break; 247 #ifdef DEBUG 248 case CTL_DEBUG: 249 fn = debug_sysctl; 250 break; 251 #endif 252 #ifdef DDB 253 case CTL_DDB: 254 fn = ddb_sysctl; 255 break; 256 #endif 257 case CTL_PROC: 258 fn = proc_sysctl; 259 break; 260 default: 261 return (EOPNOTSUPP); 262 } 263 264 /* 265 * XXX Hey, we wire `old', but what about `new'? 266 */ 267 268 if (SCARG(uap, oldlenp) && 269 (error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, oldlenp)), 270 &savelen, sizeof(savelen)))) 271 return (error); 272 if (SCARG(uap, old) != NULL) { 273 error = lockmgr(&sysctl_memlock, LK_EXCLUSIVE, NULL); 274 if (error) 275 return (error); 276 error = uvm_vslock(p, (void *)(vaddr_t)SCARG(uap, old), savelen, 277 VM_PROT_WRITE); 278 if (error) { 279 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 280 return error; 281 } 282 oldlen = savelen; 283 } 284 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, 285 (void *)NETBSD32PTR64(SCARG(uap, old)), &oldlen, 286 (void *)NETBSD32PTR64(SCARG(uap, new)), SCARG(uap, newlen), p); 287 if (SCARG(uap, old) != NULL) { 288 uvm_vsunlock(p, (void *)NETBSD32PTR64(SCARG(uap, old)), 289 savelen); 290 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 291 } 292 savelen = oldlen; 293 if (error) 294 return (error); 295 if (SCARG(uap, oldlenp)) 296 error = copyout(&savelen, 297 (caddr_t)NETBSD32PTR64(SCARG(uap, oldlenp)), 298 sizeof(savelen)); 299 return (error); 300 } 301