| 396 | } |
| 397 | |
| 398 | int |
| 399 | linux_modify_ldt(struct thread *td, struct linux_modify_ldt_args *uap) |
| 400 | { |
| 401 | int error; |
| 402 | struct i386_ldt_args ldt; |
| 403 | struct l_descriptor ld; |
| 404 | union descriptor desc; |
| 405 | int size, written; |
| 406 | |
| 407 | switch (uap->func) { |
| 408 | case 0x00: /* read_ldt */ |
| 409 | ldt.start = 0; |
| 410 | ldt.descs = uap->ptr; |
| 411 | ldt.num = uap->bytecount / sizeof(union descriptor); |
| 412 | error = i386_get_ldt(td, &ldt); |
| 413 | td->td_retval[0] *= sizeof(union descriptor); |
| 414 | break; |
| 415 | case 0x02: /* read_default_ldt = 0 */ |
| 416 | size = 5*sizeof(struct l_desc_struct); |
| 417 | if (size > uap->bytecount) |
| 418 | size = uap->bytecount; |
| 419 | for (written = error = 0; written < size && error == 0; written++) |
| 420 | error = subyte((char *)uap->ptr + written, 0); |
| 421 | td->td_retval[0] = written; |
| 422 | break; |
| 423 | case 0x01: /* write_ldt */ |
| 424 | case 0x11: /* write_ldt */ |
| 425 | if (uap->bytecount != sizeof(ld)) |
| 426 | return (EINVAL); |
| 427 | |
| 428 | error = copyin(uap->ptr, &ld, sizeof(ld)); |
| 429 | if (error) |
| 430 | return (error); |
| 431 | |
| 432 | ldt.start = ld.entry_number; |
| 433 | ldt.descs = &desc; |
| 434 | ldt.num = 1; |
| 435 | desc.sd.sd_lolimit = (ld.limit & 0x0000ffff); |
| 436 | desc.sd.sd_hilimit = (ld.limit & 0x000f0000) >> 16; |
| 437 | desc.sd.sd_lobase = (ld.base_addr & 0x00ffffff); |
| 438 | desc.sd.sd_hibase = (ld.base_addr & 0xff000000) >> 24; |
| 439 | desc.sd.sd_type = SDT_MEMRO | ((ld.read_exec_only ^ 1) << 1) | |
| 440 | (ld.contents << 2); |
| 441 | desc.sd.sd_dpl = 3; |
| 442 | desc.sd.sd_p = (ld.seg_not_present ^ 1); |
| 443 | desc.sd.sd_xx = 0; |
| 444 | desc.sd.sd_def32 = ld.seg_32bit; |
| 445 | desc.sd.sd_gran = ld.limit_in_pages; |
| 446 | error = i386_set_ldt(td, &ldt, &desc); |
| 447 | break; |
| 448 | default: |
| 449 | error = ENOSYS; |
| 450 | break; |
| 451 | } |
| 452 | |
| 453 | if (error == EOPNOTSUPP) { |
| 454 | linux_msg(td, "modify_ldt needs kernel option USER_LDT"); |
| 455 | error = ENOSYS; |
nothing calls this directly
no test coverage detected