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