Windows是否有sigaltstack和sigaction的替代方法?

时间:2018-10-24 13:43:07

标签: c windows

对于不了解Linux的人们,sigalstack用于创建备用堆栈,您可以阅读有关更多内容here。但是,基本思想可以总结如下:

  1. 分配用于备用信号的内存区域       堆栈。

  2. 使用sigaltstack()通知系统存在和存在       备用信号堆栈的位置。

  3. 使用sigaction(2)建立信号处理程序时,通知       信号处理程序应在备用系统上执行的系统       通过指定SA_ONSTACK标志来表示信号栈。

我基本上是用这种方式来测试内存清零功能的。

#ifndef _WIN32
#define MEMZERO_STACK_SIZE              (SIGSTKSZ + sizeof(secret))
#else
#define MEMZERO_STACK_SIZE              sizeof(secret) // Maybe we need to add something here?!
#endif

// The secret that we write out to the stack. 
static const char secret[24] = {
    0x4e, 0x65, 0x76, 0x65, 0x72, 0x20, 0x67, 0x6f,
    0x6e, 0x6e, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65,
    0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x70, 0x2c,
};

static char stack_buf[MEMZERO_STACK_SIZE];

#ifndef _WIN32
// Verify that we are on the custom stack.
static void assert_on_stack(void) {
    stack_t current_stack;
    assert(0 == sigaltstack(NULL, &current_stack));
    assert(SS_ONSTACK == (current_stack.ss_flags & SS_ONSTACK));
}

// Call the provided signal handler on a custom stack.
static void call_on_stack(void (*fn)(int)) {
    const stack_t stack = {
        .ss_sp = stack_buf,
        .ss_size = sizeof(stack_buf),
    };

    const struct sigaction action = {
        .sa_handler = fn,
        .sa_flags = SA_ONSTACK,
    };

    stack_t old_stack;
    struct sigaction old_action;

    // Setup the stack and signal handler.
    assert(0 == sigaltstack(&stack, &old_stack));
    assert(0 == sigaction(SIGUSR1, &action, &old_action));

    // Raise a signal. This will only return after the signal handler has returned.
    assert(0 == raise(SIGUSR1));

    // Restore the previous state, disable our alt stack.
    sigaction(SIGUSR1, &old_action, NULL);
    sigaltstack(&old_stack, NULL);
}
#endif

static char *memzero_test() {
    char buf[sizeof(secret)];
    char *result;

    assert_on_stack();

    memcpy(buf, secret, sizeof(secret));
    result = memmem(stack_buf, MEMZERO_STACK_SIZE, buf, sizeof(buf));

    memset(buf, 0, sizeof(buf));   
    return result;
}

static void memzero_test_correctness_signal_handler(int arg)
{
   // Removed for brevity. It calls memzero_test here, and basically
   // when this function finishes execution a signal is sent to the 
   // call_on_stack function.
   char *buf = memzero_test();
   if (memcmp(buf, secret, sizeof(secret)) != 0) {
      printf("Test passed\n");
    } else {
      printf("Test failed\n");
    }
}

call_on_stack(memzero_test_correctness_signal_handler);

因此,我也想在Windows中进行测试,但是Windows当然不支持这些GNU C库特定的数据类型和常量。因此,我需要另一种方法来重写它,更具体地说,创建一个自定义堆栈,在其上执行一个函数,并通知函数何时完成以清除它。有任何想法在Windows中如何做到吗?

1 个答案:

答案 0 :(得分:2)

在Windows中运行多个堆栈的受支持方法是fibers

但是,我不确定这是否适合您的任务。如果您想在收到事件时擦除秘密,请从事件处理程序中调用SecureZeroMemory