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