xref: /netbsd-src/sys/compat/linux/common/linux_sysctl.c (revision 73704c4ce4ee2a60eb617e693ce7e9f03902613e)
1 /*	$NetBSD: linux_sysctl.c,v 1.10 2003/08/07 16:30:45 agc Exp $	*/
2 
3 /*-
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Mike Karels at Berkeley Software Design, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)kern_sysctl.c	8.9 (Berkeley) 5/20/95
35  */
36 
37 /*
38  * sysctl system call.
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.10 2003/08/07 16:30:45 agc Exp $");
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/proc.h>
48 #include <sys/mount.h>
49 #include <sys/sysctl.h>
50 #include <sys/sa.h>
51 #include <sys/syscallargs.h>
52 
53 #include <compat/linux/common/linux_types.h>
54 #include <compat/linux/common/linux_signal.h>
55 
56 #include <compat/linux/linux_syscallargs.h>
57 #include <compat/linux/common/linux_sysctl.h>
58 #include <compat/linux/common/linux_exec.h>
59 
60 int linux_kern_sysctl(int *, u_int, void *, size_t *, void *, size_t,
61     struct proc *);
62 int linux_vm_sysctl(int *, u_int, void *, size_t *, void *, size_t,
63     struct proc *);
64 int linux_net_sysctl(int *, u_int, void *, size_t *, void *, size_t,
65     struct proc *);
66 int linux_proc_sysctl(int *, u_int, void *, size_t *, void *, size_t,
67     struct proc *);
68 int linux_fs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
69     struct proc *);
70 #ifdef DEBUG
71 int linux_debug_sysctl(int *, u_int, void *, size_t *, void *, size_t,
72     struct proc *);
73 #endif
74 int linux_dev_sysctl(int *, u_int, void *, size_t *, void *, size_t,
75     struct proc *);
76 int linux_bus_sysctl(int *, u_int, void *, size_t *, void *, size_t,
77     struct proc *);
78 
79 int
80 linux_sys___sysctl(struct lwp *l, void *v, register_t *retval)
81 {
82 	struct linux_sys___sysctl_args /* {
83 		syscallarg(struct linux___sysctl *) lsp;
84 	} */ *uap = v;
85 	struct proc *p = l->l_proc;
86 	struct linux___sysctl ls;
87 	int error;
88 	size_t savelen = 0, oldlen = 0;
89 	sysctlfn *fn;
90 	int name[CTL_MAXNAME];
91 	size_t *oldlenp;
92 
93 
94 	if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls)))
95 		return error;
96 	/*
97 	 * all top-level sysctl names are non-terminal
98 	 */
99 	if (ls.nlen > CTL_MAXNAME || ls.nlen < 2)
100 		return (EINVAL);
101 	error = copyin(ls.name, &name, ls.nlen * sizeof(int));
102 	if (error)
103 		return (error);
104 
105 	/*
106 	 * For all but CTL_PROC, must be root to change a value.
107 	 * For CTL_PROC, must be root, or owner of the proc (and not suid),
108 	 * this is checked in proc_sysctl() (once we know the targer proc).
109 	 */
110 	if (ls.newval != NULL && name[0] != CTL_PROC &&
111 		    (error = suser(p->p_ucred, &p->p_acflag)))
112 			return error;
113 
114 	switch (name[0]) {
115 	case LINUX_CTL_KERN:
116 		fn = linux_kern_sysctl;
117 		break;
118 	case LINUX_CTL_VM:
119 		fn = linux_vm_sysctl;
120 		break;
121 	case LINUX_CTL_NET:
122 		fn = linux_net_sysctl;
123 		break;
124 	case LINUX_CTL_PROC:
125 		fn = linux_proc_sysctl;
126 		break;
127 	case LINUX_CTL_FS:
128 		fn = linux_fs_sysctl;
129 		break;
130 #ifdef DEBUG
131 	case LINUX_CTL_DEBUG:
132 		fn = linux_debug_sysctl;
133 		break;
134 #endif
135 	case LINUX_CTL_DEV:
136 		fn = linux_dev_sysctl;
137 		break;
138 	case LINUX_CTL_BUS:
139 		fn = linux_bus_sysctl;
140 		break;
141 	default:
142 		return (EOPNOTSUPP);
143 	}
144 
145 	/*
146 	 * XXX Hey, we wire `oldval', but what about `newval'?
147 	 */
148 	oldlenp = ls.oldlenp;
149 	if (oldlenp) {
150 		if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen))))
151 			return (error);
152 		oldlenp = &oldlen;
153 	}
154 	if (ls.oldval != NULL) {
155 		error = uvm_vslock(p, ls.oldval, oldlen,
156 		    VM_PROT_READ|VM_PROT_WRITE);
157 		savelen = oldlen;
158 	}
159 	error = (*fn)(name + 1, ls.nlen - 1, ls.oldval, oldlenp, ls.newval,
160 	    ls.newlen, p);
161 	if (ls.oldval != NULL)
162 		uvm_vsunlock(p, ls.oldval, savelen);
163 	if (error)
164 		return (error);
165 	if (ls.oldlenp)
166 		error = copyout(&oldlen, ls.oldlenp, sizeof(oldlen));
167 	return (error);
168 }
169 
170 char linux_sysname[128] = "Linux";
171 #if defined(__i386__) || defined(__powerpc__)
172 char linux_release[128] = "2.4.18";
173 char linux_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002";
174 #else
175 char linux_release[128] = "2.0.38";
176 char linux_version[128] = "#0 Sun Nov 11 11:11:11 MET 2000";
177 #endif
178 
179 /*
180  * kernel related system variables.
181  */
182 int
183 linux_kern_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
184     void *newp, size_t newlen, struct proc *p)
185 {
186 	/*
187 	 * Note that we allow writing into this, so that userland
188 	 * programs can setup things as they see fit. This is suboptimal.
189 	 */
190 	switch (name[0]) {
191 	case LINUX_KERN_OSTYPE:
192 		return sysctl_string(oldp, oldlenp, newp, newlen,
193 		    linux_sysname, sizeof(linux_sysname));
194 	case LINUX_KERN_OSRELEASE:
195 		return sysctl_string(oldp, oldlenp, newp, newlen,
196 		    linux_release, sizeof(linux_release));
197 	case LINUX_KERN_VERSION:
198 		return sysctl_string(oldp, oldlenp, newp, newlen,
199 		    linux_version, sizeof(linux_version));
200 	default:
201 		return EOPNOTSUPP;
202 	}
203 }
204 
205 /*
206  * kernel related system variables.
207  */
208 int
209 linux_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
210     void *newp, size_t newlen, struct proc *p)
211 {
212 	if (nlen != 2 || name[0] != EMUL_LINUX_KERN)
213 		return EOPNOTSUPP;
214 
215 	/*
216 	 * Note that we allow writing into this, so that userland
217 	 * programs can setup things as they see fit. This is suboptimal.
218 	 */
219 	switch (name[1]) {
220 	case EMUL_LINUX_KERN_OSTYPE:
221 		return sysctl_string(oldp, oldlenp, newp, newlen,
222 		    linux_sysname, sizeof(linux_sysname));
223 	case EMUL_LINUX_KERN_OSRELEASE:
224 		return sysctl_string(oldp, oldlenp, newp, newlen,
225 		    linux_release, sizeof(linux_release));
226 	case EMUL_LINUX_KERN_VERSION:
227 		return sysctl_string(oldp, oldlenp, newp, newlen,
228 		    linux_version, sizeof(linux_version));
229 	default:
230 		return EOPNOTSUPP;
231 	}
232 }
233 
234 /*
235  * hardware related system variables.
236  */
237 int
238 linux_vm_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
239     void *newp, size_t newlen, struct proc *p)
240 {
241 	return (EOPNOTSUPP);
242 }
243 
244 int
245 linux_net_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
246     void *newp, size_t newlen, struct proc *p)
247 {
248 	return (EOPNOTSUPP);
249 }
250 
251 int
252 linux_proc_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
253     void *newp, size_t newlen, struct proc *p)
254 {
255 	return (EOPNOTSUPP);
256 }
257 
258 int
259 linux_fs_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
260     void *newp, size_t newlen, struct proc *p)
261 {
262 	return (EOPNOTSUPP);
263 }
264 #ifdef DEBUG
265 int
266 linux_debug_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
267     void *newp, size_t newlen, struct proc *p)
268 {
269 	return (EOPNOTSUPP);
270 }
271 #endif /* DEBUG */
272 
273 int
274 linux_dev_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
275     void *newp, size_t newlen, struct proc *p)
276 {
277 	return (EOPNOTSUPP);
278 }
279 
280 int
281 linux_bus_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
282     void *newp, size_t newlen, struct proc *p)
283 {
284 	return (EOPNOTSUPP);
285 }
286