This source file includes following definitions.
- i386_print_ldt
- i386_get_ldt
- i386_set_ldt
- i386_iopl
- i386_get_ioperm
- i386_set_ioperm
- sys_sysarch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/ioctl.h>
42 #include <sys/file.h>
43 #include <sys/time.h>
44 #include <sys/proc.h>
45 #include <sys/signalvar.h>
46 #include <sys/user.h>
47 #include <sys/uio.h>
48 #include <sys/kernel.h>
49 #include <sys/mtio.h>
50 #include <sys/buf.h>
51 #include <sys/signal.h>
52 #include <sys/malloc.h>
53
54 #include <sys/mount.h>
55 #include <sys/syscallargs.h>
56
57 #include <uvm/uvm_extern.h>
58
59 #include <machine/cpu.h>
60 #include <machine/cpufunc.h>
61 #include <machine/gdt.h>
62 #include <machine/psl.h>
63 #include <machine/reg.h>
64 #include <machine/sysarch.h>
65
66 #ifdef VM86
67 #include <machine/vm86.h>
68 #endif
69
70 extern struct vm_map *kernel_map;
71
72 int i386_iopl(struct proc *, void *, register_t *);
73 int i386_get_ioperm(struct proc *, void *, register_t *);
74 int i386_set_ioperm(struct proc *, void *, register_t *);
75
76 #ifdef USER_LDT
77
78 #ifdef LDT_DEBUG
79 static void i386_print_ldt(int, const struct segment_descriptor *);
80
81 static void
82 i386_print_ldt(int i, const struct segment_descriptor *d)
83 {
84 printf("[%d] lolimit=0x%x, lobase=0x%x, type=%u, dpl=%u, p=%u, "
85 "hilimit=0x%x, xx=%x, def32=%u, gran=%u, hibase=0x%x\n",
86 i, d->sd_lolimit, d->sd_lobase, d->sd_type, d->sd_dpl, d->sd_p,
87 d->sd_hilimit, d->sd_xx, d->sd_def32, d->sd_gran, d->sd_hibase);
88 }
89 #endif
90
91 int
92 i386_get_ldt(struct proc *p, void *args, register_t *retval)
93 {
94 int error;
95 pmap_t pmap = p->p_vmspace->vm_map.pmap;
96 int nldt, num;
97 union descriptor *lp, *cp;
98 struct i386_get_ldt_args ua;
99
100 if (user_ldt_enable == 0)
101 return (ENOSYS);
102
103 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
104 return (error);
105
106 #ifdef LDT_DEBUG
107 printf("i386_get_ldt: start=%d num=%d descs=%p\n", ua.start,
108 ua.num, ua.desc);
109 #endif
110
111 if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
112 ua.start + ua.num > 8192)
113 return (EINVAL);
114
115 cp = malloc(ua.num * sizeof(union descriptor), M_TEMP, M_WAITOK);
116 if (cp == NULL)
117 return ENOMEM;
118
119 simple_lock(&pmap->pm_lock);
120
121 if (pmap->pm_flags & PMF_USER_LDT) {
122 nldt = pmap->pm_ldt_len;
123 lp = pmap->pm_ldt;
124 } else {
125 nldt = NLDT;
126 lp = ldt;
127 }
128
129 if (ua.start > nldt) {
130 simple_unlock(&pmap->pm_lock);
131 free(cp, M_TEMP);
132 return (EINVAL);
133 }
134
135 lp += ua.start;
136 num = min(ua.num, nldt - ua.start);
137 #ifdef LDT_DEBUG
138 {
139 int i;
140 for (i = 0; i < num; i++)
141 i386_print_ldt(i, &lp[i].sd);
142 }
143 #endif
144
145 memcpy(cp, lp, num * sizeof(union descriptor));
146 simple_unlock(&pmap->pm_lock);
147
148 error = copyout(cp, ua.desc, num * sizeof(union descriptor));
149 if (error == 0)
150 *retval = num;
151
152 free(cp, M_TEMP);
153 return (error);
154 }
155
156 int
157 i386_set_ldt(struct proc *p, void *args, register_t *retval)
158 {
159 int error, i, n;
160 struct pcb *pcb = &p->p_addr->u_pcb;
161 pmap_t pmap = p->p_vmspace->vm_map.pmap;
162 struct i386_set_ldt_args ua;
163 union descriptor *descv;
164 size_t old_len, new_len, ldt_len;
165 union descriptor *old_ldt, *new_ldt;
166
167 if (user_ldt_enable == 0)
168 return (ENOSYS);
169
170 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
171 return (error);
172
173 if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
174 ua.start + ua.num > 8192)
175 return (EINVAL);
176
177 descv = malloc(sizeof (*descv) * ua.num, M_TEMP, M_NOWAIT);
178 if (descv == NULL)
179 return (ENOMEM);
180
181 if ((error = copyin(ua.desc, descv, sizeof (*descv) * ua.num)) != 0)
182 goto out;
183
184
185 for (i = 0; i < ua.num; i++) {
186 union descriptor *desc = &descv[i];
187
188 switch (desc->sd.sd_type) {
189 case SDT_SYSNULL:
190 desc->sd.sd_p = 0;
191 break;
192 case SDT_SYS286CGT:
193 case SDT_SYS386CGT:
194
195
196
197
198
199
200 if (desc->gd.gd_p != 0 &&
201 !ISLDT(desc->gd.gd_selector) &&
202 ((IDXSEL(desc->gd.gd_selector) >= NGDT) ||
203 (gdt[IDXSEL(desc->gd.gd_selector)].sd.sd_dpl !=
204 SEL_UPL))) {
205 error = EACCES;
206 goto out;
207 }
208 break;
209 case SDT_MEMEC:
210 case SDT_MEMEAC:
211 case SDT_MEMERC:
212 case SDT_MEMERAC:
213
214 if (desc->sd.sd_p == 0) {
215 error = EACCES;
216 goto out;
217 }
218 break;
219 case SDT_MEMRO:
220 case SDT_MEMROA:
221 case SDT_MEMRW:
222 case SDT_MEMRWA:
223 case SDT_MEMROD:
224 case SDT_MEMRODA:
225 case SDT_MEMRWD:
226 case SDT_MEMRWDA:
227 case SDT_MEME:
228 case SDT_MEMEA:
229 case SDT_MEMER:
230 case SDT_MEMERA:
231 break;
232 default:
233
234
235
236
237 if (desc->sd.sd_p != 0) {
238 error = EACCES;
239 goto out;
240 }
241 break;
242 }
243
244 if (desc->sd.sd_p != 0) {
245
246 if (desc->sd.sd_dpl != SEL_UPL) {
247 error = EACCES;
248 goto out;
249 }
250 }
251 }
252
253
254 simple_lock(&pmap->pm_lock);
255 if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
256 if (pmap->pm_flags & PMF_USER_LDT)
257 ldt_len = pmap->pm_ldt_len;
258 else
259 ldt_len = 512;
260 while ((ua.start + ua.num) > ldt_len)
261 ldt_len *= 2;
262 new_len = ldt_len * sizeof(union descriptor);
263
264 simple_unlock(&pmap->pm_lock);
265 new_ldt = (union descriptor *)uvm_km_alloc(kernel_map,
266 new_len);
267 simple_lock(&pmap->pm_lock);
268
269 if (pmap->pm_ldt != NULL && ldt_len <= pmap->pm_ldt_len) {
270
271
272
273
274
275
276
277
278 uvm_km_free(kernel_map, (vaddr_t)new_ldt, new_len);
279 goto copy;
280 }
281
282 old_ldt = pmap->pm_ldt;
283
284 if (old_ldt != NULL) {
285 old_len = pmap->pm_ldt_len * sizeof(union descriptor);
286 } else {
287 old_len = NLDT * sizeof(union descriptor);
288 old_ldt = ldt;
289 }
290
291 memcpy(new_ldt, old_ldt, old_len);
292 memset((caddr_t)new_ldt + old_len, 0, new_len - old_len);
293
294 if (old_ldt != ldt)
295 uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
296
297 pmap->pm_ldt = new_ldt;
298 pmap->pm_ldt_len = ldt_len;
299
300 if (pmap->pm_flags & PMF_USER_LDT)
301 ldt_free(pmap);
302 else
303 pmap->pm_flags |= PMF_USER_LDT;
304 ldt_alloc(pmap, new_ldt, new_len);
305 pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
306 if (pcb == curpcb)
307 lldt(pcb->pcb_ldt_sel);
308
309 }
310 copy:
311
312 for (i = 0, n = ua.start; i < ua.num; i++, n++)
313 pmap->pm_ldt[n] = descv[i];
314
315 simple_unlock(&pmap->pm_lock);
316
317 *retval = ua.start;
318
319 out:
320 free(descv, M_TEMP);
321 return (error);
322 }
323 #endif
324
325 #ifdef APERTURE
326 extern int allowaperture;
327 #endif
328
329 int
330 i386_iopl(struct proc *p, void *args, register_t *retval)
331 {
332 int error;
333 struct trapframe *tf = p->p_md.md_regs;
334 struct i386_iopl_args ua;
335
336 if ((error = suser(p, 0)) != 0)
337 return error;
338 #ifdef APERTURE
339 if (!allowaperture && securelevel > 0)
340 return EPERM;
341 #else
342 if (securelevel > 0)
343 return EPERM;
344 #endif
345
346 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
347 return error;
348
349 if (ua.iopl)
350 tf->tf_eflags |= PSL_IOPL;
351 else
352 tf->tf_eflags &= ~PSL_IOPL;
353
354 return 0;
355 }
356
357 int
358 i386_get_ioperm(struct proc *p, void *args, register_t *retval)
359 {
360 int error;
361 struct pcb *pcb = &p->p_addr->u_pcb;
362 struct i386_get_ioperm_args ua;
363
364 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
365 return (error);
366
367 return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
368 }
369
370 int
371 i386_set_ioperm(struct proc *p, void *args, register_t *retval)
372 {
373 int error;
374 struct pcb *pcb = &p->p_addr->u_pcb;
375 struct i386_set_ioperm_args ua;
376
377 if ((error = suser(p, 0)) != 0)
378 return error;
379
380 #ifdef APERTURE
381 if (!allowaperture && securelevel > 0)
382 return EPERM;
383 #else
384 if (securelevel > 0)
385 return EPERM;
386 #endif
387 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
388 return (error);
389
390 return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
391 }
392
393 int
394 sys_sysarch(struct proc *p, void *v, register_t *retval)
395 {
396 struct sys_sysarch_args
397
398
399 *uap = v;
400 int error = 0;
401
402 switch(SCARG(uap, op)) {
403 #ifdef USER_LDT
404 case I386_GET_LDT:
405 error = i386_get_ldt(p, SCARG(uap, parms), retval);
406 break;
407
408 case I386_SET_LDT:
409 error = i386_set_ldt(p, SCARG(uap, parms), retval);
410 break;
411 #endif
412
413 case I386_IOPL:
414 error = i386_iopl(p, SCARG(uap, parms), retval);
415 break;
416
417 case I386_GET_IOPERM:
418 error = i386_get_ioperm(p, SCARG(uap, parms), retval);
419 break;
420
421 case I386_SET_IOPERM:
422 error = i386_set_ioperm(p, SCARG(uap, parms), retval);
423 break;
424
425 #ifdef VM86
426 case I386_VM86:
427 error = i386_vm86(p, SCARG(uap, parms), retval);
428 break;
429 #endif
430
431 default:
432 error = EINVAL;
433 break;
434 }
435 return (error);
436 }