linux32_sysctl.c revision 1.4 1 /* $NetBSD: linux32_sysctl.c,v 1.4 2007/02/09 21:55:21 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
19 * permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: linux32_sysctl.c,v 1.4 2007/02/09 21:55:21 ad Exp $");
35
36 #include "opt_ktrace.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/errno.h>
41 #include <sys/proc.h>
42 #include <sys/mount.h>
43 #include <sys/sysctl.h>
44 #include <sys/syscallargs.h>
45 #ifdef KTRACE
46 #include <sys/ktrace.h>
47 #endif
48
49 #include <compat/netbsd32/netbsd32.h>
50
51 #include <compat/linux/common/linux_types.h>
52 #include <compat/linux/common/linux_signal.h>
53 #include <compat/linux/common/linux_sysctl.h>
54
55 #include <compat/linux/linux_syscallargs.h>
56
57 #include <compat/linux32/common/linux32_types.h>
58 #include <compat/linux32/common/linux32_signal.h>
59 #include <compat/linux32/common/linux32_sysctl.h>
60
61 #include <compat/linux32/linux32_syscallargs.h>
62
63 char linux32_sysname[128] = "Linux";
64 char linux32_release[128] = "2.4.18";
65 char linux32_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002";
66
67
68 SYSCTL_SETUP(sysctl_emul_linux32_setup, "sysctl emul.linux32 subtree setup")
69 {
70
71 sysctl_createv(clog, 0, NULL, NULL,
72 CTLFLAG_PERMANENT,
73 CTLTYPE_NODE, "emul", NULL,
74 NULL, 0, NULL, 0,
75 CTL_EMUL, CTL_EOL);
76 sysctl_createv(clog, 0, NULL, NULL,
77 CTLFLAG_PERMANENT,
78 CTLTYPE_NODE, "linux32",
79 SYSCTL_DESCR("Linux 32 bit emulation settings"),
80 NULL, 0, NULL, 0,
81 CTL_EMUL, EMUL_LINUX32, CTL_EOL);
82 sysctl_createv(clog, 0, NULL, NULL,
83 CTLFLAG_PERMANENT,
84 CTLTYPE_NODE, "kern",
85 SYSCTL_DESCR("Linux 32 bit kernel emulation settings"),
86 NULL, 0, NULL, 0,
87 CTL_EMUL, EMUL_LINUX32, EMUL_LINUX32_KERN, CTL_EOL);
88
89 sysctl_createv(clog, 0, NULL, NULL,
90 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
91 CTLTYPE_STRING, "ostype",
92 SYSCTL_DESCR("Linux 32 bit operating system type"),
93 NULL, 0, linux32_sysname, sizeof(linux32_sysname),
94 CTL_EMUL, EMUL_LINUX32, EMUL_LINUX32_KERN,
95 EMUL_LINUX32_KERN_OSTYPE, CTL_EOL);
96 sysctl_createv(clog, 0, NULL, NULL,
97 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
98 CTLTYPE_STRING, "osrelease",
99 SYSCTL_DESCR("Linux 32 bit operating system release"),
100 NULL, 0, linux32_release, sizeof(linux32_release),
101 CTL_EMUL, EMUL_LINUX32, EMUL_LINUX32_KERN,
102 EMUL_LINUX32_KERN_OSRELEASE, CTL_EOL);
103 sysctl_createv(clog, 0, NULL, NULL,
104 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
105 CTLTYPE_STRING, "osversion",
106 SYSCTL_DESCR("Linux 32 bit operating system revision"),
107 NULL, 0, linux32_version, sizeof(linux32_version),
108 CTL_EMUL, EMUL_LINUX32, EMUL_LINUX32_KERN,
109 EMUL_LINUX32_KERN_VERSION, CTL_EOL);
110 }
111
112 #ifndef _LKM
113 static
114 #endif
115 struct sysctlnode linux32_sysctl_root = {
116 .sysctl_flags = SYSCTL_VERSION|
117 CTLFLAG_ROOT|CTLTYPE_NODE|CTLFLAG_READWRITE,
118 .sysctl_num = 0,
119 .sysctl_name = "(linux32_root)",
120 sysc_init_field(_sysctl_size, sizeof(struct sysctlnode)),
121 };
122
123 SYSCTL_SETUP(linux32_sysctl_setup, "linux32 emulated sysctl subtree setup")
124 {
125 const struct sysctlnode *node = &linux32_sysctl_root;
126
127 sysctl_createv(clog, 0, &node, &node,
128 CTLFLAG_PERMANENT,
129 CTLTYPE_NODE, "kern", NULL,
130 NULL, 0, NULL, 0,
131 LINUX_CTL_KERN, CTL_EOL);
132
133 sysctl_createv(clog, 0, &node, NULL,
134 CTLFLAG_PERMANENT,
135 CTLTYPE_STRING, "ostype", NULL,
136 NULL, 0, linux32_sysname, sizeof(linux32_sysname),
137 LINUX_KERN_OSTYPE, CTL_EOL);
138 sysctl_createv(clog, 0, &node, NULL,
139 CTLFLAG_PERMANENT,
140 CTLTYPE_STRING, "osrelease", NULL,
141 NULL, 0, linux32_release, sizeof(linux32_release),
142 LINUX_KERN_OSRELEASE, CTL_EOL);
143 sysctl_createv(clog, 0, &node, NULL,
144 CTLFLAG_PERMANENT,
145 CTLTYPE_STRING, "version", NULL,
146 NULL, 0, linux32_version, sizeof(linux32_version),
147 LINUX_KERN_VERSION, CTL_EOL);
148
149 linux32_sysctl_root.sysctl_flags &= ~CTLFLAG_READWRITE;
150 }
151
152 int
153 linux32_sys___sysctl(l, v, retval)
154 struct lwp *l;
155 void *v;
156 register_t *retval;
157 {
158 struct linux32_sys___sysctl_args /* {
159 syscallarg(linux32___sysctlp_t) lsp;
160 } */ *uap = v;
161 struct linux32_sysctl ls32;
162 int name[CTL_MAXNAME];
163 size_t savelen;
164 netbsd32_size_t oldlen32;
165 size_t oldlen;
166 int error;
167
168 /*
169 * Read sysctl arguments
170 */
171 if ((error = copyin(NETBSD32PTR64(SCARG(uap, lsp)),
172 &ls32, sizeof(ls32))) != 0)
173 return error;
174
175 /*
176 * Read oldlen
177 */
178 if (NETBSD32PTR64(ls32.oldlenp) != NULL) {
179 if ((error = copyin(NETBSD32PTR64(ls32.oldlenp),
180 &oldlen32, sizeof(oldlen32))) != 0)
181 return error;
182 } else {
183 oldlen32 = 0;
184 }
185
186 savelen = (size_t)oldlen32;
187
188 /*
189 * Sanity check nlen
190 */
191 if ((ls32.nlen > CTL_MAXNAME) || (ls32.nlen < 1))
192 return EINVAL;
193
194 /*
195 * Read the sysctl name
196 */
197 if ((error = copyin(NETBSD32PTR64(ls32.name), &name,
198 ls32.nlen * sizeof(int))) != 0)
199 return error;
200
201 #ifdef KTRACE
202 if (KTRPOINT(l->l_proc, KTR_MIB))
203 ktrmib(l, name, ls32.nlen);
204 #endif
205
206 if ((error = sysctl_lock(l,
207 NETBSD32PTR64(ls32.oldval), savelen)) != 0)
208 return error;
209
210 /*
211 * First try linux32 tree, then linux tree
212 */
213 oldlen = (size_t)oldlen32;
214 error = sysctl_dispatch(name, ls32.nlen,
215 NETBSD32PTR64(ls32.oldval), &oldlen,
216 NETBSD32PTR64(ls32.newval), ls32.newlen,
217 name, l, &linux32_sysctl_root);
218 oldlen32 = (netbsd32_size_t)oldlen;
219
220 sysctl_unlock(l);
221
222 /*
223 * Check for oldlen overflow (not likely, but who knows...)
224 */
225 if (oldlen != oldlen32) {
226 #ifdef DEBUG_LINUX
227 printf("%s: oldlen32 = %d, oldlen = %ld\n",
228 __func__, oldlen32, oldlen);
229 #endif
230 return EINVAL;
231 }
232
233 /*
234 * set caller's oldlen, even if we got an error
235 */
236 if (NETBSD32PTR64(ls32.oldlenp)) {
237 int nerror;
238
239 nerror = copyout(&oldlen32,
240 NETBSD32PTR64(ls32.oldlenp), sizeof(oldlen32));
241
242 if (error == 0)
243 error = nerror;
244 }
245
246 /*
247 * oldlen was too short
248 */
249 if ((error == 0) &&
250 (NETBSD32PTR64(ls32.oldval) != NULL) &&
251 (savelen < oldlen32))
252 error = ENOMEM;
253
254 return error;
255 }
256