This source file includes following definitions.
- read_ldt
- write_ldt
- sys_modify_ldt
1
2
3
4
5
6
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/string.h>
10 #include <asm/segment.h>
11 #include <asm/system.h>
12 #include <linux/ldt.h>
13
14 static int read_ldt(void * ptr, unsigned long bytecount)
15 {
16 int error;
17 void * address = current->ldt;
18 unsigned long size;
19
20 if (!ptr)
21 return -EINVAL;
22 size = LDT_ENTRIES*LDT_ENTRY_SIZE;
23 if (!address) {
24 address = &default_ldt;
25 size = sizeof(default_ldt);
26 }
27 if (size > bytecount)
28 size = bytecount;
29 error = verify_area(VERIFY_WRITE, ptr, size);
30 if (error)
31 return error;
32 memcpy_tofs(ptr, address, size);
33 return size;
34 }
35
36 static int write_ldt(void * ptr, unsigned long bytecount)
37 {
38 struct modify_ldt_ldt_s ldt_info;
39 unsigned long *lp;
40 unsigned long base, limit;
41 int error, i;
42
43 if (bytecount != sizeof(ldt_info))
44 return -EINVAL;
45 error = verify_area(VERIFY_READ, ptr, sizeof(ldt_info));
46 if (error)
47 return error;
48
49 memcpy_fromfs(&ldt_info, ptr, sizeof(ldt_info));
50
51 if (ldt_info.contents == 3 || ldt_info.entry_number >= LDT_ENTRIES)
52 return -EINVAL;
53
54 limit = ldt_info.limit;
55 base = ldt_info.base_addr;
56 if (ldt_info.limit_in_pages)
57 limit *= PAGE_SIZE;
58
59 limit += base;
60 if (limit < base || limit >= 0xC0000000)
61 return -EINVAL;
62
63 if (!current->ldt) {
64 for (i=1 ; i<NR_TASKS ; i++) {
65 if (task[i] == current) {
66 if (!(current->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE)))
67 return -ENOMEM;
68 set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, current->ldt, LDT_ENTRIES);
69 load_ldt(i);
70 }
71 }
72 }
73
74 lp = (unsigned long *) ¤t->ldt[ldt_info.entry_number];
75
76 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
77 *lp = 0;
78 *(lp+1) = 0;
79 return 0;
80 }
81 *lp = ((ldt_info.base_addr & 0x0000ffff) << 16) |
82 (ldt_info.limit & 0x0ffff);
83 *(lp+1) = (ldt_info.base_addr & 0xff000000) |
84 ((ldt_info.base_addr & 0x00ff0000)>>16) |
85 (ldt_info.limit & 0xf0000) |
86 (ldt_info.contents << 10) |
87 ((ldt_info.read_exec_only ^ 1) << 9) |
88 (ldt_info.seg_32bit << 22) |
89 (ldt_info.limit_in_pages << 23) |
90 ((ldt_info.seg_not_present ^1) << 15) |
91 0x7000;
92 return 0;
93 }
94
95 asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
96 {
97 if (func == 0)
98 return read_ldt(ptr, bytecount);
99 if (func == 1)
100 return write_ldt(ptr, bytecount);
101 return -ENOSYS;
102 }