1 /* $MirOS: src/sys/compat/common/kern_gen.c,v 1.4 2008/11/08 23:04:09 tg Exp $ */
2
3 /*-
4 * Copyright (c) 2004
5 * Thorsten "mirabilos" Glaser <tg@mirbsd.org>
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * Advertising materials mentioning features or use of this work must
14 * display the following acknowledgement:
15 * This product includes material provided by Thorsten Glaser.
16 *
17 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
18 * the utmost extent permitted by applicable law, neither express nor
19 * implied; without malicious intent or gross negligence. In no event
20 * may a licensor, author or contributor be held liable for indirect,
21 * direct, other damage, loss, or other issues arising in any way out
22 * of dealing in the work, even if advised of the possibility of such
23 * damage or existence of a defect, except proven that it results out
24 * of said person's immediate fault when using the work as intended.
25 *-
26 * Based upon code Copyright (c) 1982, 1986, 1989, 1993
27 * The Regents of the University of California. All rights reserved.
28 */
29
30 #include <sys/param.h>
31 #include <sys/resourcevar.h>
32 #include <sys/kernel.h>
33 #include <sys/systm.h>
34 #include <sys/proc.h>
35 #include <sys/vnode.h>
36 #include <sys/signalvar.h>
37
38 #include <sys/mount.h>
39 #include <sys/syscallargs.h>
40
41 #include <machine/cpu.h>
42 #include <compat/common/compat_util.h>
43 #include <compat/common/kern_gen.h>
44
45 int compat_time_sys_gettimeofday(struct proc *, void *, register_t *);
46 int compat_time_sys_settimeofday(struct proc *, void *, register_t *);
47 int compat_time_sys_setitimer(struct proc *, void *, register_t *);
48 int compat_time_sys_getitimer(struct proc *, void *, register_t *);
49 int compat_time_sys_clock_gettime(struct proc *, void *, register_t *);
50 int compat_time_sys_clock_settime(struct proc *, void *, register_t *);
51 int compat_time_sys_clock_getres(struct proc *, void *, register_t *);
52 int compat_time_sys_nanosleep(struct proc *, void *, register_t *);
53 int compat_time_sys_kevent(struct proc *, void *, register_t *);
54
55
56 #if defined(COMPAT_OPENBSD) || defined(COMPAT_LINUX)
57 int
compat_time_sys_gettimeofday(struct proc * p,void * v,register_t * retval)58 compat_time_sys_gettimeofday(struct proc *p, void *v, register_t *retval)
59 {
60 struct compat_time_sys_gettimeofday_args /* {
61 syscallarg(struct timeval_compat *) tp;
62 syscallarg(struct timezone *) tzp;
63 } */ *uap = v;
64 struct timeval atv;
65 struct timeval_compat ctv;
66 int error = 0;
67
68 if (SCARG(uap, tp)) {
69 microtime(&atv);
70 ctv.tv_sec = atv.tv_sec;
71 ctv.tv_usec = atv.tv_usec;
72 if ((error = copyout((void *)&ctv, (void *)SCARG(uap, tp),
73 sizeof (ctv))))
74 return (error);
75 }
76 if (SCARG(uap, tzp))
77 error = copyout((void *)&tz, (void *)SCARG(uap, tzp),
78 sizeof (tz));
79 return (error);
80 }
81
82 int
compat_time_sys_settimeofday(struct proc * p,void * v,register_t * retval)83 compat_time_sys_settimeofday(struct proc *p, void *v, register_t *retval)
84 {
85 struct compat_time_sys_settimeofday_args /* {
86 syscallarg(const struct timeval_compat *) tv;
87 syscallarg(const struct timezone *) tzp;
88 } */ *uap = v;
89 struct timeval atv;
90 struct timeval_compat ctv;
91 struct timezone atz;
92 int error;
93
94 if ((error = suser(p, 0)))
95 return (error);
96 /* Verify all parameters before changing time. */
97 if (SCARG(uap, tv) && (error = copyin((void *)SCARG(uap, tv),
98 (void *)&ctv, sizeof(ctv))))
99 return (error);
100 if (SCARG(uap, tzp) && (error = copyin((void *)SCARG(uap, tzp),
101 (void *)&atz, sizeof(atz))))
102 return (error);
103 if (SCARG(uap, tv)) {
104 atv.tv_sec = ctv.tv_sec;
105 atv.tv_usec = ctv.tv_usec;
106 if ((error = settime(&atv)) != 0)
107 return (error);
108 }
109 if (SCARG(uap, tzp))
110 tz = atz;
111 return (0);
112 }
113
114 int
compat_time_sys_setitimer(struct proc * p,void * v,register_t * retval)115 compat_time_sys_setitimer(struct proc *p, void *v, register_t *retval)
116 {
117 struct compat_time_sys_setitimer_args /* {
118 syscallarg(int) which;
119 syscallarg(const struct itimerval_compat *) itv;
120 syscallarg(struct itimerval_compat *) oitv;
121 } */ *uap = v;
122 struct sys_setitimer_args {
123 syscallarg(int) which;
124 syscallarg(const struct itimerval *) itv;
125 syscallarg(struct itimerval *) oitv;
126 } bap;
127 struct itimerval tv, *tvp1 = NULL, *tvp2 = NULL;
128 struct itimerval_compat ctv;
129 caddr_t sg = stackgap_init(p->p_emul);
130 int error;
131
132 SCARG(&bap, which) = SCARG(uap, which);
133 if (SCARG(uap, oitv) != NULL)
134 tvp2 = stackgap_alloc(&sg, sizeof(tv));
135 SCARG(&bap, oitv) = tvp2;
136
137 if (SCARG(uap, itv) != NULL) {
138 tvp1 = stackgap_alloc(&sg, sizeof(tv));
139
140 if ((error = copyin((void *)SCARG(uap, itv),
141 (void *)&ctv, sizeof(ctv))))
142 return error;
143 tv.it_interval.tv_sec = ctv.it_interval.tv_sec;
144 tv.it_interval.tv_usec = ctv.it_interval.tv_usec;
145 tv.it_value.tv_sec = ctv.it_value.tv_sec;
146 tv.it_value.tv_usec = ctv.it_value.tv_usec;
147 if ((error = copyout(&tv, tvp1, sizeof(tv))))
148 return error;
149 }
150 SCARG(&bap, itv) = tvp1;
151
152 if ((error = sys_setitimer(p, &bap, retval)))
153 return error;
154
155 if (SCARG(uap, oitv) != NULL) {
156 if ((error = copyin(tvp2, (void *)&tv, sizeof(tv))))
157 return error;
158 ctv.it_interval.tv_sec = __BOUNDLONG(tv.it_interval.tv_sec);
159 ctv.it_interval.tv_usec = tv.it_interval.tv_usec;
160 ctv.it_value.tv_sec = __BOUNDLONG(tv.it_value.tv_sec);
161 ctv.it_value.tv_usec = tv.it_value.tv_usec;
162 if ((error = copyout(&ctv, SCARG(uap, oitv), sizeof(ctv))))
163 return error;
164 }
165
166 return error;
167 }
168
169 int
compat_time_sys_getitimer(struct proc * p,void * v,register_t * retval)170 compat_time_sys_getitimer(struct proc *p, void *v, register_t *retval)
171 {
172 struct compat_time_sys_getitimer_args /* {
173 syscallarg(int) which;
174 syscallarg(struct itimerval_compat *) itv;
175 } */ *uap = v;
176 struct sys_getitimer_args {
177 syscallarg(int) which;
178 syscallarg(struct itimerval *) itv;
179 } bap;
180 struct itimerval tv, *tvp2 = NULL;
181 struct itimerval_compat ctv;
182 caddr_t sg = stackgap_init(p->p_emul);
183 int error;
184
185 SCARG(&bap, which) = SCARG(uap, which);
186 if (SCARG(uap, itv) != NULL)
187 tvp2 = stackgap_alloc(&sg, sizeof(tv));
188 SCARG(&bap, itv) = tvp2;
189
190 if ((error = sys_getitimer(p, &bap, retval)))
191 return error;
192
193 if (SCARG(uap, itv) != NULL) {
194 if ((error = copyin(tvp2, (void *)&tv, sizeof(tv))))
195 return error;
196 ctv.it_interval.tv_sec = __BOUNDLONG(tv.it_interval.tv_sec);
197 ctv.it_interval.tv_usec = tv.it_interval.tv_usec;
198 ctv.it_value.tv_sec = __BOUNDLONG(tv.it_value.tv_sec);
199 ctv.it_value.tv_usec = tv.it_value.tv_usec;
200 if ((error = copyout(&ctv, SCARG(uap, itv), sizeof(ctv))))
201 return error;
202 }
203
204 return error;
205 }
206 #endif
207
208 #if defined(COMPAT_OPENBSD)
209 int
compat_time_sys_clock_gettime(struct proc * p,void * v,register_t * retval)210 compat_time_sys_clock_gettime(struct proc *p, void *v, register_t *retval)
211 {
212 struct compat_time_sys_clock_gettime_args /* {
213 syscallarg(clockid_t) clock_id;
214 syscallarg(struct timespec_compat *) tp;
215 } */ *uap = v;
216 struct sys_clock_gettime_args {
217 syscallarg(clockid_t) clock_id;
218 syscallarg(struct timespec *) tp;
219 } bap;
220 struct timespec tv, *tvp2 = NULL;
221 struct timespec_compat ctv;
222 caddr_t sg = stackgap_init(p->p_emul);
223 int error;
224
225 SCARG(&bap, clock_id) = SCARG(uap, clock_id);
226 if (SCARG(uap, tp) != NULL)
227 tvp2 = stackgap_alloc(&sg, sizeof(tv));
228 SCARG(&bap, tp) = tvp2;
229
230 if ((error = sys_clock_gettime(p, &bap, retval)))
231 return error;
232
233 if (SCARG(uap, tp) != NULL) {
234 if ((error = copyin(tvp2, (void *)&tv, sizeof(tv))))
235 return error;
236 ctv.tv_sec = __BOUNDLONG(tv.tv_sec);
237 ctv.tv_nsec = tv.tv_nsec;
238 if ((error = copyout(&ctv, SCARG(uap, tp), sizeof(ctv))))
239 return error;
240 }
241
242 return error;
243 }
244
245 int
compat_time_sys_clock_settime(struct proc * p,void * v,register_t * retval)246 compat_time_sys_clock_settime(struct proc *p, void *v, register_t *retval)
247 {
248 struct compat_time_sys_clock_settime_args /* {
249 syscallarg(clockid_t) clock_id;
250 syscallarg(const struct timespec_compat *) tp;
251 } */ *uap = v;
252 struct sys_clock_settime_args {
253 syscallarg(clockid_t) clock_id;
254 syscallarg(const struct timespec *) tp;
255 } bap;
256 struct timespec tv, *tvp1 = NULL;
257 struct timespec_compat ctv;
258 int error;
259
260 SCARG(&bap, clock_id) = SCARG(uap, clock_id);
261
262 if (SCARG(uap, tp) != NULL) {
263 caddr_t sg = stackgap_init(p->p_emul);
264 tvp1 = stackgap_alloc(&sg, sizeof(tv));
265
266 if ((error = copyin((void *)SCARG(uap, tp),
267 (void *)&ctv, sizeof(ctv))))
268 return error;
269 tv.tv_sec = ctv.tv_sec;
270 tv.tv_nsec = ctv.tv_nsec;
271 if ((error = copyout(&tv, tvp1, sizeof(tv))))
272 return error;
273 }
274 SCARG(&bap, tp) = tvp1;
275
276 return sys_clock_settime(p, &bap, retval);
277 }
278
279 int
compat_time_sys_clock_getres(struct proc * p,void * v,register_t * retval)280 compat_time_sys_clock_getres(struct proc *p, void *v, register_t *retval)
281 {
282 struct compat_time_sys_clock_getres_args /* {
283 syscallarg(clockid_t) clock_id;
284 syscallarg(struct timespec_compat *) tp;
285 } */ *uap = v;
286 struct sys_clock_getres_args {
287 syscallarg(clockid_t) clock_id;
288 syscallarg(struct timespec *) tp;
289 } bap;
290 struct timespec tv, *tvp2 = NULL;
291 struct timespec_compat ctv;
292 caddr_t sg = stackgap_init(p->p_emul);
293 int error;
294
295 SCARG(&bap, clock_id) = SCARG(uap, clock_id);
296 if (SCARG(uap, tp) != NULL)
297 tvp2 = stackgap_alloc(&sg, sizeof(tv));
298 SCARG(&bap, tp) = tvp2;
299
300 if ((error = sys_clock_getres(p, &bap, retval)))
301 return error;
302
303 if (SCARG(uap, tp) != NULL) {
304 if ((error = copyin(tvp2, (void *)&tv, sizeof(tv))))
305 return error;
306 ctv.tv_sec = __BOUNDLONG(tv.tv_sec);
307 ctv.tv_nsec = tv.tv_nsec;
308 if ((error = copyout(&ctv, SCARG(uap, tp), sizeof(ctv))))
309 return error;
310 }
311
312 return error;
313 }
314 #endif
315
316 #if defined(COMPAT_OPENBSD) || defined(COMPAT_LINUX)
317 int
compat_time_sys_nanosleep(struct proc * p,void * v,register_t * retval)318 compat_time_sys_nanosleep(struct proc *p, void *v, register_t *retval)
319 {
320 struct compat_time_sys_nanosleep_args /* {
321 syscallarg(const struct timespec_compat *) rqtp;
322 syscallarg(struct timespec_compat *) rmtp;
323 } */ *uap = v;
324 struct sys_nanosleep_args {
325 syscallarg(const struct timespec *) rqtp;
326 syscallarg(struct timespec *) rmtp;
327 } bap;
328 struct timespec tv, *tvp1 = NULL, *tvp2 = NULL;
329 struct timespec_compat ctv;
330 caddr_t sg = stackgap_init(p->p_emul);
331 int error;
332
333 if (SCARG(uap, rmtp) != NULL)
334 tvp2 = stackgap_alloc(&sg, sizeof(tv));
335 SCARG(&bap, rmtp) = tvp2;
336
337 if (SCARG(uap, rqtp) != NULL) {
338 tvp1 = stackgap_alloc(&sg, sizeof(tv));
339
340 if ((error = copyin((void *)SCARG(uap, rqtp),
341 (void *)&ctv, sizeof(ctv))))
342 return error;
343 tv.tv_sec = ctv.tv_sec;
344 tv.tv_nsec = ctv.tv_nsec;
345 if ((error = copyout(&tv, tvp1, sizeof(tv))))
346 return error;
347 }
348 SCARG(&bap, rqtp) = tvp1;
349
350 if ((error = sys_nanosleep(p, &bap, retval)))
351 return error;
352
353 if (SCARG(uap, rmtp) != NULL) {
354 if ((error = copyin(tvp2, (void *)&tv, sizeof(tv))))
355 return error;
356 ctv.tv_sec = __BOUNDLONG(tv.tv_sec);
357 ctv.tv_nsec = tv.tv_nsec;
358 if ((error = copyout(&ctv, SCARG(uap, rmtp), sizeof(ctv))))
359 return error;
360 }
361
362 return error;
363 }
364 #endif
365
366 #if defined(COMPAT_OPENBSD)
367 int
compat_time_sys_kevent(struct proc * p,void * v,register_t * retval)368 compat_time_sys_kevent(struct proc *p, void *v, register_t *retval)
369 {
370 struct compat_time_sys_kevent_args /* {
371 syscallarg(int) fd;
372 syscallarg(const struct kevent *) changelist;
373 syscallarg(int) nchanges;
374 syscallarg(struct kevent *) eventlist;
375 syscallarg(int) nevents;
376 syscallarg(const struct timespec_compat *) timeout;
377 } */ *uap = v;
378 struct sys_kevent_args {
379 syscallarg(int) fd;
380 syscallarg(const struct kevent *) changelist;
381 syscallarg(int) nchanges;
382 syscallarg(struct kevent *) eventlist;
383 syscallarg(int) nevents;
384 syscallarg(const struct timespec *) timeout;
385 } bap;
386 struct timespec tv, *tvp = NULL;
387 struct timespec_compat ctv;
388 caddr_t sg;
389 int error;
390
391 SCARG(&bap,fd ) = SCARG(uap, fd);
392 SCARG(&bap,changelist ) = SCARG(uap, changelist);
393 SCARG(&bap,nchanges ) = SCARG(uap, nchanges);
394 SCARG(&bap,eventlist ) = SCARG(uap, eventlist);
395 SCARG(&bap,nevents ) = SCARG(uap, nevents);
396
397 if (SCARG(uap, timeout) != NULL) {
398 sg = stackgap_init(p->p_emul);
399 tvp = stackgap_alloc(&sg, sizeof(tv));
400
401 if ((error = copyin((void *)SCARG(uap, timeout),
402 (void *)&ctv, sizeof(ctv))))
403 return error;
404 tv.tv_sec = ctv.tv_sec;
405 tv.tv_nsec = ctv.tv_nsec;
406 if ((error = copyout(&tv, tvp, sizeof(tv))))
407 return error;
408 }
409 SCARG(&bap, timeout) = tvp;
410
411 return sys_kevent(p, &bap, retval);
412 }
413 #endif
414