TIB Custom Storage - PullRequest
       57

TIB Custom Storage

2 голосов
/ 13 февраля 2012

После долгого поиска в Google и некоторых подсказок здесь мне наконец удалось найти макет сегмента FS (используемый окнами для хранения данных TIB). Особый интерес для меня представляет член ArbitraryUserPointer, указанный в PSDK:

typedef struct _NT_TIB {
    struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
    PVOID StackBase;
    PVOID StackLimit;
    PVOID SubSystemTib;
    union {
        PVOID FiberData;
        DWORD Version;
    };
    PVOID ArbitraryUserPointer;
    struct _NT_TIB *Self;
} NT_TIB;

Насколько безопасно использовать эту переменную (в Vista и выше)? и существует ли он на x64?

Второстепенным является доступ к этой переменной. Я использую MSVC, и как таковой я иметь доступ к __readfsdword & __readgsqword встроенным функциям, однако MSDN по некоторым причинам помечает их как привилегированные инструкции:

Эти встроенные функции доступны только в режиме ядра, а подпрограммы доступны только как встроенные.

Они, конечно, не только для ядра, но почему они помечены как таковые, просто неверная документация? (мои автономные документы по VS 2008 не имеют этого пункта).

Наконец, безопасно ли обращаться к ArbitraryUserPointer напрямую через один __readfsdword(0x14) или предпочтительнее использовать его по линейному адресу TIB? (который все еще потребует чтения от FS).

Ответы [ 2 ]

4 голосов
/ 13 февраля 2012

ArbitraryUserPointer является внутренним полем, не предназначенным для общего использования.Операционная система использует его внутренне, и если вы перезапишите его, вы испортите материал.Я признаю, что у него очень плохое имя.

0 голосов
/ 01 апреля 2012

Если вы все еще хотите ответить, у меня возникла та же проблема, и я отправил свой вопрос, похожий на ваш:

Потоковое локальное хранилище в режиме ядра?

Мне нужен TLS-эквивалент в драйвере режима ядра. Если быть точным, у меня есть глубокое дерево вызовов функций, которое возникает в какой-то момент (например, процедура диспетчеризации драйверов), и мне нужно передать контекстную информацию.

В моем конкретном случае выгода в том, что мне не нужно постоянное хранилище, мне просто нужен специфичный для потока заполнитель для чего-то для одного вызова функции верхнего уровня. Поэтому я решил использовать произвольную запись в массиве TLS для вызова функции, а после того, как это сделано, - восстановить ее первоначальное значение.

Вы получаете массив TLS следующим образом:

DWORD* get_Tls()
{
    return (DWORD*) (__readfsdword(0x18) + 0xe10);
}

Кстати, я понятия не имею, почему к TIB обычно обращаются, читая содержимое fs:[0x18]. Это просто указывает селектор fs. Но именно так весь код MS получает к нему доступ, поэтому я решил сделать это тоже.

Далее вы выбираете произвольный индекс TLS, скажем, 0.

const DWORD g_dwMyTlsIndex = 0;

void MyTopLevelFunc()
{
    // prolog
    DWORD dwOrgVal = get_Tls()[g_dwMyTlsIndex];
    get_Tls()[g_dwMyTlsIndex] = dwMyContextValue;

    DoSomething();

    // epilog
    get_Tls()[g_dwMyTlsIndex] = dwOrgVal;
}

void DoSomething()
{
    DWORD dwMyContext = get_Tls()[g_dwMyTlsIndex];
}
...