Как узнать, включена ли в моей системе поддержка битов ARN XN (не выполнять)? - PullRequest
2 голосов
/ 10 мая 2019

Я работаю над встроенной системой linux с процессором ARM cortex A5 и версией ядра linux где-то около 3.13.9.Как я могу проверить, включена ли поддержка битов XN?

Также я знаю, что архитектура ARMv7 поддерживает ее, но что нужно от ядра для ее использования?

Насколько я знаю, / proc / cpuinfo не имеет флага возможностейдля поддержки ARM xn (хотя у Intel есть флаг для nx).

Кроме того, кажется, что более новые ARM имеют UXN и PXN.Как это относится к старому XN?

Было бы неплохо увидеть, может быть, увидеть таблицы страниц с помеченным битом или регистры, показывающие бит NX = 1. Кроме того, есть ли простой запуск, скажем,Атака ret2usr для проверки защиты?Любые другие методы проверки с благодарностью.

1 Ответ

1 голос
/ 10 мая 2019

Как проверить, включена ли поддержка битов XN?

Согласно руководству ARM 5.5.3.Выполнить никогда не биты , XN находится в c1 Регистр управления .Пользовательская область (уровень исключения 0) не может получить доступ к этим полям в конфигурациях, о которых я знаю.

У вас есть два или три варианта (или, возможно, один).Во-первых, если выполняется как привилегированный процесс (уровень исключения 1 или выше), просто прочитайте регистр c1.

Во-вторых, посмотрите, можно ли запросить функцию с помощью HWCAP.Вот Торвальдс asm/hwcaps.h, но я не вижу HWCAP_XN или подобное.HWCAP_IWMMXT может быть, но я не могу найти то, что представляет определение.

HWCAP - это самый простой путь, потому что вам нужно только сделать следующее (но он не доступен для вас):

if ((getauxval(AT_HWCAP) & HWCAP_XN) != 0)
    return true;

Поскольку второй вариант недоступен, вы можете выполнить проверку функции.Я называю их SIGILL пробами, потому что вы часто проверяете поддержку ISA, например, NEON, используя нагрузку NEON.Если вы ловите SIGILL, вы знаете, что процессор не поддерживает NEON.

В вашем случае вы должны выполнить то, что @ o11c предлагает в комментарии.Вы должны выделить страницу, установить PROT_EXEC и посмотреть, сможете ли вы написать на нее.Если вы не можете написать в него, то write завершится с ошибкой errno=EPERM или вы поймаете исключение.Если произойдет сбой write, вы пометите функцию NX как доступную.

У меня нет удобного зонда для XN (он мне никогда не был нужен), но я могу показать вам, чтоSIGILL пробник выглядит, когда пробует поддержку ARMv7 .

Также будьте осторожны с пробниками на компьютерах Apple.У Apple есть ошибка, которая влияет на регистр или состояние процесса после взятия longjmp, и она будет отбрасывать что-то ужасное.Никогда не исследуйте платформы Apple.Просто верните false для этой функции.


extern "C" {
    typedef void (*SigHandler)(int);

    static jmp_buf s_jmpSIGILL;
    static void SigIllHandler(int)
    {
        longjmp(s_jmpSIGILL, 1);
    }
}

bool CPU_ProbeARMv7()
{
    // longjmp and clobber warnings. Volatile is required.
    // http://stackoverflow.com/q/7721854
    volatile bool result = true;

    volatile SigHandler oldHandler = signal(SIGILL, SigIllHandler);
    if (oldHandler == SIG_ERR)
        return false;

    volatile sigset_t oldMask;
    if (sigprocmask(0, NULLPTR, (sigset_t*)&oldMask))
        return false;

    if (setjmp(s_jmpSIGILL))
        result = false;
    else
    {
        // ARMv7 added movt and movw
        int a;
        asm volatile("movw %0,%1 \n"
                     "movt %0,%1 \n"
                     : "=r"(a) : "i"(0x1234));
        result = (a == 0x12341234);
    }

    sigprocmask(SIG_SETMASK, (sigset_t*)&oldMask, NULLPTR);
    signal(SIGILL, oldHandler);
    return result;
}
...