xref: /netbsd-src/sys/compat/netbsd32/netbsd32_sysctl.c (revision da5f4674a3fc214be3572d358b66af40ab9401e7)
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