summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-12-04 12:20:00 -0800
committerAndy Lutomirski <luto@amacapital.net>2014-12-04 12:20:00 -0800
commit67b8ffac570cc44cd6f4d975bdf119d378417cba (patch)
treed44082fbc45198b1bcd927cb21281dd4a6d93a54
parent8bf0f3233d8433a1b376175dc7753e7e146abda1 (diff)
downloadmisc-tests-67b8ffac570cc44cd6f4d975bdf119d378417cba.tar.gz
sigreturn: Test even more things
-rw-r--r--sigreturn.c98
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);