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