Skip to content

Commit d744dca

Browse files
amlutoIngo Molnar
authored andcommitted
selftests/x86/ldt_gdt: Add infrastructure to test set_thread_area()
Much of the test design could apply to set_thread_area() (i.e. GDT), not just modify_ldt(). Add set_thread_area() to the install_valid_mode() helper. Signed-off-by: Andy Lutomirski <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/02c23f8fba5547007f741dc24c3926e5284ede02.1509794321.git.luto@kernel.org Signed-off-by: Ingo Molnar <[email protected]>
1 parent d60ad74 commit d744dca

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

tools/testing/selftests/x86/ldt_gdt.c

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -137,38 +137,59 @@ static void check_valid_segment(uint16_t index, int ldt,
137137
}
138138
}
139139

140-
static bool install_valid_mode(const struct user_desc *desc, uint32_t ar,
141-
bool oldmode)
140+
static bool install_valid_mode(const struct user_desc *d, uint32_t ar,
141+
bool oldmode, bool ldt)
142142
{
143-
int ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
144-
desc, sizeof(*desc));
145-
if (ret < -1)
146-
errno = -ret;
143+
struct user_desc desc = *d;
144+
int ret;
145+
146+
if (!ldt) {
147+
#ifndef __i386__
148+
/* No point testing set_thread_area in a 64-bit build */
149+
return false;
150+
#endif
151+
if (!gdt_entry_num)
152+
return false;
153+
desc.entry_number = gdt_entry_num;
154+
155+
ret = syscall(SYS_set_thread_area, &desc);
156+
} else {
157+
ret = syscall(SYS_modify_ldt, oldmode ? 1 : 0x11,
158+
&desc, sizeof(desc));
159+
160+
if (ret < -1)
161+
errno = -ret;
162+
163+
if (ret != 0 && errno == ENOSYS) {
164+
printf("[OK]\tmodify_ldt returned -ENOSYS\n");
165+
return false;
166+
}
167+
}
168+
147169
if (ret == 0) {
148-
uint32_t limit = desc->limit;
149-
if (desc->limit_in_pages)
170+
uint32_t limit = desc.limit;
171+
if (desc.limit_in_pages)
150172
limit = (limit << 12) + 4095;
151-
check_valid_segment(desc->entry_number, 1, ar, limit, true);
173+
check_valid_segment(desc.entry_number, ldt, ar, limit, true);
152174
return true;
153-
} else if (errno == ENOSYS) {
154-
printf("[OK]\tmodify_ldt returned -ENOSYS\n");
155-
return false;
156175
} else {
157-
if (desc->seg_32bit) {
158-
printf("[FAIL]\tUnexpected modify_ldt failure %d\n",
176+
if (desc.seg_32bit) {
177+
printf("[FAIL]\tUnexpected %s failure %d\n",
178+
ldt ? "modify_ldt" : "set_thread_area",
159179
errno);
160180
nerrs++;
161181
return false;
162182
} else {
163-
printf("[OK]\tmodify_ldt rejected 16 bit segment\n");
183+
printf("[OK]\t%s rejected 16 bit segment\n",
184+
ldt ? "modify_ldt" : "set_thread_area");
164185
return false;
165186
}
166187
}
167188
}
168189

169190
static bool install_valid(const struct user_desc *desc, uint32_t ar)
170191
{
171-
return install_valid_mode(desc, ar, false);
192+
return install_valid_mode(desc, ar, false, true);
172193
}
173194

174195
static void install_invalid(const struct user_desc *desc, bool oldmode)

0 commit comments

Comments
 (0)