1 /* $NetBSD: linux32_unistd.c,v 1.33 2009/06/02 13:00:24 njoly Exp $ */
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
34 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: linux32_unistd.c,v 1.33 2009/06/02 13:00:24 njoly Exp $");
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/fstypes.h>
41 #include <sys/signal.h>
42 #include <sys/dirent.h>
43 #include <sys/kernel.h>
44 #include <sys/fcntl.h>
45 #include <sys/select.h>
47 #include <sys/ucred.h>
49 #include <sys/kauth.h>
51 #include <machine/types.h>
53 #include <sys/syscallargs.h>
55 #include <compat/netbsd32/netbsd32.h>
56 #include <compat/netbsd32/netbsd32_conv.h>
58 #include <compat/linux/common/linux_types.h>
59 #include <compat/linux/common/linux_signal.h>
60 #include <compat/linux/common/linux_machdep.h>
61 #include <compat/linux/common/linux_misc.h>
62 #include <compat/linux/common/linux_oldolduname.h>
63 #include <compat/linux/common/linux_ipc.h>
64 #include <compat/linux/common/linux_sem.h>
65 #include <compat/linux/linux_syscallargs.h>
67 #include <compat/linux32/common/linux32_types.h>
68 #include <compat/linux32/common/linux32_signal.h>
69 #include <compat/linux32/common/linux32_machdep.h>
70 #include <compat/linux32/common/linux32_sysctl.h>
71 #include <compat/linux32/common/linux32_socketcall.h>
72 #include <compat/linux32/linux32_syscallargs.h>
74 static int linux32_select1(struct lwp
*, register_t
*,
75 int, fd_set
*, fd_set
*, fd_set
*, struct timeval
*);
78 linux32_sys_brk(struct lwp
*l
, const struct linux32_sys_brk_args
*uap
, register_t
*retval
)
81 syscallarg(netbsd32_charp) nsize;
83 struct linux_sys_brk_args ua
;
85 NETBSD32TOP_UAP(nsize
, char);
86 return linux_sys_brk(l
, &ua
, retval
);
90 linux32_sys_llseek(struct lwp
*l
, const struct linux32_sys_llseek_args
*uap
, register_t
*retval
)
94 syscallarg(u_int32_t) ohigh;
95 syscallarg(u_int32_t) olow;
96 syscallarg(netbsd32_voidp) res;
97 syscallarg(int) whence;
99 struct linux_sys_llseek_args ua
;
101 NETBSD32TO64_UAP(fd
);
102 NETBSD32TO64_UAP(ohigh
);
103 NETBSD32TO64_UAP(olow
);
104 NETBSD32TOP_UAP(res
, void);
105 NETBSD32TO64_UAP(whence
);
107 return linux_sys_llseek(l
, &ua
, retval
);
111 linux32_sys_select(struct lwp
*l
, const struct linux32_sys_select_args
*uap
, register_t
*retval
)
114 syscallarg(int) nfds;
115 syscallarg(netbsd32_fd_setp_t) readfds;
116 syscallarg(netbsd32_fd_setp_t) writefds;
117 syscallarg(netbsd32_fd_setp_t) exceptfds;
118 syscallarg(netbsd32_timeval50p_t) timeout;
121 return linux32_select1(l
, retval
, SCARG(uap
, nfds
),
122 SCARG_P32(uap
, readfds
),
123 SCARG_P32(uap
, writefds
),
124 SCARG_P32(uap
, exceptfds
),
125 SCARG_P32(uap
, timeout
));
129 linux32_sys_oldselect(struct lwp
*l
, const struct linux32_sys_oldselect_args
*uap
, register_t
*retval
)
132 syscallarg(linux32_oldselectp_t) lsp;
134 struct linux32_oldselect lsp32
;
137 if ((error
= copyin(SCARG_P32(uap
, lsp
), &lsp32
, sizeof(lsp32
))) != 0)
140 return linux32_select1(l
, retval
, lsp32
.nfds
,
141 NETBSD32PTR64(lsp32
.readfds
), NETBSD32PTR64(lsp32
.writefds
),
142 NETBSD32PTR64(lsp32
.exceptfds
), NETBSD32PTR64(lsp32
.timeout
));
146 linux32_select1(struct lwp
*l
, register_t
*retval
, int nfds
,
147 fd_set
*readfds
, fd_set
*writefds
, fd_set
*exceptfds
,
148 struct timeval
*timeout
)
150 struct timespec ts0
, ts1
, uts
, *ts
= NULL
;
151 struct netbsd32_timeval50 utv32
;
156 * Store current time for computation of the amount of
160 if ((error
= copyin(timeout
, &utv32
, sizeof(utv32
))))
163 uts
.tv_sec
= utv32
.tv_sec
;
164 uts
.tv_nsec
= utv32
.tv_usec
* 1000;
166 if (itimespecfix(&uts
)) {
168 * The timeval was invalid. Convert it to something
169 * valid that will act as it does under Linux.
171 uts
.tv_sec
+= uts
.tv_nsec
/ 1000000000;
172 uts
.tv_nsec
%= 1000000000;
173 if (uts
.tv_nsec
< 0) {
175 uts
.tv_nsec
+= 1000000000;
183 timespecclear(&uts
); /* XXX GCC4 */
185 error
= selcommon(retval
, nfds
, readfds
, writefds
, exceptfds
, ts
, NULL
);
189 * See fs/select.c in the Linux kernel. Without this,
190 * Maelstrom doesn't work.
192 if (error
== ERESTART
)
200 * Compute how much time was left of the timeout,
201 * by subtracting the current time and the time
202 * before we started the call, and subtracting
203 * that result from the user-supplied value.
206 timespecsub(&ts1
, &ts0
, &ts1
);
207 timespecsub(&uts
, &ts1
, &uts
);
214 utv32
.tv_sec
= uts
.tv_sec
;
215 utv32
.tv_usec
= uts
.tv_nsec
/ 1000;
217 if ((error
= copyout(&utv32
, timeout
, sizeof(utv32
))))
225 linux32_sys_pipe(struct lwp
*l
, const struct linux32_sys_pipe_args
*uap
, register_t
*retval
)
228 syscallarg(netbsd32_intp) fd;
233 if ((error
= sys_pipe(l
, 0, retval
)))
236 pfds
[0] = (int)retval
[0];
237 pfds
[1] = (int)retval
[1];
239 if ((error
= copyout(pfds
, SCARG_P32(uap
, fd
), 2 * sizeof (int))) != 0)
250 linux32_sys_unlink(struct lwp
*l
, const struct linux32_sys_unlink_args
*uap
, register_t
*retval
)
253 syscallarg(const netbsd32_charp) path;
255 struct linux_sys_unlink_args ua
;
257 NETBSD32TOP_UAP(path
, const char);
259 return linux_sys_unlink(l
, &ua
, retval
);
263 linux32_sys_creat(struct lwp
*l
, const struct linux32_sys_creat_args
*uap
, register_t
*retval
)
266 syscallarg(const netbsd32_charp) path;
267 syscallarg(int) mode;
269 struct sys_open_args ua
;
271 NETBSD32TOP_UAP(path
, const char);
272 SCARG(&ua
, flags
) = O_CREAT
| O_TRUNC
| O_WRONLY
;
273 NETBSD32TO64_UAP(mode
);
275 return sys_open(l
, &ua
, retval
);
279 linux32_sys_mknod(struct lwp
*l
, const struct linux32_sys_mknod_args
*uap
, register_t
*retval
)
282 syscallarg(const netbsd32_charp) path;
283 syscallarg(int) mode;
286 struct linux_sys_mknod_args ua
;
288 NETBSD32TOP_UAP(path
, const char);
289 NETBSD32TO64_UAP(mode
);
290 NETBSD32TO64_UAP(dev
);
292 return linux_sys_mknod(l
, &ua
, retval
);
296 linux32_sys_break(struct lwp
*l
, const struct linux32_sys_break_args
*uap
, register_t
*retval
)
300 syscallarg(const netbsd32_charp) nsize;
308 linux32_sys_swapon(struct lwp
*l
, const struct linux32_sys_swapon_args
*uap
, register_t
*retval
)
311 syscallarg(const netbsd32_charp) name;
313 struct sys_swapctl_args ua
;
315 SCARG(&ua
, cmd
) = SWAP_ON
;
316 SCARG(&ua
, arg
) = SCARG_P32(uap
, name
);
317 SCARG(&ua
, misc
) = 0; /* priority */
318 return (sys_swapctl(l
, &ua
, retval
));
322 linux32_sys_swapoff(struct lwp
*l
, const struct linux32_sys_swapoff_args
*uap
, register_t
*retval
)
325 syscallarg(const netbsd32_charp) path;
327 struct sys_swapctl_args ua
;
329 SCARG(&ua
, cmd
) = SWAP_OFF
;
330 SCARG(&ua
, arg
) = SCARG_P32(uap
, path
);
331 SCARG(&ua
, misc
) = 0; /* priority */
332 return (sys_swapctl(l
, &ua
, retval
));
337 linux32_sys_reboot(struct lwp
*l
, const struct linux32_sys_reboot_args
*uap
, register_t
*retval
)
340 syscallarg(int) magic1;
341 syscallarg(int) magic2;
343 syscallarg(netbsd32_voidp) arg;
345 struct linux_sys_reboot_args ua
;
347 NETBSD32TO64_UAP(magic1
);
348 NETBSD32TO64_UAP(magic2
);
349 NETBSD32TO64_UAP(cmd
);
350 NETBSD32TOP_UAP(arg
, void);
352 return linux_sys_reboot(l
, &ua
, retval
);
356 linux32_sys_setresuid(struct lwp
*l
, const struct linux32_sys_setresuid_args
*uap
, register_t
*retval
)
359 syscallarg(uid_t) ruid;
360 syscallarg(uid_t) euid;
361 syscallarg(uid_t) suid;
363 struct linux_sys_setresuid_args ua
;
365 NETBSD32TO64_UAP(ruid
);
366 NETBSD32TO64_UAP(euid
);
367 NETBSD32TO64_UAP(suid
);
369 return linux_sys_setresuid(l
, &ua
, retval
);
373 linux32_sys_getresuid(struct lwp
*l
, const struct linux32_sys_getresuid_args
*uap
, register_t
*retval
)
376 syscallarg(linux32_uidp_t) ruid;
377 syscallarg(linux32_uidp_t) euid;
378 syscallarg(linux32_uidp_t) suid;
380 kauth_cred_t pc
= l
->l_cred
;
384 uid
= kauth_cred_getuid(pc
);
385 if ((error
= copyout(&uid
, SCARG_P32(uap
, ruid
), sizeof(uid_t
))) != 0)
388 uid
= kauth_cred_geteuid(pc
);
389 if ((error
= copyout(&uid
, SCARG_P32(uap
, euid
), sizeof(uid_t
))) != 0)
392 uid
= kauth_cred_getsvuid(pc
);
393 return copyout(&uid
, SCARG_P32(uap
, suid
), sizeof(uid_t
));
397 linux32_sys_setresgid(struct lwp
*l
, const struct linux32_sys_setresgid_args
*uap
, register_t
*retval
)
400 syscallarg(gid_t) rgid;
401 syscallarg(gid_t) egid;
402 syscallarg(gid_t) sgid;
404 struct linux_sys_setresgid_args ua
;
406 NETBSD32TO64_UAP(rgid
);
407 NETBSD32TO64_UAP(egid
);
408 NETBSD32TO64_UAP(sgid
);
410 return linux_sys_setresgid(l
, &ua
, retval
);
414 linux32_sys_getresgid(struct lwp
*l
, const struct linux32_sys_getresgid_args
*uap
, register_t
*retval
)
417 syscallarg(linux32_gidp_t) rgid;
418 syscallarg(linux32_gidp_t) egid;
419 syscallarg(linux32_gidp_t) sgid;
421 kauth_cred_t pc
= l
->l_cred
;
425 gid
= kauth_cred_getgid(pc
);
426 if ((error
= copyout(&gid
, SCARG_P32(uap
, rgid
), sizeof(gid_t
))) != 0)
429 gid
= kauth_cred_getegid(pc
);
430 if ((error
= copyout(&gid
, SCARG_P32(uap
, egid
), sizeof(gid_t
))) != 0)
433 gid
= kauth_cred_getsvgid(pc
);
434 return copyout(&gid
, SCARG_P32(uap
, sgid
), sizeof(gid_t
));
438 linux32_sys_nice(struct lwp
*l
, const struct linux32_sys_nice_args
*uap
, register_t
*retval
)
441 syscallarg(int) incr;
443 struct proc
*p
= l
->l_proc
;
444 struct sys_setpriority_args bsa
;
447 SCARG(&bsa
, which
) = PRIO_PROCESS
;
448 SCARG(&bsa
, who
) = 0;
449 SCARG(&bsa
, prio
) = p
->p_nice
- NZERO
+ SCARG(uap
, incr
);
451 error
= sys_setpriority(l
, &bsa
, retval
);
452 return (error
) ? EPERM
: 0;
456 linux32_sys_alarm(struct lwp
*l
, const struct linux32_sys_alarm_args
*uap
, register_t
*retval
)
459 syscallarg(unsigned int) secs;
461 struct linux_sys_alarm_args ua
;
463 NETBSD32TO64_UAP(secs
);
465 return linux_sys_alarm(l
, &ua
, retval
);
469 linux32_sys_fdatasync(struct lwp
*l
, const struct linux32_sys_fdatasync_args
*uap
, register_t
*retval
)
474 struct linux_sys_fdatasync_args ua
;
476 NETBSD32TO64_UAP(fd
);
478 return linux_sys_fdatasync(l
, &ua
, retval
);
482 linux32_sys_setfsuid(struct lwp
*l
, const struct linux32_sys_setfsuid_args
*uap
, register_t
*retval
)
485 syscallarg(uid_t) uid;
487 struct linux_sys_setfsuid_args ua
;
489 NETBSD32TO64_UAP(uid
);
491 return linux_sys_setfsuid(l
, &ua
, retval
);
495 linux32_sys_setfsgid(struct lwp
*l
, const struct linux32_sys_setfsgid_args
*uap
, register_t
*retval
)
498 syscallarg(gid_t) gid;
500 struct linux_sys_setfsgid_args ua
;
502 NETBSD32TO64_UAP(gid
);
504 return linux_sys_setfsgid(l
, &ua
, retval
);
511 linux32_sys_pread(struct lwp
*l
,
512 const struct linux32_sys_pread_args
*uap
, register_t
*retval
)
516 syscallarg(netbsd32_voidp) buf;
517 syscallarg(netbsd32_size_t) nbyte;
518 syscallarg(linux32_off_t) offset;
520 struct sys_pread_args pra
;
522 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
523 SCARG(&pra
, buf
) = SCARG_P32(uap
, buf
);
524 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
525 SCARG(&pra
, offset
) = SCARG(uap
, offset
);
527 return sys_pread(l
, &pra
, retval
);
534 linux32_sys_pwrite(struct lwp
*l
,
535 const struct linux32_sys_pwrite_args
*uap
, register_t
*retval
)
539 syscallarg(const netbsd32_voidp) buf;
540 syscallarg(netbsd32_size_t) nbyte;
541 syscallarg(linux32_off_t) offset;
543 struct sys_pwrite_args pra
;
545 SCARG(&pra
, fd
) = SCARG(uap
, fd
);
546 SCARG(&pra
, buf
) = SCARG_P32(uap
, buf
);
547 SCARG(&pra
, nbyte
) = SCARG(uap
, nbyte
);
548 SCARG(&pra
, offset
) = SCARG(uap
, offset
);
550 return sys_pwrite(l
, &pra
, retval
);