C ++: __aligned (__ alignof__) вызывает проблемы с данными массива char? - PullRequest
0 голосов
/ 10 февраля 2020

Tl; dr: Массив char, к которому обращается мой код, который ранее указывал на ожидаемое строковое значение, теперь содержит неожиданные символы перед строкой. Моя текущая теория заключается в том, что это как-то вызвано изменением выравнивания массива символов, и я пытаюсь выяснить, прав ли я и как это исправить.

Я пытаюсь сохранить Linux модуль ядра, написанный на C ++. Прошло много времени с тех пор, как я работал в C ++, поэтому я немного застрял в том, что вижу в данный момент.

У нас есть отдельная утилита вне модуля ядра, которая записывает ключ в связку ключей ядра. Позже модуль ядра проверяет это и сравнивает его с ожидаемым значением ключа. Вот метод поиска:

#include <linux/key.h>
#include <keys/user-type.h>

int read_key(char *key_desc, char *expected_key) {
    struct key *key;
    struct user_key_payload *key_payload;

    key = request_key(&key_type_user, key_desc, NULL);
    key_payload = rcu_dereference(key->payload.data[0]);

    return strncmp(key_payload->data, expected_key, key_payload->datalen));
}

Этот код в настоящее время работает на большинстве версий ядра, которые мы поддерживаем. Но недавно было обновление ядра в одной конкретной ОС, и теперь мой вызов strncmp не может найти соответствие. Кажется, что данные каким-то образом смещены. Например, если key_payload-> datalen = 16 и Ожидаемый_ключ = "1234567890123456", то key_payload-> data = "abcdef1234567890123456". Что, поскольку я сравниваю первые 16 символов, очевидно, не будет совпадать, но будет, если вместо этого я начну с key_payload-> data [6]. Пока что key_payload-> datalen по-прежнему является правильной ожидаемой длиной строки. Это просто key_payload-> data, которые изменились в новой версии ядра.

Я рассмотрел несколько патчей в новом ядре, я думаю, что это может быть связано с проблемой. Одно очевидное отличие, которое я обнаружил, это это . До патча объект user_key_payload from выглядел следующим образом:

struct user_key_payload {
    struct rcu_head rcu;        /* RCU destructor */
    unsigned short  datalen;    /* length of this data */
    char        data[0];    /* actual data */
};

Но после этого он выглядит следующим образом:

struct user_key_payload {
    struct rcu_head rcu;        /* RCU destructor */
    unsigned short  datalen;    /* length of this data */
    char        data[0] __aligned(__alignof__(u64)); /* actual data */
};

Я не знаю, действительно ли это является причиной моей проблемы, но кажется, как очевидное место, чтобы начать искать. Я никогда не работал с выровненными или выровненными ключевыми словами прежде. Я прочитал несколько статей о выравнивании, но все это намного ниже, чем то, с чем я работал уже несколько лет. Кто-нибудь знает, есть ли способ, которым выравнивание user_key_payload.data может испортить ожидаемый адрес памяти ключевых данных, и как выяснить, где мои ожидаемые данные на самом деле?

1 Ответ

0 голосов
/ 10 февраля 2020

char data[0] означает указатель сразу после структуры. Он широко используется в ядре для указания полезной нагрузки переменной длины, следующей за заголовком.

__aligned(__alignof__(u64)) выравнивает данные по 8-байтовой (64-битной) границе. Это означает, например, что если требуемый размер для хранения всех полей в struct user_key_payload равен 10 байтам, то структура дополняется до 16 байт (2 * 8).

Следовательно, если ядро ​​угрожает данные выровнены по 8 байтам, но ваш модуль - нет, тогда «abcdef» - ​​это заполнение, с которого вы читаете. используются для компиляции ядра.

...