diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-12-04 12:20:00 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-12-04 12:20:00 -0800 |
commit | 67b8ffac570cc44cd6f4d975bdf119d378417cba (patch) | |
tree | d44082fbc45198b1bcd927cb21281dd4a6d93a54 | |
parent | 8bf0f3233d8433a1b376175dc7753e7e146abda1 (diff) | |
download | misc-tests-67b8ffac570cc44cd6f4d975bdf119d378417cba.tar.gz |
sigreturn: Test even more things
-rw-r--r-- | sigreturn.c | 98 |
1 files changed, 75 insertions, 23 deletions
diff --git a/sigreturn.c b/sigreturn.c index bbf13ce..e2de0e5 100644 --- a/sigreturn.c +++ b/sigreturn.c @@ -23,6 +23,10 @@ struct selectors { unsigned short cs, gs, fs, ss; }; +static bool has_code16, has_data16, has_npcode32, has_npdata16; + +static int gdt_data16_idx; + static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags) { @@ -58,6 +62,16 @@ asm (".pushsection .text\n\t" ".popsection"); extern char int3[4096]; +static void add_ldt(const struct user_desc *desc, bool *var, const char *name) +{ + if (syscall(SYS_modify_ldt, 1, desc, sizeof(*desc)) == 0) { + *var = true; + } else { + printf("[NOTE]\tFailed to create %s segment\n", name); + *var = false; + } +} + static void setup_ldt(void) { if ((unsigned long)stack16 > (1ULL << 32) - sizeof(stack16)) @@ -77,6 +91,8 @@ static void setup_ldt(void) .seg_not_present = 0, .useable = 0 }; + add_ldt(&code16_desc, &has_code16, "code16"); + const struct user_desc data16_desc = { .entry_number = 1, .base_addr = (unsigned long)stack16, @@ -88,7 +104,9 @@ static void setup_ldt(void) .seg_not_present = 0, .useable = 0 }; - const struct user_desc npcode16_desc = { + add_ldt(&data16_desc, &has_data16, "data16"); + + const struct user_desc npcode32_desc = { .entry_number = 3, .base_addr = (unsigned long)int3, .limit = 4095, @@ -99,6 +117,8 @@ static void setup_ldt(void) .seg_not_present = 1, .useable = 0 }; + add_ldt(&npcode32_desc, &has_npcode32, "npcode32"); + const struct user_desc npdata16_desc = { .entry_number = 4, .base_addr = (unsigned long)stack16, @@ -110,15 +130,27 @@ static void setup_ldt(void) .seg_not_present = 1, .useable = 0 }; + add_ldt(&npdata16_desc, &has_npdata16, "npdata16"); + + struct user_desc gdt_data16_desc = { + .entry_number = -1, + .base_addr = (unsigned long)stack16, + .limit = 0xffff, + .seg_32bit = 0, + .contents = 0, /* Data, grow-up */ + .read_exec_only = 0, + .limit_in_pages = 0, + .seg_not_present = 0, + .useable = 0 + }; - if (syscall(SYS_modify_ldt, 1, &code16_desc, sizeof code16_desc) != 0) - err(1, "modify_ldt"); - if (syscall(SYS_modify_ldt, 1, &data16_desc, sizeof data16_desc) != 0) - err(1, "modify_ldt"); - if (syscall(SYS_modify_ldt, 1, &npcode16_desc, sizeof npcode16_desc) != 0) - err(1, "modify_ldt"); - if (syscall(SYS_modify_ldt, 1, &npdata16_desc, sizeof npdata16_desc) != 0) - err(1, "modify_ldt"); + if (syscall(SYS_set_thread_area, &gdt_data16_desc) == 0) { + printf("[FAIL]\tset_thread_area allocated data16 at index %d\n", + gdt_data16_desc.entry_number); + gdt_data16_idx = gdt_data16_desc.entry_number; + } else { + printf("[OK]\tset_thread_area refused 16-bit data\n"); + } } static gregset_t initial_regs, requested_regs, resulting_regs; @@ -253,21 +285,35 @@ int find_cs(int bitness) return -1; } -static int do_test(int cs_bits, bool use_16bit_ss) +static int do_test(int cs_bits, bool use_16bit_ss, int force_ss) { int cs = find_cs(cs_bits); - if (cs == -1) + if (cs == -1) { + printf("[SKIP]\tCode segment unavailable for %d-bit CS, %d-bit SS\n", + cs_bits, use_16bit_ss ? 16 : 32); return 0; + } - if (use_16bit_ss) - sig_ss = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */ - else - asm volatile ("mov %%ss,%0" : "=r" (sig_ss)); + if (force_ss != -1) { + sig_ss = force_ss; + } else { + if (use_16bit_ss) { + if (!has_data16) { + printf("[SKIP]\tData segment unavailable for %d-bit CS, 16-bit SS\n", + cs_bits); + return 0; + } + sig_ss = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */ + } else { + asm volatile ("mov %%ss,%0" : "=r" (sig_ss)); + } + } sig_cs = cs; - printf("[RUN]\t%d-bit CS (%hx), %d-bit SS (%hx)\n", - cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss); + printf("[RUN]\t%d-bit CS (%hx), %d-bit SS (%hx%s)\n", + cs_bits, sig_cs, use_16bit_ss ? 16 : 32, sig_ss, + (sig_ss & 4) ? "" : ", GDT"); raise(SIGUSR1); @@ -404,12 +450,18 @@ int main() sethandler(SIGUSR1, sigusr1, 0); sethandler(SIGTRAP, sigtrap, SA_ONSTACK); - total_nerrs += do_test(64, false); - total_nerrs += do_test(32, false); - total_nerrs += do_test(16, false); - total_nerrs += do_test(64, true); - total_nerrs += do_test(32, true); - total_nerrs += do_test(16, true); + total_nerrs += do_test(64, false, -1); + total_nerrs += do_test(32, false, -1); + total_nerrs += do_test(16, false, -1); + total_nerrs += do_test(64, true, -1); + total_nerrs += do_test(32, true, -1); + total_nerrs += do_test(16, true, -1); + + if (gdt_data16_idx) { + total_nerrs += do_test(64, true, (gdt_data16_idx << 3) | 3); + total_nerrs += do_test(32, true, (gdt_data16_idx << 3) | 3); + total_nerrs += do_test(16, true, (gdt_data16_idx << 3) | 3); + } clearhandler(SIGTRAP); sethandler(SIGSEGV, sigtrap, SA_ONSTACK); |