简体   繁体   English

使用syscall()在initramfs中链接密钥环

[英]Link keyrings in initramfs using syscall()

I want to load certificates for IMA/EVM into Linux keyrings. 我想将IMA / EVM的证书加载到Linux密钥环中。

The related shell commands are 相关的shell命令是

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

This nearly works except for a problem with permissions. 这几乎可以工作,除了权限问题。

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

Searching the web I found this: https://github.com/systemd/systemd/issues/5522 在网上搜索我发现了这个: https//github.com/systemd/systemd/issues/5522

And the workaround is to link the keyrings: 解决方法是链接密钥环:

keyctl link @us @s

If I enter these commands on a shell after booting, I can see the keys: 如果我在启动后在shell上输入这些命令,我​​可以看到键:

# 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

So far so good... 到现在为止还挺好...

To be useful I need to put this stuff into initramfs . 为了有用,我需要把这些东西放到initramfs The system I am dealing with is an embedded Linux where I don't have a shell during initramfs . 我正在处理的系统是嵌入式Linux,我在initramfs期间没有shell。

Therefore I used syscall to do what needs to be done... 因此我使用syscall来做需要做的事情......

Creating the keyrings and importing the keys works fine. 创建密钥环并导入密钥可以正常工作。 But linking the keyrings does not. 但链接密钥环没有。

After booting I get the same "permission denied" error as above. 启动后,我得到与上面相同的“权限被拒绝”错误。 I also get error message when I try to execute a file with IMA signature. 当我尝试使用IMA签名执行文件时,我也收到错误消息。 It says "_ima" keyring was not found. 它说没有找到“_ima”钥匙圈。

If I manually enter keyctl link @us @s everything works again. 如果我手动输入keyctl link @us @s一切正常。

My assumption is that something related to the keyrings is not yet in place during initramfs but I cannot get hold of it. 我的假设是在initramfs期间还没有与keyrings相关的东西,但是我无法掌握它。

The syscall I use for linking is as follows: 我用于链接的syscall如下:

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

I don't get any negative result from the call. 我没有从电话中得到任何负面结果。

UPDATE UPDATE

I found some hints at this page: https://mjg59.dreamwidth.org/37333.html 我在此页面上找到了一些提示: https//mjg59.dreamwidth.org/37333.html

According to this, the sequence should be as follows: 据此,序列应如下:

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

This is valid for keys, but as far as I understand it should be valid for keyrings as well. 这对于密钥有效,但据我所知,它也应该对密钥环有效。

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
    }
}

The error handling was stripped for this example. 此示例删除了错误处理。 I do not get any error results. 我没有得到任何错误结果。

Now I get the expected result from keyctl show @u but the keyring is still not recognized. 现在我从keyctl show @u获得了预期的结果,但密钥环仍然无法识别。 Executing a signed file leads to an error message again: 执行签名文件会再次出现错误消息:

digsig: no _ima keyring: -126

I'm not entirely clear on the actual steps you have taken to populate the initramfs... try examining the contents: (assuming gzip compression, can also try xz/lz4/none) 我不完全清楚你填充initramfs的实际步骤...尝试检查内容:(假设gzip压缩,也可以尝试xz / lz4 / none)

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

My first guess is that you're going to find /etc/keys/x509-blahblah don't exist in the initramfs img. 我的第一个猜测是你要在initramfs img中找不到/etc/keys/x509-blahblah Especially since they're "not found" at boot time but work after login. 特别是因为它们在启动时“找不到”但在登录后工作。 It may also be missing necessary binaries/libs or kernel modules. 它也可能缺少必要的二进制文件/库或内核模块。

If it's just the keys themselves, adding them to whatever initramfs-generating tool's configuration should be fairly straightforward, provided that's allowed. 如果它只是密钥本身,那么将它们添加到initramfs生成工具的配置中应该是相当简单的,前提是允许的。 If keyctl requires a symlink to the same physical storage, you'll need to arrange for initramfs to run your tasks after mounting real_root, but cpio can get one in there. 如果keyctl需要一个符号链接到同一个物理存储,你需要安装initramfs来在安装real_root之后运行你的任务,但是cpio可以在那里得到一个。 If it needs you to add crypto modules by hand you might be in for a very fun time. 如果它需要您手动添加加密模块,您可能会在非常有趣的时间。

The kernel (since 2.something?) can also accept multiple initramfs files, which it will merge. 内核(自2.something?)也可以接受多个initramfs文件,它将合并。 Last time I looked most desktop-targeted bootloaders did have some way of doing this, complete documentation silence on the matter notwithstanding... it may be sufficient to build a seperate initramfs image with just your keys in it and pass both. 上次我看起来大多数以桌面为目标的引导加载程序确实有一些方法可以做到这一点,尽管有完整的文档沉默,但是构建一个单独的initramfs映像只需要你的密钥并传递它们就足够了。 The following should work to create one. 以下应该可以创建一个。

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'

The way I've written it the keys will get dumped into initramfs's root directory at boot time, which in my experience is simpler than trying to get directories to merge, but change that if you like. 我写它的方式将在启动时将密钥转储到initramfs的根目录中,根据我的经验,这比尝试合并目录更简单,但如果你愿意,可以改变它。

EDIT: I assume your system is not configured to union mount the rootfs after pivot_root or some similar embedded-person thing? 编辑:我假设你的系统没有配置为在pivot_root或类似的嵌入式人物之后联合mount rootfs?

After a bit more reading and digging into configuration it turned out that an additional configuration flag is required. 经过一番阅读并深入研究配置后,发现需要一个额外的配置标志。

I had to enable CONFIG_PERSISTENT_KEYRINGS=y and with that flag I can now load the key within initramfs and use it later after login. 我必须启用CONFIG_PERSISTENT_KEYRINGS=y并使用该标志我现在可以在initramfs加载密钥并在以后登录后使用它。

No more "no _ima keyring" complaints. 没有更多的“没有_ima keyring”投诉。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM