File: | compat/freebsd32/freebsd32_ioctl.c |
Warning: | line 327, column 16 Copies out a struct with a partially unsanitized field |
1 | /*- | |||
2 | * Copyright (c) 2008 David E. O'Brien | |||
3 | * All rights reserved. | |||
4 | * | |||
5 | * Redistribution and use in source and binary forms, with or without | |||
6 | * modification, are permitted provided that the following conditions | |||
7 | * are met: | |||
8 | * 1. Redistributions of source code must retain the above copyright | |||
9 | * notice, this list of conditions and the following disclaimer. | |||
10 | * 2. Redistributions in binary form must reproduce the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer in the | |||
12 | * documentation and/or other materials provided with the distribution. | |||
13 | * 3. Neither the name of the author nor the names of its contributors | |||
14 | * may be used to endorse or promote products derived from this software | |||
15 | * without specific prior written permission. | |||
16 | * | |||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
27 | * SUCH DAMAGE. | |||
28 | */ | |||
29 | ||||
30 | #include <sys/cdefs.h> | |||
31 | __FBSDID("$FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_ioctl.c 266981 2014-06-02 19:53:53Z mav $")__asm__(".ident\t\"" "$FreeBSD: releng/11.0/sys/compat/freebsd32/freebsd32_ioctl.c 266981 2014-06-02 19:53:53Z mav $" "\""); | |||
32 | ||||
33 | #include "opt_compat.h" | |||
34 | ||||
35 | #include <sys/param.h> | |||
36 | #include <sys/capsicum.h> | |||
37 | #include <sys/cdio.h> | |||
38 | #include <sys/fcntl.h> | |||
39 | #include <sys/filio.h> | |||
40 | #include <sys/file.h> | |||
41 | #include <sys/ioccom.h> | |||
42 | #include <sys/malloc.h> | |||
43 | #include <sys/mdioctl.h> | |||
44 | #include <sys/memrange.h> | |||
45 | #include <sys/pciio.h> | |||
46 | #include <sys/proc.h> | |||
47 | #include <sys/syscall.h> | |||
48 | #include <sys/syscallsubr.h> | |||
49 | #include <sys/sysctl.h> | |||
50 | #include <sys/sysent.h> | |||
51 | #include <sys/sysproto.h> | |||
52 | #include <sys/systm.h> | |||
53 | ||||
54 | #include <compat/freebsd32/freebsd32.h> | |||
55 | #include <compat/freebsd32/freebsd32_ioctl.h> | |||
56 | #include <compat/freebsd32/freebsd32_proto.h> | |||
57 | ||||
58 | /* Cannot get exact size in 64-bit due to alignment issue of entire struct. */ | |||
59 | CTASSERT((sizeof(struct md_ioctl32)+4) == 436)_Static_assert((sizeof(struct md_ioctl32)+4) == 436, "compile-time assertion failed" ); | |||
60 | CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8)_Static_assert(sizeof(struct ioc_read_toc_entry32) == 8, "compile-time assertion failed" ); | |||
61 | CTASSERT(sizeof(struct ioc_toc_header32) == 4)_Static_assert(sizeof(struct ioc_toc_header32) == 4, "compile-time assertion failed" ); | |||
62 | CTASSERT(sizeof(struct mem_range_op32) == 12)_Static_assert(sizeof(struct mem_range_op32) == 12, "compile-time assertion failed" ); | |||
63 | CTASSERT(sizeof(struct pci_conf_io32) == 36)_Static_assert(sizeof(struct pci_conf_io32) == 36, "compile-time assertion failed" ); | |||
64 | CTASSERT(sizeof(struct pci_match_conf32) == 44)_Static_assert(sizeof(struct pci_match_conf32) == 44, "compile-time assertion failed" ); | |||
65 | CTASSERT(sizeof(struct pci_conf32) == 44)_Static_assert(sizeof(struct pci_conf32) == 44, "compile-time assertion failed" ); | |||
66 | ||||
67 | ||||
68 | static int | |||
69 | freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap, | |||
70 | struct file *fp) | |||
71 | { | |||
72 | struct md_ioctl mdv; | |||
73 | struct md_ioctl32 md32; | |||
74 | u_long com = 0; | |||
75 | int i, error; | |||
76 | ||||
77 | if (uap->com & IOC_IN0x80000000) { | |||
78 | if ((error = copyin(uap->data, &md32, sizeof(md32)))) { | |||
79 | return (error); | |||
80 | } | |||
81 | CP(md32, mdv, md_version)do { (mdv).md_version = (md32).md_version; } while (0); | |||
82 | CP(md32, mdv, md_unit)do { (mdv).md_unit = (md32).md_unit; } while (0); | |||
83 | CP(md32, mdv, md_type)do { (mdv).md_type = (md32).md_type; } while (0); | |||
84 | PTRIN_CP(md32, mdv, md_file)do { (mdv).md_file = (void *)(uintptr_t) ((md32).md_file); } while (0); | |||
85 | CP(md32, mdv, md_mediasize)do { (mdv).md_mediasize = (md32).md_mediasize; } while (0); | |||
86 | CP(md32, mdv, md_sectorsize)do { (mdv).md_sectorsize = (md32).md_sectorsize; } while (0); | |||
87 | CP(md32, mdv, md_options)do { (mdv).md_options = (md32).md_options; } while (0); | |||
88 | CP(md32, mdv, md_base)do { (mdv).md_base = (md32).md_base; } while (0); | |||
89 | CP(md32, mdv, md_fwheads)do { (mdv).md_fwheads = (md32).md_fwheads; } while (0); | |||
90 | CP(md32, mdv, md_fwsectors)do { (mdv).md_fwsectors = (md32).md_fwsectors; } while (0); | |||
91 | } else if (uap->com & IOC_OUT0x40000000) { | |||
92 | /* | |||
93 | * Zero the buffer so the user always | |||
94 | * gets back something deterministic. | |||
95 | */ | |||
96 | bzero(&mdv, sizeof mdv); | |||
97 | } | |||
98 | ||||
99 | switch (uap->com) { | |||
100 | case MDIOCATTACH_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (0))): | |||
101 | com = MDIOCATTACH((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl)) & ((1 << 13) - 1)) << 16) | ((('m' )) << 8) | ((0)))); | |||
102 | break; | |||
103 | case MDIOCDETACH_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (1))): | |||
104 | com = MDIOCDETACH((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl)) & ((1 << 13) - 1)) << 16) | ((('m' )) << 8) | ((1)))); | |||
105 | break; | |||
106 | case MDIOCQUERY_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (2))): | |||
107 | com = MDIOCQUERY((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl)) & ((1 << 13) - 1)) << 16) | ((('m' )) << 8) | ((2)))); | |||
108 | break; | |||
109 | case MDIOCLIST_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (3))): | |||
110 | com = MDIOCLIST((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl)) & ((1 << 13) - 1)) << 16) | ((('m' )) << 8) | ((3)))); | |||
111 | break; | |||
112 | default: | |||
113 | panic("%s: unknown MDIOC %#x", __func__, uap->com); | |||
114 | } | |||
115 | error = fo_ioctl(fp, com, (caddr_t)&mdv, td->td_ucred, td); | |||
116 | if (error == 0 && (com & IOC_OUT0x40000000)) { | |||
117 | CP(mdv, md32, md_version)do { (md32).md_version = (mdv).md_version; } while (0); | |||
118 | CP(mdv, md32, md_unit)do { (md32).md_unit = (mdv).md_unit; } while (0); | |||
119 | CP(mdv, md32, md_type)do { (md32).md_type = (mdv).md_type; } while (0); | |||
120 | PTROUT_CP(mdv, md32, md_file)do { (md32).md_file = (u_int32_t)(uintptr_t) ((mdv).md_file); } while (0); | |||
121 | CP(mdv, md32, md_mediasize)do { (md32).md_mediasize = (mdv).md_mediasize; } while (0); | |||
122 | CP(mdv, md32, md_sectorsize)do { (md32).md_sectorsize = (mdv).md_sectorsize; } while (0); | |||
123 | CP(mdv, md32, md_options)do { (md32).md_options = (mdv).md_options; } while (0); | |||
124 | CP(mdv, md32, md_base)do { (md32).md_base = (mdv).md_base; } while (0); | |||
125 | CP(mdv, md32, md_fwheads)do { (md32).md_fwheads = (mdv).md_fwheads; } while (0); | |||
126 | CP(mdv, md32, md_fwsectors)do { (md32).md_fwsectors = (mdv).md_fwsectors; } while (0); | |||
127 | if (com == MDIOCLIST((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl)) & ((1 << 13) - 1)) << 16) | ((('m' )) << 8) | ((3))))) { | |||
128 | /* | |||
129 | * Use MDNPAD, and not MDNPAD32. Padding is | |||
130 | * allocated and used by compat32 ABI. | |||
131 | */ | |||
132 | for (i = 0; i < MDNPAD97; i++) | |||
133 | CP(mdv, md32, md_pad[i])do { (md32).md_pad[i] = (mdv).md_pad[i]; } while (0); | |||
134 | } | |||
135 | error = copyout(&md32, uap->data, sizeof(md32)); | |||
136 | } | |||
137 | return error; | |||
138 | } | |||
139 | ||||
140 | ||||
141 | static int | |||
142 | freebsd32_ioctl_ioc_toc_header(struct thread *td, | |||
143 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
144 | { | |||
145 | struct ioc_toc_header toch; | |||
146 | struct ioc_toc_header32 toch32; | |||
147 | int error; | |||
148 | ||||
149 | if ((error = copyin(uap->data, &toch32, sizeof(toch32)))) | |||
150 | return (error); | |||
151 | CP(toch32, toch, len)do { (toch).len = (toch32).len; } while (0); | |||
152 | CP(toch32, toch, starting_track)do { (toch).starting_track = (toch32).starting_track; } while (0); | |||
153 | CP(toch32, toch, ending_track)do { (toch).ending_track = (toch32).ending_track; } while (0); | |||
154 | error = fo_ioctl(fp, CDIOREADTOCHEADER((unsigned long) ((0x40000000) | (((sizeof(struct ioc_toc_header )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((4)))), (caddr_t)&toch, | |||
155 | td->td_ucred, td); | |||
156 | return (error); | |||
157 | } | |||
158 | ||||
159 | ||||
160 | static int | |||
161 | freebsd32_ioctl_ioc_read_toc(struct thread *td, | |||
162 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
163 | { | |||
164 | struct ioc_read_toc_entry toce; | |||
165 | struct ioc_read_toc_entry32 toce32; | |||
166 | int error; | |||
167 | ||||
168 | if ((error = copyin(uap->data, &toce32, sizeof(toce32)))) | |||
169 | return (error); | |||
170 | CP(toce32, toce, address_format)do { (toce).address_format = (toce32).address_format; } while (0); | |||
171 | CP(toce32, toce, starting_track)do { (toce).starting_track = (toce32).starting_track; } while (0); | |||
172 | CP(toce32, toce, data_len)do { (toce).data_len = (toce32).data_len; } while (0); | |||
173 | PTRIN_CP(toce32, toce, data)do { (toce).data = (void *)(uintptr_t) ((toce32).data); } while (0); | |||
174 | ||||
175 | if ((error = fo_ioctl(fp, CDIOREADTOCENTRYS((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct ioc_read_toc_entry)) & ((1 << 13) - 1)) << 16 ) | ((('c')) << 8) | ((5)))), (caddr_t)&toce, | |||
176 | td->td_ucred, td))) { | |||
177 | CP(toce, toce32, address_format)do { (toce32).address_format = (toce).address_format; } while (0); | |||
178 | CP(toce, toce32, starting_track)do { (toce32).starting_track = (toce).starting_track; } while (0); | |||
179 | CP(toce, toce32, data_len)do { (toce32).data_len = (toce).data_len; } while (0); | |||
180 | PTROUT_CP(toce, toce32, data)do { (toce32).data = (u_int32_t)(uintptr_t) ((toce).data); } while (0); | |||
181 | error = copyout(&toce32, uap->data, sizeof(toce32)); | |||
182 | } | |||
183 | return error; | |||
184 | } | |||
185 | ||||
186 | static int | |||
187 | freebsd32_ioctl_fiodgname(struct thread *td, | |||
188 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
189 | { | |||
190 | struct fiodgname_arg fgn; | |||
191 | struct fiodgname_arg32 fgn32; | |||
192 | int error; | |||
193 | ||||
194 | if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0) | |||
195 | return (error); | |||
196 | CP(fgn32, fgn, len)do { (fgn).len = (fgn32).len; } while (0); | |||
197 | PTRIN_CP(fgn32, fgn, buf)do { (fgn).buf = (void *)(uintptr_t) ((fgn32).buf); } while ( 0); | |||
198 | error = fo_ioctl(fp, FIODGNAME((unsigned long) ((0x80000000) | (((sizeof(struct fiodgname_arg )) & ((1 << 13) - 1)) << 16) | ((('f')) << 8) | ((120)))), (caddr_t)&fgn, td->td_ucred, td); | |||
199 | return (error); | |||
200 | } | |||
201 | ||||
202 | static int | |||
203 | freebsd32_ioctl_memrange(struct thread *td, | |||
204 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
205 | { | |||
206 | struct mem_range_op mro; | |||
207 | struct mem_range_op32 mro32; | |||
208 | int error; | |||
209 | u_long com; | |||
210 | ||||
211 | if ((error = copyin(uap->data, &mro32, sizeof(mro32))) != 0) | |||
212 | return (error); | |||
213 | ||||
214 | PTRIN_CP(mro32, mro, mo_desc)do { (mro).mo_desc = (void *)(uintptr_t) ((mro32).mo_desc); } while (0); | |||
215 | CP(mro32, mro, mo_arg[0])do { (mro).mo_arg[0] = (mro32).mo_arg[0]; } while (0); | |||
216 | CP(mro32, mro, mo_arg[1])do { (mro).mo_arg[1] = (mro32).mo_arg[1]; } while (0); | |||
217 | ||||
218 | com = 0; | |||
219 | switch (uap->com) { | |||
220 | case MEMRANGE_GET32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct mem_range_op32)) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((50)))): | |||
221 | com = MEMRANGE_GET((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct mem_range_op)) & ((1 << 13) - 1)) << 16) | ( (('m')) << 8) | ((50)))); | |||
222 | break; | |||
223 | ||||
224 | case MEMRANGE_SET32((unsigned long) ((0x80000000) | (((sizeof(struct mem_range_op32 )) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((51)))): | |||
225 | com = MEMRANGE_SET((unsigned long) ((0x80000000) | (((sizeof(struct mem_range_op )) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((51)))); | |||
226 | break; | |||
227 | ||||
228 | default: | |||
229 | panic("%s: unknown MEMRANGE %#x", __func__, uap->com); | |||
230 | } | |||
231 | ||||
232 | if ((error = fo_ioctl(fp, com, (caddr_t)&mro, td->td_ucred, td)) != 0) | |||
233 | return (error); | |||
234 | ||||
235 | if ( (com & IOC_OUT0x40000000) ) { | |||
236 | CP(mro, mro32, mo_arg[0])do { (mro32).mo_arg[0] = (mro).mo_arg[0]; } while (0); | |||
237 | CP(mro, mro32, mo_arg[1])do { (mro32).mo_arg[1] = (mro).mo_arg[1]; } while (0); | |||
238 | ||||
239 | error = copyout(&mro32, uap->data, sizeof(mro32)); | |||
240 | } | |||
241 | ||||
242 | return (error); | |||
243 | } | |||
244 | ||||
245 | static int | |||
246 | freebsd32_ioctl_pciocgetconf(struct thread *td, | |||
247 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
248 | { | |||
249 | struct pci_conf_io pci; | |||
250 | struct pci_conf_io32 pci32; | |||
251 | struct pci_match_conf32 pmc32; | |||
252 | struct pci_match_conf32 *pmc32p; | |||
253 | struct pci_match_conf pmc; | |||
254 | struct pci_match_conf *pmcp; | |||
255 | struct pci_conf32 pc32; | |||
256 | struct pci_conf32 *pc32p; | |||
257 | struct pci_conf pc; | |||
258 | struct pci_conf *pcp; | |||
259 | u_int32_t i; | |||
260 | u_int32_t npat_to_convert; | |||
261 | u_int32_t nmatch_to_convert; | |||
262 | vm_offset_t addr; | |||
263 | int error; | |||
264 | ||||
265 | if ((error = copyin(uap->data, &pci32, sizeof(pci32))) != 0) | |||
| ||||
266 | return (error); | |||
267 | ||||
268 | CP(pci32, pci, num_patterns)do { (pci).num_patterns = (pci32).num_patterns; } while (0); | |||
269 | CP(pci32, pci, offset)do { (pci).offset = (pci32).offset; } while (0); | |||
270 | CP(pci32, pci, generation)do { (pci).generation = (pci32).generation; } while (0); | |||
271 | ||||
272 | npat_to_convert = pci32.pat_buf_len / sizeof(struct pci_match_conf32); | |||
273 | pci.pat_buf_len = npat_to_convert * sizeof(struct pci_match_conf); | |||
274 | pci.patterns = NULL((void *)0); | |||
275 | nmatch_to_convert = pci32.match_buf_len / sizeof(struct pci_conf32); | |||
276 | pci.match_buf_len = nmatch_to_convert * sizeof(struct pci_conf); | |||
277 | pci.matches = NULL((void *)0); | |||
278 | ||||
279 | if ((error = copyout_map(td, &addr, pci.pat_buf_len)) != 0) | |||
280 | goto cleanup; | |||
281 | pci.patterns = (struct pci_match_conf *)addr; | |||
282 | if ((error = copyout_map(td, &addr, pci.match_buf_len)) != 0) | |||
283 | goto cleanup; | |||
284 | pci.matches = (struct pci_conf *)addr; | |||
285 | ||||
286 | npat_to_convert = min(npat_to_convert, pci.num_patterns); | |||
287 | ||||
288 | for (i = 0, pmc32p = (struct pci_match_conf32 *)PTRIN(pci32.patterns)(void *)(uintptr_t) (pci32.patterns), | |||
289 | pmcp = pci.patterns; | |||
290 | i < npat_to_convert; i++, pmc32p++, pmcp++) { | |||
291 | if ((error = copyin(pmc32p, &pmc32, sizeof(pmc32))) != 0) | |||
292 | goto cleanup; | |||
293 | CP(pmc32,pmc,pc_sel)do { (pmc).pc_sel = (pmc32).pc_sel; } while (0); | |||
294 | strlcpy(pmc.pd_name, pmc32.pd_name, sizeof(pmc.pd_name)); | |||
295 | CP(pmc32,pmc,pd_unit)do { (pmc).pd_unit = (pmc32).pd_unit; } while (0); | |||
296 | CP(pmc32,pmc,pc_vendor)do { (pmc).pc_vendor = (pmc32).pc_vendor; } while (0); | |||
297 | CP(pmc32,pmc,pc_device)do { (pmc).pc_device = (pmc32).pc_device; } while (0); | |||
298 | CP(pmc32,pmc,pc_class)do { (pmc).pc_class = (pmc32).pc_class; } while (0); | |||
299 | CP(pmc32,pmc,flags)do { (pmc).flags = (pmc32).flags; } while (0); | |||
300 | if ((error = copyout(&pmc, pmcp, sizeof(pmc))) != 0) | |||
301 | goto cleanup; | |||
302 | } | |||
303 | ||||
304 | if ((error = fo_ioctl(fp, PCIOCGETCONF((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct pci_conf_io)) & ((1 << 13) - 1)) << 16) | (( ('p')) << 8) | ((5)))), (caddr_t)&pci, | |||
305 | td->td_ucred, td)) != 0) | |||
306 | goto cleanup; | |||
307 | ||||
308 | nmatch_to_convert = min(nmatch_to_convert, pci.num_matches); | |||
309 | ||||
310 | for (i = 0, pcp = pci.matches, | |||
311 | pc32p = (struct pci_conf32 *)PTRIN(pci32.matches)(void *)(uintptr_t) (pci32.matches); | |||
312 | i < nmatch_to_convert; i++, pcp++, pc32p++) { | |||
313 | if ((error = copyin(pcp, &pc, sizeof(pc))) != 0) | |||
314 | goto cleanup; | |||
315 | CP(pc,pc32,pc_sel)do { (pc32).pc_sel = (pc).pc_sel; } while (0); | |||
316 | CP(pc,pc32,pc_hdr)do { (pc32).pc_hdr = (pc).pc_hdr; } while (0); | |||
317 | CP(pc,pc32,pc_subvendor)do { (pc32).pc_subvendor = (pc).pc_subvendor; } while (0); | |||
318 | CP(pc,pc32,pc_subdevice)do { (pc32).pc_subdevice = (pc).pc_subdevice; } while (0); | |||
319 | CP(pc,pc32,pc_vendor)do { (pc32).pc_vendor = (pc).pc_vendor; } while (0); | |||
320 | CP(pc,pc32,pc_device)do { (pc32).pc_device = (pc).pc_device; } while (0); | |||
321 | CP(pc,pc32,pc_class)do { (pc32).pc_class = (pc).pc_class; } while (0); | |||
322 | CP(pc,pc32,pc_subclass)do { (pc32).pc_subclass = (pc).pc_subclass; } while (0); | |||
323 | CP(pc,pc32,pc_progif)do { (pc32).pc_progif = (pc).pc_progif; } while (0); | |||
324 | CP(pc,pc32,pc_revid)do { (pc32).pc_revid = (pc).pc_revid; } while (0); | |||
325 | strlcpy(pc32.pd_name, pc.pd_name, sizeof(pc32.pd_name)); | |||
326 | CP(pc,pc32,pd_unit)do { (pc32).pd_unit = (pc).pd_unit; } while (0); | |||
327 | if ((error = copyout(&pc32, pc32p, sizeof(pc32))) != 0) | |||
| ||||
328 | goto cleanup; | |||
329 | } | |||
330 | ||||
331 | CP(pci, pci32, num_matches)do { (pci32).num_matches = (pci).num_matches; } while (0); | |||
332 | CP(pci, pci32, offset)do { (pci32).offset = (pci).offset; } while (0); | |||
333 | CP(pci, pci32, generation)do { (pci32).generation = (pci).generation; } while (0); | |||
334 | CP(pci, pci32, status)do { (pci32).status = (pci).status; } while (0); | |||
335 | ||||
336 | error = copyout(&pci32, uap->data, sizeof(pci32)); | |||
337 | ||||
338 | cleanup: | |||
339 | if (pci.patterns) | |||
340 | copyout_unmap(td, (vm_offset_t)pci.patterns, pci.pat_buf_len); | |||
341 | if (pci.matches) | |||
342 | copyout_unmap(td, (vm_offset_t)pci.matches, pci.match_buf_len); | |||
343 | ||||
344 | return (error); | |||
345 | } | |||
346 | ||||
347 | static int | |||
348 | freebsd32_ioctl_sg(struct thread *td, | |||
349 | struct freebsd32_ioctl_args *uap, struct file *fp) | |||
350 | { | |||
351 | struct sg_io_hdr io; | |||
352 | struct sg_io_hdr32 io32; | |||
353 | int error; | |||
354 | ||||
355 | if ((error = copyin(uap->data, &io32, sizeof(io32))) != 0) | |||
356 | return (error); | |||
357 | ||||
358 | CP(io32, io, interface_id)do { (io).interface_id = (io32).interface_id; } while (0); | |||
359 | CP(io32, io, dxfer_direction)do { (io).dxfer_direction = (io32).dxfer_direction; } while ( 0); | |||
360 | CP(io32, io, cmd_len)do { (io).cmd_len = (io32).cmd_len; } while (0); | |||
361 | CP(io32, io, mx_sb_len)do { (io).mx_sb_len = (io32).mx_sb_len; } while (0); | |||
362 | CP(io32, io, iovec_count)do { (io).iovec_count = (io32).iovec_count; } while (0); | |||
363 | CP(io32, io, dxfer_len)do { (io).dxfer_len = (io32).dxfer_len; } while (0); | |||
364 | PTRIN_CP(io32, io, dxferp)do { (io).dxferp = (void *)(uintptr_t) ((io32).dxferp); } while (0); | |||
365 | PTRIN_CP(io32, io, cmdp)do { (io).cmdp = (void *)(uintptr_t) ((io32).cmdp); } while ( 0); | |||
366 | PTRIN_CP(io32, io, sbp)do { (io).sbp = (void *)(uintptr_t) ((io32).sbp); } while (0); | |||
367 | CP(io32, io, timeout)do { (io).timeout = (io32).timeout; } while (0); | |||
368 | CP(io32, io, flags)do { (io).flags = (io32).flags; } while (0); | |||
369 | CP(io32, io, pack_id)do { (io).pack_id = (io32).pack_id; } while (0); | |||
370 | PTRIN_CP(io32, io, usr_ptr)do { (io).usr_ptr = (void *)(uintptr_t) ((io32).usr_ptr); } while (0); | |||
371 | CP(io32, io, status)do { (io).status = (io32).status; } while (0); | |||
372 | CP(io32, io, masked_status)do { (io).masked_status = (io32).masked_status; } while (0); | |||
373 | CP(io32, io, msg_status)do { (io).msg_status = (io32).msg_status; } while (0); | |||
374 | CP(io32, io, sb_len_wr)do { (io).sb_len_wr = (io32).sb_len_wr; } while (0); | |||
375 | CP(io32, io, host_status)do { (io).host_status = (io32).host_status; } while (0); | |||
376 | CP(io32, io, driver_status)do { (io).driver_status = (io32).driver_status; } while (0); | |||
377 | CP(io32, io, resid)do { (io).resid = (io32).resid; } while (0); | |||
378 | CP(io32, io, duration)do { (io).duration = (io32).duration; } while (0); | |||
379 | CP(io32, io, info)do { (io).info = (io32).info; } while (0); | |||
380 | ||||
381 | if ((error = fo_ioctl(fp, SG_IO((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct sg_io_hdr)) & ((1 << 13) - 1)) << 16) | ((('"' )) << 8) | ((0x85)))), (caddr_t)&io, td->td_ucred, td)) != 0) | |||
382 | return (error); | |||
383 | ||||
384 | CP(io, io32, interface_id)do { (io32).interface_id = (io).interface_id; } while (0); | |||
385 | CP(io, io32, dxfer_direction)do { (io32).dxfer_direction = (io).dxfer_direction; } while ( 0); | |||
386 | CP(io, io32, cmd_len)do { (io32).cmd_len = (io).cmd_len; } while (0); | |||
387 | CP(io, io32, mx_sb_len)do { (io32).mx_sb_len = (io).mx_sb_len; } while (0); | |||
388 | CP(io, io32, iovec_count)do { (io32).iovec_count = (io).iovec_count; } while (0); | |||
389 | CP(io, io32, dxfer_len)do { (io32).dxfer_len = (io).dxfer_len; } while (0); | |||
390 | PTROUT_CP(io, io32, dxferp)do { (io32).dxferp = (u_int32_t)(uintptr_t) ((io).dxferp); } while (0); | |||
391 | PTROUT_CP(io, io32, cmdp)do { (io32).cmdp = (u_int32_t)(uintptr_t) ((io).cmdp); } while (0); | |||
392 | PTROUT_CP(io, io32, sbp)do { (io32).sbp = (u_int32_t)(uintptr_t) ((io).sbp); } while ( 0); | |||
393 | CP(io, io32, timeout)do { (io32).timeout = (io).timeout; } while (0); | |||
394 | CP(io, io32, flags)do { (io32).flags = (io).flags; } while (0); | |||
395 | CP(io, io32, pack_id)do { (io32).pack_id = (io).pack_id; } while (0); | |||
396 | PTROUT_CP(io, io32, usr_ptr)do { (io32).usr_ptr = (u_int32_t)(uintptr_t) ((io).usr_ptr); } while (0); | |||
397 | CP(io, io32, status)do { (io32).status = (io).status; } while (0); | |||
398 | CP(io, io32, masked_status)do { (io32).masked_status = (io).masked_status; } while (0); | |||
399 | CP(io, io32, msg_status)do { (io32).msg_status = (io).msg_status; } while (0); | |||
400 | CP(io, io32, sb_len_wr)do { (io32).sb_len_wr = (io).sb_len_wr; } while (0); | |||
401 | CP(io, io32, host_status)do { (io32).host_status = (io).host_status; } while (0); | |||
402 | CP(io, io32, driver_status)do { (io32).driver_status = (io).driver_status; } while (0); | |||
403 | CP(io, io32, resid)do { (io32).resid = (io).resid; } while (0); | |||
404 | CP(io, io32, duration)do { (io32).duration = (io).duration; } while (0); | |||
405 | CP(io, io32, info)do { (io32).info = (io).info; } while (0); | |||
406 | ||||
407 | error = copyout(&io32, uap->data, sizeof(io32)); | |||
408 | ||||
409 | return (error); | |||
410 | } | |||
411 | ||||
412 | int | |||
413 | freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) | |||
414 | { | |||
415 | struct ioctl_args ap /*{ | |||
416 | int fd; | |||
417 | u_long com; | |||
418 | caddr_t data; | |||
419 | }*/ ; | |||
420 | struct file *fp; | |||
421 | cap_rights_t rights; | |||
422 | int error; | |||
423 | ||||
424 | error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL)__cap_rights_init(0, &rights, ((1ULL << (57 + (1))) | (0x0000000000000080ULL)), 0ULL), &fp); | |||
425 | if (error != 0) | |||
426 | return (error); | |||
427 | if ((fp->f_flag & (FREAD0x0001 | FWRITE0x0002)) == 0) { | |||
428 | fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td)) : _fnoop()); | |||
429 | return (EBADF9); | |||
430 | } | |||
431 | ||||
432 | switch (uap->com) { | |||
433 | case MDIOCATTACH_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (0))): /* FALLTHROUGH */ | |||
434 | case MDIOCDETACH_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (1))): /* FALLTHROUGH */ | |||
435 | case MDIOCQUERY_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (2))): /* FALLTHROUGH */ | |||
436 | case MDIOCLIST_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct md_ioctl32) + 4) & ((1 << 13) - 1)) << 16) | (('m') << 8) | (3))): | |||
437 | error = freebsd32_ioctl_md(td, uap, fp); | |||
438 | break; | |||
439 | ||||
440 | case CDIOREADTOCENTRYS_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct ioc_read_toc_entry32)) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((5)))): | |||
441 | error = freebsd32_ioctl_ioc_read_toc(td, uap, fp); | |||
442 | break; | |||
443 | ||||
444 | case CDIOREADTOCHEADER_32((unsigned long) ((0x40000000) | (((sizeof(struct ioc_toc_header32 )) & ((1 << 13) - 1)) << 16) | ((('c')) << 8) | ((4)))): | |||
445 | error = freebsd32_ioctl_ioc_toc_header(td, uap, fp); | |||
446 | break; | |||
447 | ||||
448 | case FIODGNAME_32((unsigned long) ((0x80000000) | (((sizeof(struct fiodgname_arg32 )) & ((1 << 13) - 1)) << 16) | ((('f')) << 8) | ((120)))): | |||
449 | error = freebsd32_ioctl_fiodgname(td, uap, fp); | |||
450 | break; | |||
451 | ||||
452 | case MEMRANGE_GET32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct mem_range_op32)) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((50)))): /* FALLTHROUGH */ | |||
453 | case MEMRANGE_SET32((unsigned long) ((0x80000000) | (((sizeof(struct mem_range_op32 )) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((51)))): | |||
454 | error = freebsd32_ioctl_memrange(td, uap, fp); | |||
455 | break; | |||
456 | ||||
457 | case PCIOCGETCONF_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct pci_conf_io32)) & ((1 << 13) - 1)) << 16) | ( (('p')) << 8) | ((5)))): | |||
458 | error = freebsd32_ioctl_pciocgetconf(td, uap, fp); | |||
459 | break; | |||
460 | ||||
461 | case SG_IO_32((unsigned long) (((0x80000000|0x40000000)) | (((sizeof(struct sg_io_hdr32)) & ((1 << 13) - 1)) << 16) | (( ('"')) << 8) | ((0x85)))): | |||
462 | error = freebsd32_ioctl_sg(td, uap, fp); | |||
463 | break; | |||
464 | ||||
465 | default: | |||
466 | fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td)) : _fnoop()); | |||
467 | ap.fd = uap->fd; | |||
468 | ap.com = uap->com; | |||
469 | PTRIN_CP(*uap, ap, data)do { (ap).data = (void *)(uintptr_t) ((*uap).data); } while ( 0); | |||
470 | return sys_ioctl(td, &ap); | |||
471 | } | |||
472 | ||||
473 | fdrop(fp, td)(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td)) : _fnoop()); | |||
474 | return error; | |||
475 | } |