Связывать цепочки ключей в initramfs с помощью syscall()

#c #linux #security #system-calls

#c #linux #Безопасность #системные вызовы

Вопрос:

Я хочу загрузить сертификаты для IMA / EVM в связки ключей Linux.

Связанные команды командной строки являются

 ima_id=`keyctl newring _ima @u`
evm_id=`keyctl newring _evm @u`
evmctl import  /etc/keys/x509_ima.der $ima_id
evmctl import  /etc/keys/x509_evm.der $evm_id
  

Это почти работает, за исключением проблемы с разрешениями.

 # keyctl show @u
Keyring
 272896171 --alswrv      0 65534  keyring: _uid.0
 406281657 --alswrv      0     0   _ keyring: _ima
keyctl_read: Permission denied
  

Поискав в Интернете, я нашел это:https://github.com/systemd/systemd/issues/5522

И обходной путь заключается в том, чтобы связать цепочки ключей:

 keyctl link @us @s
  

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

 # keyctl show @u
Keyring
 272896171 --alswrv      0 65534  keyring: _uid.0
 406281657 --alswrv      0     0   _ keyring: _ima
 647882074 --als--v      0     0   |   _ asymmetric: abc: gerhard signing key: 15733607aff5480b5eb8b59b501760f9c5d33965
  19332842 --alswrv      0     0   _ keyring: _evm
 470827275 --als--v      0     0       _ asymmetric: abc: gerhard signing key: 7e5959ee64090c7fabb6dd803e7d1f48e83c5970
  

Пока все хорошо…

Чтобы быть полезным, мне нужно поместить этот материал в initramfs . Система, с которой я имею дело, представляет собой встроенный Linux, в котором у меня нет оболочки во время initramfs .

Поэтому я использовал syscall , чтобы делать то, что должно быть сделано…

Создание цепочек ключей и импорт ключей работают нормально. Но связывание связок ключей не выполняется.

После загрузки я получаю ту же ошибку «отказано в разрешении», что и выше. Я также получаю сообщение об ошибке при попытке выполнить файл с подписью IMA. Написано, что связка ключей «_ima» не найдена.

Если я введу вручную keyctl link @us @s , все снова заработает.

Я предполагаю, что что-то, связанное с связками ключей, еще не установлено во время initramfs , но я не могу получить это.

syscall Я использую для связывания следующее:

 ret = syscall(__NR_keyctl, KEYCTL_LINK, KEY_SPEC_USER_SESSION_KEYRING, KEY_SPEC_SESSION_KEYRING, 0, 0);
  

Я не получаю никакого отрицательного результата от вызова.

Обновить

Я нашел несколько подсказок на этой странице:https://mjg59.dreamwidth.org/37333.html

В соответствии с этим последовательность должна быть следующей:

 $ keyctl add user testkey testdata @s
$ keyctl setperm 678913344 0x3f3f0000
$ keyctl link 678913344 @u
$ keyctl unlink 678913344 @s
  

Это справедливо для ключей, но, насколько я понимаю, это должно быть справедливо и для связок ключей.

 static void create_ima_keyring(void)
{
    char *name = "_ima";
    char *filename = "/etc/keys/x509_ima.der";

    int ringid = syscall(__NR_add_key, "keyring", name, NULL, 0, KEY_SPEC_SESSION_KEYRING);
    {
        // Set permission for keyring ...
        int ret = syscall(__NR_keyctl, KEYCTL_SETPERM, ringid, 0x3f3f0000, 0, 0);

        // ... and link to @u
        syscall(__NR_keyctl, KEYCTL_LINK, ringid, KEY_SPEC_USER_KEYRING);

        int len;
        unsigned char *pub = file2bin(filename, amp;len);
        if (pub != NULL)
        {
            int keyid = syscall(__NR_add_key, "asymmetric", NULL, pub, len, ringid);
            if (keyid >= 0)
            {
                int ret = syscall(__NR_keyctl, KEYCTL_SETPERM, keyid, 0x3f3f0000, 0, 0);
            }
            free(pub);
        }

        // TODO: Unlink from @s
    }
}
  

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

Теперь я получаю ожидаемый результат от keyctl show @u , но связка ключей все еще не распознана. Выполнение подписанного файла снова приводит к появлению сообщения об ошибке:

 digsig: no _ima keyring: -126
  

Ответ №1:

Мне не совсем понятны фактические шаги, которые вы предприняли для заполнения initramfs … попробуйте изучить содержимое: (предполагая сжатие gzip, также можете попробовать xz / lz4 / none)

gzip -dkcq -S img '/path/to/initramfs.img' | cpio -t

Мое первое предположение заключается в том, что вы обнаружите, /etc/keys/x509-blahblah что они не существуют в img initramfs. Тем более, что они «не найдены» во время загрузки, но работают после входа в систему. Также могут отсутствовать необходимые двоичные файлы / библиотеки или модули ядра.

Если это просто сами ключи, добавление их в конфигурацию любого инструмента, генерирующего initramfs, должно быть довольно простым, при условии, что это разрешено. Если для keyctl требуется символическая ссылка на то же физическое хранилище, вам нужно будет настроить initramfs для выполнения ваших задач после монтирования real_root, но cpio может получить ее там. Если вам нужно вручную добавлять криптомодули, возможно, вас ждет очень веселое времяпрепровождение.

Ядро (начиная с 2.что-то?) также может принимать несколько файлов initramfs, которые он объединит. В прошлый раз, когда я просматривал, у большинства загрузчиков, ориентированных на настольные компьютеры, был какой-то способ сделать это, несмотря на полное молчание документации по этому вопросу… может быть достаточно создать отдельный образ initramfs, содержащий только ваши ключи, и передать оба. Для их создания должно сработать следующее.

 cd /etc/keys
mkdir mkimg
find ./ -maxdepth 1 -type f | 
   sed 's/^[.]///' |
   cpio -o -H newc --no-absolute-filenames --renumber-inodes |
   gzip -9qc - > ./mkimg/bootkeys.img'
  

То, как я это написал, ключи будут сбрасываться в корневой каталог initramfs во время загрузки, что, по моему опыту, проще, чем пытаться объединить каталоги, но измените это, если хотите.

РЕДАКТИРОВАТЬ: я предполагаю, что ваша система не настроена на объединенное монтирование корневых файлов после pivot_root или какой-либо подобной встроенной функции?

Комментарии:

1. Как я упоминал в вопросе, все ключи есть и могут быть добавлены без проблем. Я не получаю никаких ошибок при их загрузке. И после связывания @us с @s я могу даже использовать ключи. Это также показывает, что они были загружены правильно. Любые проблемы с файловой системой могут быть исключены. Я не использую keyctl, но напрямую выполняю те же системные вызовы, которые использовались бы с keyctl или evmctl.

2. Я слышу тебя, с этой точки зрения просто немного расплывчато, какие из ваших результатов собираются после входа в систему, а какие — во время загрузки. Не могли бы вы выполнить чистую загрузку и поделиться « dmesg -Hxf kern,user, auth, системный журнал, демон«

3. Я делаю это syscall во время initramfs . (Вся функция create_ima_keyring ) На данный момент ни один вызов не возвращает результат ошибки. После входа в систему я пытаюсь использовать ключи. keyctl show @u выполняется после входа в систему. Если ключи недоступны для использования, я делаю дополнительные keyctl link @us @s после входа в систему.

4. хорошо … немного почитал, если ваша проблема действительно такая же, как описанная в отчетах systemd и archlinux, то, по-видимому, она связана с изменениями, призванными разрешить подразделениям systemd cgroup иметь свои собственные связки ключей. Короче говоря, похоже, что вам, возможно, придется обойти подсистему, которая хочет обеспечить нераспространение ключей / разрешений в разных процессах входа… но это становится довольно далеким от моей сферы. [продолжение ниже]

5. При этом на справочных страницах в моей системе, похоже, написано «не забудьте связать с -lkeyutils» везде, где это подойдет… Я предполагаю, что вы предпочли бы избежать этого (что при использовании syscall напрямую), но, возможно, стоит проверить, по крайней мере, в целях отладки. И проверьте, что есть в ваших журналах загрузки. В отчете archlinux упоминается, что journalctl выдает сбой systemd, который, по крайней мере, был бы диагностическим. Это, наверное, все, что у меня есть, извините.

Ответ №2:

После еще немного чтения и углубления в конфигурацию оказалось, что требуется дополнительный флаг конфигурации.

Мне пришлось включить, CONFIG_PERSISTENT_KEYRINGS=y и с этим флагом теперь я могу загрузить ключ внутри initramfs и использовать его позже после входа в систему.

Больше никаких жалоб на «no _ima keyring».