Связывание ключей в initramfs с помощью syscall () - PullRequest
6 голосов
/ 29 марта 2019

Я хочу загрузить сертификаты для 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, &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

Ответы [ 2 ]

1 голос
/ 07 апреля 2019

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

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

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

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

Ядро (начиная с 2.something?) Также может принимать несколько файлов 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 во время загрузки, что, по моему опыту, проще, чем пытаться объединить каталоги, но измените, если хотите.

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

0 голосов
/ 10 апреля 2019

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

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

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

...