xref: /netbsd-src/sys/compat/linux/common/linux_sysctl.c (revision 0dd5877adce57db949b16ae963e5a6831cccdfb6)
1 /*	$NetBSD: linux_sysctl.c,v 1.2 2002/02/20 17:02:48 christos 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.2 2002/02/20 17:02:48 christos 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/syscallargs.h>
55 
56 #include <compat/linux/common/linux_types.h>
57 #include <compat/linux/common/linux_signal.h>
58 
59 #include <compat/linux/linux_syscallargs.h>
60 #include <compat/linux/common/linux_sysctl.h>
61 
62 int linux_kern_sysctl(int *, u_int, void *, size_t *, void *, size_t,
63     struct proc *);
64 int linux_vm_sysctl(int *, u_int, void *, size_t *, void *, size_t,
65     struct proc *);
66 int linux_net_sysctl(int *, u_int, void *, size_t *, void *, size_t,
67     struct proc *);
68 int linux_proc_sysctl(int *, u_int, void *, size_t *, void *, size_t,
69     struct proc *);
70 int linux_fs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
71     struct proc *);
72 #ifdef DEBUG
73 int linux_debug_sysctl(int *, u_int, void *, size_t *, void *, size_t,
74     struct proc *);
75 #endif
76 int linux_dev_sysctl(int *, u_int, void *, size_t *, void *, size_t,
77     struct proc *);
78 int linux_bus_sysctl(int *, u_int, void *, size_t *, void *, size_t,
79     struct proc *);
80 
81 int
82 linux_sys___sysctl(struct proc *p, void *v, register_t *retval)
83 {
84 	struct linux_sys___sysctl_args /* {
85 		syscallarg(struct linux___sysctl *) lsp;
86 	} */ *uap = v;
87 	struct linux___sysctl ls;
88 	int error;
89 	size_t savelen = 0, oldlen = 0;
90 	sysctlfn *fn;
91 	int name[CTL_MAXNAME];
92 	size_t *oldlenp;
93 
94 
95 	if ((error = copyin(SCARG(uap, lsp), &ls, sizeof ls)))
96 		return error;
97 	/*
98 	 * all top-level sysctl names are non-terminal
99 	 */
100 	if (ls.nlen > CTL_MAXNAME || ls.nlen < 2)
101 		return (EINVAL);
102 	error = copyin(ls.name, &name, ls.nlen * sizeof(int));
103 	if (error)
104 		return (error);
105 
106 	/*
107 	 * For all but CTL_PROC, must be root to change a value.
108 	 * For CTL_PROC, must be root, or owner of the proc (and not suid),
109 	 * this is checked in proc_sysctl() (once we know the targer proc).
110 	 */
111 	if (ls.newval != NULL && name[0] != CTL_PROC &&
112 		    (error = suser(p->p_ucred, &p->p_acflag)))
113 			return error;
114 
115 	switch (name[0]) {
116 	case LINUX_CTL_KERN:
117 		fn = linux_kern_sysctl;
118 		break;
119 	case LINUX_CTL_VM:
120 		fn = linux_vm_sysctl;
121 		break;
122 	case LINUX_CTL_NET:
123 		fn = linux_net_sysctl;
124 		break;
125 	case LINUX_CTL_PROC:
126 		fn = linux_proc_sysctl;
127 		break;
128 	case LINUX_CTL_FS:
129 		fn = linux_fs_sysctl;
130 		break;
131 #ifdef DEBUG
132 	case LINUX_CTL_DEBUG:
133 		fn = linux_debug_sysctl;
134 		break;
135 #endif
136 	case LINUX_CTL_DEV:
137 		fn = linux_dev_sysctl;
138 		break;
139 	case LINUX_CTL_BUS:
140 		fn = linux_bus_sysctl;
141 		break;
142 	default:
143 		return (EOPNOTSUPP);
144 	}
145 
146 	/*
147 	 * XXX Hey, we wire `oldval', but what about `newval'?
148 	 */
149 	oldlenp = ls.oldlenp;
150 	if (oldlenp) {
151 		if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen))))
152 			return (error);
153 		oldlenp = &oldlen;
154 	}
155 	if (ls.oldval != NULL) {
156 		error = uvm_vslock(p, ls.oldval, oldlen,
157 		    VM_PROT_READ|VM_PROT_WRITE);
158 		savelen = oldlen;
159 	}
160 	error = (*fn)(name + 1, ls.nlen - 1, ls.oldval, oldlenp, ls.newval,
161 	    ls.newlen, p);
162 	if (ls.oldval != NULL)
163 		uvm_vsunlock(p, ls.oldval, savelen);
164 	if (error)
165 		return (error);
166 	if (ls.oldlenp)
167 		error = copyout(&oldlen, ls.oldlenp, sizeof(oldlen));
168 	return (error);
169 }
170 
171 /*
172  * NOTE: DO NOT CHANGE THIS
173  * Linux makes assumptions about specific features being present with
174  * more recent kernels. Specifically, LinuxThreads use RT queued
175  * signals if the kernel release is bigger. Since we don't support them
176  * yet, the version needs to stay this way until we'd have the RT queued
177  * signals implemented.
178  */
179 char linux_sysname[128] = "Linux";
180 char linux_release[128] = "2.0.38";
181 char linux_version[128] = "#0 Sun Apr 1 11:11:11 MET 2000";
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  * hardware related system variables.
211  */
212 int
213 linux_vm_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
214     void *newp, size_t newlen, struct proc *p)
215 {
216 	return (EOPNOTSUPP);
217 }
218 
219 int
220 linux_net_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
221     void *newp, size_t newlen, struct proc *p)
222 {
223 	return (EOPNOTSUPP);
224 }
225 
226 int
227 linux_proc_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
228     void *newp, size_t newlen, struct proc *p)
229 {
230 	return (EOPNOTSUPP);
231 }
232 
233 int
234 linux_fs_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
235     void *newp, size_t newlen, struct proc *p)
236 {
237 	return (EOPNOTSUPP);
238 }
239 #ifdef DEBUG
240 int
241 linux_debug_sysctl(int *name, u_int nlen, void *oldp, size_t *oldlenp,
242     void *newp, size_t newlen, struct proc *p)
243 {
244 	return (EOPNOTSUPP);
245 }
246 #endif /* DEBUG */
247 
248 int
249 linux_dev_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_bus_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