xref: /netbsd-src/sys/compat/linux/common/linux_misc_notalpha.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: linux_misc_notalpha.c,v 1.55 2000/06/29 02:40:39 mrg Exp $	*/
2 
3 /*-
4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
9  * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/mman.h>
44 #include <sys/mount.h>
45 #include <sys/malloc.h>
46 #include <sys/mbuf.h>
47 #include <sys/namei.h>
48 #include <sys/ptrace.h>
49 #include <sys/resource.h>
50 #include <sys/resourcevar.h>
51 #include <sys/wait.h>
52 
53 #include <sys/syscallargs.h>
54 
55 #include <compat/linux/common/linux_types.h>
56 #include <compat/linux/common/linux_fcntl.h>
57 #include <compat/linux/common/linux_misc.h>
58 #include <compat/linux/common/linux_mmap.h>
59 #include <compat/linux/common/linux_signal.h>
60 #include <compat/linux/common/linux_util.h>
61 
62 #include <compat/linux/linux_syscallargs.h>
63 
64 /*
65  * This file contains routines which are used
66  * on every linux architechture except the Alpha.
67  */
68 
69 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
70 /* Not used on: alpha */
71 
72 /*
73  * Alarm. This is a libc call which uses setitimer(2) in NetBSD.
74  * Fiddle with the timers to make it work.
75  */
76 int
77 linux_sys_alarm(p, v, retval)
78 	struct proc *p;
79 	void *v;
80 	register_t *retval;
81 {
82 	struct linux_sys_alarm_args /* {
83 		syscallarg(unsigned int) secs;
84 	} */ *uap = v;
85 	int s;
86 	struct itimerval *itp, it;
87 
88 	itp = &p->p_realtimer;
89 	s = splclock();
90 	/*
91 	 * Clear any pending timer alarms.
92 	 */
93 	callout_stop(&p->p_realit_ch);
94 	timerclear(&itp->it_interval);
95 	if (timerisset(&itp->it_value) &&
96 	    timercmp(&itp->it_value, &time, >))
97 		timersub(&itp->it_value, &time, &itp->it_value);
98 	/*
99 	 * Return how many seconds were left (rounded up)
100 	 */
101 	retval[0] = itp->it_value.tv_sec;
102 	if (itp->it_value.tv_usec)
103 		retval[0]++;
104 
105 	/*
106 	 * alarm(0) just resets the timer.
107 	 */
108 	if (SCARG(uap, secs) == 0) {
109 		timerclear(&itp->it_value);
110 		splx(s);
111 		return 0;
112 	}
113 
114 	/*
115 	 * Check the new alarm time for sanity, and set it.
116 	 */
117 	timerclear(&it.it_interval);
118 	it.it_value.tv_sec = SCARG(uap, secs);
119 	it.it_value.tv_usec = 0;
120 	if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) {
121 		splx(s);
122 		return (EINVAL);
123 	}
124 
125 	if (timerisset(&it.it_value)) {
126 		timeradd(&it.it_value, &time, &it.it_value);
127 		callout_reset(&p->p_realit_ch, hzto(&it.it_value),
128 		    realitexpire, p);
129 	}
130 	p->p_realtimer = it;
131 	splx(s);
132 
133 	return 0;
134 }
135 
136 int
137 linux_sys_nice(p, v, retval)
138 	struct proc *p;
139 	void *v;
140 	register_t *retval;
141 {
142 	struct linux_sys_nice_args /* {
143 		syscallarg(int) incr;
144 	} */ *uap = v;
145         struct sys_setpriority_args bsa;
146 
147         SCARG(&bsa, which) = PRIO_PROCESS;
148         SCARG(&bsa, who) = 0;
149 	SCARG(&bsa, prio) = SCARG(uap, incr);
150         return sys_setpriority(p, &bsa, retval);
151 }
152 
153 /*
154  * The old Linux readdir was only able to read one entry at a time,
155  * even though it had a 'count' argument. In fact, the emulation
156  * of the old call was better than the original, because it did handle
157  * the count arg properly. Don't bother with it anymore now, and use
158  * it to distinguish between old and new. The difference is that the
159  * newer one actually does multiple entries, and the reclen field
160  * really is the reclen, not the namelength.
161  */
162 int
163 linux_sys_readdir(p, v, retval)
164 	struct proc *p;
165 	void *v;
166 	register_t *retval;
167 {
168 	struct linux_sys_readdir_args /* {
169 		syscallarg(int) fd;
170 		syscallarg(struct linux_dirent *) dent;
171 		syscallarg(unsigned int) count;
172 	} */ *uap = v;
173 
174 	SCARG(uap, count) = 1;
175 	return linux_sys_getdents(p, uap, retval);
176 }
177 
178 /*
179  * I wonder why Linux has gettimeofday() _and_ time().. Still, we
180  * need to deal with it.
181  */
182 int
183 linux_sys_time(p, v, retval)
184 	struct proc *p;
185 	void *v;
186 	register_t *retval;
187 {
188 	struct linux_sys_time_args /* {
189 		linux_time_t *t;
190 	} */ *uap = v;
191 	struct timeval atv;
192 	linux_time_t tt;
193 	int error;
194 
195 	microtime(&atv);
196 
197 	tt = atv.tv_sec;
198 	if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt)))
199 		return error;
200 
201 	retval[0] = tt;
202 	return 0;
203 }
204 
205 /*
206  * utime(). Do conversion to things that utimes() understands,
207  * and pass it on.
208  */
209 int
210 linux_sys_utime(p, v, retval)
211 	struct proc *p;
212 	void *v;
213 	register_t *retval;
214 {
215 	struct linux_sys_utime_args /* {
216 		syscallarg(const char *) path;
217 		syscallarg(struct linux_utimbuf *)times;
218 	} */ *uap = v;
219 	caddr_t sg;
220 	int error;
221 	struct sys_utimes_args ua;
222 	struct timeval tv[2], *tvp;
223 	struct linux_utimbuf lut;
224 
225 	sg = stackgap_init(p->p_emul);
226 	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
227 
228 	SCARG(&ua, path) = SCARG(uap, path);
229 
230 	if (SCARG(uap, times) != NULL) {
231 		if ((error = copyin(SCARG(uap, times), &lut, sizeof lut)))
232 			return error;
233 		tv[0].tv_usec = tv[1].tv_usec = 0;
234 		tv[0].tv_sec = lut.l_actime;
235 		tv[1].tv_sec = lut.l_modtime;
236 		tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv));
237 		if ((error = copyout(tv, tvp, sizeof tv)))
238 			return error;
239 		SCARG(&ua, tptr) = tvp;
240 	}
241 	else
242 		SCARG(&ua, tptr) = NULL;
243 
244 	return sys_utimes(p, &ua, retval);
245 }
246 
247 /*
248  * waitpid(2). Passed on to the NetBSD call, surrounded by code to
249  * reserve some space for a NetBSD-style wait status, and converting
250  * it to what Linux wants.
251  */
252 int
253 linux_sys_waitpid(p, v, retval)
254 	struct proc *p;
255 	void *v;
256 	register_t *retval;
257 {
258 	struct linux_sys_waitpid_args /* {
259 		syscallarg(int) pid;
260 		syscallarg(int *) status;
261 		syscallarg(int) options;
262 	} */ *uap = v;
263 	struct sys_wait4_args w4a;
264 	int error, *status, tstat;
265 	caddr_t sg;
266 
267 	if (SCARG(uap, status) != NULL) {
268 		sg = stackgap_init(p->p_emul);
269 		status = (int *) stackgap_alloc(&sg, sizeof status);
270 	} else
271 		status = NULL;
272 
273 	SCARG(&w4a, pid) = SCARG(uap, pid);
274 	SCARG(&w4a, status) = status;
275 	SCARG(&w4a, options) = SCARG(uap, options);
276 	SCARG(&w4a, rusage) = NULL;
277 
278 	if ((error = sys_wait4(p, &w4a, retval)))
279 		return error;
280 
281 	sigdelset(&p->p_siglist, SIGCHLD);
282 
283 	if (status != NULL) {
284 		if ((error = copyin(status, &tstat, sizeof tstat)))
285 			return error;
286 
287 		bsd_to_linux_wstat(&tstat);
288 		return copyout(&tstat, SCARG(uap, status), sizeof tstat);
289 	}
290 
291 	return 0;
292 }
293 
294 int
295 linux_sys_setresgid(p, v, retval)
296 	struct proc *p;
297 	void *v;
298 	register_t *retval;
299 {
300 	struct linux_sys_setresgid_args /* {
301 		syscallarg(gid_t) rgid;
302 		syscallarg(gid_t) egid;
303 		syscallarg(gid_t) sgid;
304 	} */ *uap = v;
305 	struct pcred *pc = p->p_cred;
306 	gid_t rgid, egid, sgid;
307 	int error;
308 
309 	rgid = SCARG(uap, rgid);
310 	egid = SCARG(uap, egid);
311 	sgid = SCARG(uap, sgid);
312 
313 	/*
314 	 * Note: These checks are a little different than the NetBSD
315 	 * setregid(2) call performs.  This precisely follows the
316 	 * behavior of the Linux kernel.
317 	 */
318 	if (rgid != (gid_t)-1 &&
319 	    rgid != pc->p_rgid &&
320 	    rgid != pc->pc_ucred->cr_gid &&
321 	    rgid != pc->p_svgid &&
322 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
323 		return (error);
324 
325 	if (egid != (gid_t)-1 &&
326 	    egid != pc->p_rgid &&
327 	    egid != pc->pc_ucred->cr_gid &&
328 	    egid != pc->p_svgid &&
329 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
330 		return (error);
331 
332 	if (sgid != (gid_t)-1 &&
333 	    sgid != pc->p_rgid &&
334 	    sgid != pc->pc_ucred->cr_gid &&
335 	    sgid != pc->p_svgid &&
336 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
337 		return (error);
338 
339 	/*
340 	 * Now assign the real, effective, and saved GIDs.
341 	 * Note that Linux, unlike NetBSD in setregid(2), does not
342 	 * set the saved UID in this call unless the user specifies
343 	 * it.
344 	 */
345 	if (rgid != (gid_t)-1)
346 		pc->p_rgid = rgid;
347 
348 	if (egid != (gid_t)-1) {
349 		pc->pc_ucred = crcopy(pc->pc_ucred);
350 		pc->pc_ucred->cr_gid = egid;
351 	}
352 
353 	if (sgid != (gid_t)-1)
354 		pc->p_svgid = sgid;
355 
356 	if (rgid != (gid_t)-1 && egid != (gid_t)-1 && sgid != (gid_t)-1)
357 		p->p_flag |= P_SUGID;
358 	return (0);
359 }
360 
361 int
362 linux_sys_getresgid(p, v, retval)
363 	struct proc *p;
364 	void *v;
365 	register_t *retval;
366 {
367 	struct linux_sys_getresgid_args /* {
368 		syscallarg(gid_t *) rgid;
369 		syscallarg(gid_t *) egid;
370 		syscallarg(gid_t *) sgid;
371 	} */ *uap = v;
372 	struct pcred *pc = p->p_cred;
373 	int error;
374 
375 	/*
376 	 * Linux copies these values out to userspace like so:
377 	 *
378 	 *	1. Copy out rgid.
379 	 *	2. If that succeeds, copy out egid.
380 	 *	3. If both of those succeed, copy out sgid.
381 	 */
382 	if ((error = copyout(&pc->p_rgid, SCARG(uap, rgid),
383 			     sizeof(gid_t))) != 0)
384 		return (error);
385 
386 	if ((error = copyout(&pc->pc_ucred->cr_uid, SCARG(uap, egid),
387 			     sizeof(gid_t))) != 0)
388 		return (error);
389 
390 	return (copyout(&pc->p_svgid, SCARG(uap, sgid), sizeof(gid_t)));
391 }
392 
393 /*
394  * I wonder why Linux has settimeofday() _and_ stime().. Still, we
395  * need to deal with it.
396  */
397 int
398 linux_sys_stime(p, v, retval)
399 	struct proc *p;
400 	void *v;
401 	register_t *retval;
402 {
403 	struct linux_sys_time_args /* {
404 		linux_time_t *t;
405 	} */ *uap = v;
406 	struct timeval atv;
407 	linux_time_t tt;
408 	int error;
409 
410 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
411 		return (error);
412 
413 	if ((error = copyin(&tt, SCARG(uap, t), sizeof tt)) != 0)
414 		return error;
415 
416 	atv.tv_sec = tt;
417 	atv.tv_usec = 0;
418 
419 	if ((error = settime(&atv)))
420 		return (error);
421 
422 	return 0;
423 }
424