linux32_misc.c revision 1.9.10.5 1 /* $NetBSD: linux32_misc.c,v 1.9.10.5 2010/08/11 22:53:09 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 1995, 1998, 1999 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 * by Edgar Fu\ss, Mathematisches Institut der Uni Bonn.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 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.
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: linux32_misc.c,v 1.9.10.5 2010/08/11 22:53:09 yamt Exp $");
36
37 #include <sys/param.h>
38 #include <sys/proc.h>
39 #include <sys/time.h>
40 #include <sys/types.h>
41 #include <sys/malloc.h>
42 #include <sys/fstypes.h>
43 #include <sys/vfs_syscalls.h>
44 #include <sys/ptrace.h>
45 #include <sys/syscall.h>
46
47 #include <compat/netbsd32/netbsd32.h>
48 #include <compat/netbsd32/netbsd32_syscallargs.h>
49
50 #include <compat/linux32/common/linux32_types.h>
51 #include <compat/linux32/common/linux32_signal.h>
52 #include <compat/linux32/linux32_syscallargs.h>
53
54 #include <compat/linux/common/linux_ptrace.h>
55 #include <compat/linux/common/linux_types.h>
56 #include <compat/linux/common/linux_emuldata.h>
57 #include <compat/linux/common/linux_signal.h>
58 #include <compat/linux/common/linux_misc.h>
59 #include <compat/linux/common/linux_statfs.h>
60 #include <compat/linux/common/linux_ipc.h>
61 #include <compat/linux/common/linux_sem.h>
62 #include <compat/linux/common/linux_futex.h>
63 #include <compat/linux/linux_syscallargs.h>
64
65 extern const struct linux_mnttypes linux_fstypes[];
66 extern const int linux_fstypes_cnt;
67
68 void linux32_to_native_timespec(struct timespec *, struct linux32_timespec *);
69
70 /*
71 * Implement the fs stat functions. Straightforward.
72 */
73 int
74 linux32_sys_statfs(struct lwp *l, const struct linux32_sys_statfs_args *uap, register_t *retval)
75 {
76 /* {
77 syscallarg(const netbsd32_charp char) path;
78 syscallarg(linux32_statfsp) sp;
79 } */
80 struct statvfs *sb;
81 struct linux_statfs ltmp;
82 int error;
83
84 sb = STATVFSBUF_GET();
85 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
86 if (error == 0) {
87 bsd_to_linux_statfs(sb, <mp);
88 error = copyout(<mp, SCARG_P32(uap, sp), sizeof ltmp);
89 }
90
91 STATVFSBUF_PUT(sb);
92 return error;
93 }
94
95 int
96 linux32_sys_fstatfs(struct lwp *l, const struct linux32_sys_fstatfs_args *uap, register_t *retval)
97 {
98 /* {
99 syscallarg(int) fd;
100 syscallarg(linux32_statfsp) sp;
101 } */
102 struct statvfs *sb;
103 struct linux_statfs ltmp;
104 int error;
105
106 sb = STATVFSBUF_GET();
107 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
108 if (error == 0) {
109 bsd_to_linux_statfs(sb, <mp);
110 error = copyout(<mp, SCARG_P32(uap, sp), sizeof ltmp);
111 }
112 STATVFSBUF_PUT(sb);
113
114 return error;
115 }
116
117 extern const int linux_ptrace_request_map[];
118
119 int
120 linux32_sys_ptrace(struct lwp *l, const struct linux32_sys_ptrace_args *uap, register_t *retval)
121 {
122 /* {
123 i386, m68k, powerpc: T=int
124 alpha, amd64: T=long
125 syscallarg(T) request;
126 syscallarg(T) pid;
127 syscallarg(T) addr;
128 syscallarg(T) data;
129 } */
130 const int *ptr;
131 int request;
132 int error;
133
134 ptr = linux_ptrace_request_map;
135 request = SCARG(uap, request);
136 while (*ptr != -1)
137 if (*ptr++ == request) {
138 struct sys_ptrace_args pta;
139
140 SCARG(&pta, req) = *ptr;
141 SCARG(&pta, pid) = SCARG(uap, pid);
142 SCARG(&pta, addr) = NETBSD32IPTR64(SCARG(uap, addr));
143 SCARG(&pta, data) = SCARG(uap, data);
144
145 /*
146 * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
147 * to continue where the process left off previously.
148 * The same thing is achieved by addr == (void *) 1
149 * on NetBSD, so rewrite 'addr' appropriately.
150 */
151 if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
152 SCARG(&pta, addr) = (void *) 1;
153
154 error = sysent[SYS_ptrace].sy_call(l, &pta, retval);
155 if (error)
156 return error;
157 switch (request) {
158 case LINUX_PTRACE_PEEKTEXT:
159 case LINUX_PTRACE_PEEKDATA:
160 error = copyout (retval,
161 NETBSD32IPTR64(SCARG(uap, data)),
162 sizeof *retval);
163 *retval = SCARG(uap, data);
164 break;
165 default:
166 break;
167 }
168 return error;
169 }
170 else
171 ptr++;
172
173 return EIO;
174 }
175
176 int
177 linux32_sys_personality(struct lwp *l, const struct linux32_sys_personality_args *uap, register_t *retval)
178 {
179 /* {
180 syscallarg(netbsd32_u_long) per;
181 } */
182
183 switch (SCARG(uap, per)) {
184 case LINUX_PER_LINUX:
185 case LINUX_PER_LINUX32:
186 case LINUX_PER_QUERY:
187 break;
188 default:
189 return EINVAL;
190 }
191
192 retval[0] = LINUX_PER_LINUX;
193 return 0;
194 }
195
196 int
197 linux32_sys_futex(struct lwp *l,
198 const struct linux32_sys_futex_args *uap, register_t *retval)
199 {
200 /* {
201 syscallarg(linux32_intp_t) uaddr;
202 syscallarg(int) op;
203 syscallarg(int) val;
204 syscallarg(linux32_timespecp_t) timeout;
205 syscallarg(linux32_intp_t) uaddr2;
206 syscallarg(int) val3;
207 } */
208 struct linux_sys_futex_args ua;
209 struct linux32_timespec lts;
210 struct timespec ts = { 0, 0 };
211 int error;
212
213 NETBSD32TOP_UAP(uaddr, int);
214 NETBSD32TO64_UAP(op);
215 NETBSD32TO64_UAP(val);
216 NETBSD32TOP_UAP(timeout, struct linux_timespec);
217 NETBSD32TOP_UAP(uaddr2, int);
218 NETBSD32TO64_UAP(val3);
219 if ((SCARG(uap, op) & ~LINUX_FUTEX_PRIVATE_FLAG) == LINUX_FUTEX_WAIT &&
220 SCARG_P32(uap, timeout) != NULL) {
221 if ((error = copyin((void *)SCARG_P32(uap, timeout),
222 <s, sizeof(lts))) != 0) {
223 return error;
224 }
225 linux32_to_native_timespec(&ts, <s);
226 }
227 return linux_do_futex(l, &ua, retval, &ts);
228 }
229
230 int
231 linux32_sys_set_robust_list(struct lwp *l,
232 const struct linux32_sys_set_robust_list_args *uap, register_t *retval)
233 {
234 /* {
235 syscallarg(linux32_robust_list_headp_t) head;
236 syscallarg(linux32_size_t) len;
237 } */
238 struct linux_sys_set_robust_list_args ua;
239 struct linux_emuldata *led;
240
241 if (SCARG(uap, len) != 12)
242 return EINVAL;
243
244 NETBSD32TOP_UAP(head, struct robust_list_head);
245 NETBSD32TOX64_UAP(len, size_t);
246
247 led = l->l_emuldata;
248 led->led_robust_head = SCARG(&ua, head);
249 *retval = 0;
250 return 0;
251 }
252
253 int
254 linux32_sys_get_robust_list(struct lwp *l,
255 const struct linux32_sys_get_robust_list_args *uap, register_t *retval)
256 {
257 /* {
258 syscallarg(linux32_robust_list_headpp_t) head;
259 syscallarg(linux32_sizep_t) len;
260 } */
261 struct linux_sys_get_robust_list_args ua;
262
263 NETBSD32TOP_UAP(head, struct robust_list_head *);
264 NETBSD32TOP_UAP(head, size_t *);
265 return linux_sys_get_robust_list(l, &ua, retval);
266 }
267