summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-07-14 20:18:53 -0700
committerAndy Lutomirski <luto@amacapital.net>2014-07-14 20:18:53 -0700
commitb93c13e020d1e22055e7a4c66554968fb41ced60 (patch)
treef1de414cad6b321936e332598aaa597072f8d932
parentdbfe196a0f6efedc119deb1cdbb0139dbdf609ee (diff)
downloadmisc-tests-b93c13e020d1e22055e7a4c66554968fb41ced60.tar.gz
sigreturn: Do all available bitness combinations
-rw-r--r--sigreturn.c107
1 files changed, 83 insertions, 24 deletions
diff --git a/sigreturn.c b/sigreturn.c
index ac68944..24dac43 100644
--- a/sigreturn.c
+++ b/sigreturn.c
@@ -87,7 +87,7 @@ static void setup_ldt(void)
static gregset_t initial_regs, requested_regs, resulting_regs;
-static bool sig_twiddle_cs, sig_twiddle_ss;
+static unsigned short sig_cs, sig_ss;
#ifdef __x86_64__
# define REG_IP REG_RIP
@@ -121,22 +121,19 @@ static greg_t *csptr(ucontext_t *ctx)
}
#endif
+static int nerrs;
+
static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t*)ctx_void;
memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
- if (sig_twiddle_cs)
- *csptr(ctx) = (0 << 3) | 7; /* LDT selector 0, RPL = 3 */
-
- if (sig_twiddle_ss)
- *ssptr(ctx) = (1 << 3) | 7; /* LDT selector 1, RPL = 3 */
- else /* Fix for unpatched kernels. */
- asm volatile ("mov %%ss,%0" : "=r" (*ssptr(ctx)));
+ *csptr(ctx) = sig_cs;
+ *ssptr(ctx) = sig_ss;
ctx->uc_mcontext.gregs[REG_IP] =
- sig_twiddle_cs ? 0 : (unsigned long)&int3;
+ (sig_cs == 0x7) ? 0 : (unsigned long)&int3;
ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
ctx->uc_mcontext.gregs[REG_AX] = 0;
@@ -152,9 +149,13 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
unsigned short ss;
asm ("mov %%ss,%0" : "=r" (ss));
- printf("\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
- ss, *ssptr(ctx),
- (unsigned long long)ctx->uc_mcontext.gregs[REG_AX]);
+
+ greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX];
+ if (asm_ss != sig_ss) {
+ printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
+ ss, *ssptr(ctx), (unsigned long long)asm_ss);
+ nerrs++;
+ }
memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
@@ -162,16 +163,72 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
static char altstack_data[SIGSTKSZ];
-static int do_test(bool twiddle_cs, bool twiddle_ss)
+int cs_bitness(unsigned short cs)
+{
+ uint32_t valid = 0, ar;
+ asm ("lar %[cs], %[ar]\n\t"
+ "jnz 1f\n\t"
+ "mov $1, %[valid]\n\t"
+ "1:"
+ : [ar] "=r" (ar), [valid] "+rm" (valid)
+ : [cs] "r" (cs));
+
+ if (!valid)
+ return -1;
+
+ bool db = (ar & (1 << 22));
+ bool l = (ar & (1 << 21));
+
+ if (!(ar & (1<<11)))
+ return -1; /* Not code. */
+
+ if (l && !db)
+ return 64;
+ else if (!l && db)
+ return 32;
+ else if (!l && !db)
+ return 16;
+ else
+ return -1; /* Unknown bitness. */
+}
+
+int find_cs(int bitness)
{
- printf("\ttwiddle_cs = %d, twiddle_ss = %d\n",
- (int)twiddle_cs, (int)twiddle_ss);
- sig_twiddle_cs = twiddle_cs;
- sig_twiddle_ss = twiddle_ss;
+ unsigned short my_cs;
+ asm ("mov %%cs,%0" : "=r" (my_cs));
+
+ if (cs_bitness(my_cs) == bitness)
+ return my_cs;
+ if (cs_bitness(my_cs + (2 << 3)) == bitness)
+ return my_cs + (2 << 3);
+ if (my_cs > (2<<3) && cs_bitness(my_cs - (2 << 3)) == bitness)
+ return my_cs - (2 << 3);
+ if (cs_bitness(0x7) == bitness)
+ return 0x7;
+
+ printf("[WARN]\tCould not find %d-bit CS\n", bitness);
+ return -1;
+}
+
+static int do_test(int cs_bits, bool use_16bit_ss)
+{
+ int cs = find_cs(cs_bits);
+ if (cs == -1)
+ 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));
+
+ 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);
raise(SIGUSR1);
- int nerrs = 0;
+ nerrs = 0;
for (int i = 0; i < NGREG; i++) {
greg_t req = requested_regs[i], res = resulting_regs[i];
@@ -235,7 +292,7 @@ static int do_test(bool twiddle_cs, bool twiddle_ss)
int main()
{
- int nerrs = 0;
+ int total_nerrs = 0;
setup_ldt();
@@ -249,10 +306,12 @@ int main()
sethandler(SIGUSR1, sigusr1, 0);
sethandler(SIGTRAP, sigtrap, SA_ONSTACK);
- nerrs += do_test(false, false);
- nerrs += do_test(true, false);
- nerrs += do_test(false, true);
- nerrs += do_test(true, true);
+ 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);
- return nerrs ? 1 : 0;
+ return total_nerrs ? 1 : 0;
}