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