linux_misc_notalpha.c revision 1.55 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