内核与镜像

# 架构图 ![image.png](https://cos.easydoc.net/36024082/files/ludkq69m.png) # clh配置文件 ``` vim /etc/containerd/config.toml ``` ![image.png](https://cos.easydoc.net/36024082/files/ludiwquy.png) ****找到下面一行**** ``` ConfigPath = "/opt/confi- dential-containers/share/defaults/kata-containers/configuration-clh.toml" ``` ![image.png](https://cos.easydoc.net/36024082/files/ludixeb0.png) **进入配置文件** ``` vim /opt/confidential-containers/share/defaults/kata-containers/configuration-clh.toml ``` ![image.png](https://cos.easydoc.net/36024082/files/ludiytmd.png) **配置文件内容** ``` [hypervisor.clh] path = "/opt/confidential-containers/bin/cloud-hypervisor" kernel = "/opt/confidential-containers/share/kata-containers/vmlinux.container" image = "/opt/confidential-containers/share/kata-containers/kata-containers.img" ``` # Qemu配置文件 ``` vim /etc/containerd/config.toml ``` ****找到下面一行**** ``` ConfigPath="/opt/confidential-containers/share/defaults/kata-containers/configuration-qemu.toml" ``` **进入配置文件** ``` vim /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu.toml ``` ![image.png](https://cos.easydoc.net/36024082/files/ludj11ep.png) **配置文件内容** ``` [hypervisor.qemu] path = "/opt/confidential-containers/bin/qemu-system-x86_64" kernel = "/opt/confidential-containers/share/kata-containers/vmlinux.container" image = "/opt/confidential-containers/share/kata-containers/kata-containers.img" # initrd = "/opt/confidential-containers/share/kata-containers/kata-containers-initrd.img" machine_type = "q35" ``` # 使用qemu创建虚拟机 **命令** ` /opt/confidential-containers/bin/qemu-system-x86_64 -kernel /opt/confidential-containers/share/kata-containers/vmlinux.container -drive file=/opt/confidential-containers/share/kata-containers/kata-containers.img,format=raw -machine type=q35 ` **报错** ``` qemu-system-x86_64: failed to find romfile "vgabios-stdvga.bin" qemu-system-x86_64: failed to find romfile "efi-e1000.rom" qemu-system-x86_64: failed to find romfile "efi-e1000e.rom" ``` **解决办法** ``` sudo yum install seabios wget https://github.com/qemu/qemu/blob/master/pc-bios/efi-e1000.rom wget https://github.com/qemu/qemu/blob/master/pc-bios/efi-e1000e.rom mv efi-e1000.rom /usr/share/seavgabios mv efi-e1000e.rom /usr/share/seavgabios ln -s /usr/share/seavgabios/vgabios-stdvga.bin /opt/confidential-containers/share/kata-qemu/qemu/vgabios-stdvga.bin ln -s /usr/share/seavgabios/efi-e1000.rom /opt/confidential-containers/share/kata-qemu/qemu/efi-e1000.rom ln -s /usr/share/seavgabios/efi-e1000e.rom /opt/confidential-containers/share/kata-qemu/qemu/efi-e1000e.rom ``` **继续运行** `/opt/confidential-containers/bin/qemu-system-x86_64 -kernel /opt/confidential-containers/share/kata-containers/vmlinux-5.19.2-96 -drive file=/opt/confidential-containers/share/kata-containers/kata-containers.img,format=raw -machine type=q35 ` **下步工作** ``` - 了解IMA - 重新构建kernel image - 自己找一个镜像,使用kata-qemu run - Linux修改内核 - qemu -device nvdimm kata rootfs - nvdimm 是一种断电后依然可以保存数据的内存模块,用于提供虚拟机的根文件系统 - IMA在内核中,应该重写内核,那文件系统镜像还用改吗? ``` **继续创建qemu虚拟机** `/opt/confidential-containers/bin/qemu-system-x86_64 -machine q35,accel=kvm,nvdimm=on -cpu host,pmu=off -m 2048M,slots=10,maxmem=4913M -device pci-bridge,bus=pcie.0,id=pci-bridge-0,chassis_nr=1,shpc=off,addr=2,io-reserve=4k,mem-reserve=1m,pref64-reserve=1m -device virtio-serial-pci,disable-modern=true,id=serial0 -device nvdimm,id=nv0,memdev=mem0,unarmed=on -object memory-backend-file,id=mem0,mem-path=/opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image,size=268435456,readonly=on -device virtio-scsi-pci,id=scsi0,disable-modern=true -object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0 -rtc base=utc,driftfix=slew,clock=host -global kvm-pit.lost_tick_policy=discard -vga none -no-user-config -nodefaults -nographic --no-reboot -daemonize -object memory-backend-file,id=dimm1,size=2048M,mem-path=/dev/shm,share=on -numa node,memdev=dimm1 -kernel /opt/confidential-containers/share/kata-containers/vmlinux-5.19.2-96 -smp 1,cores=1,threads=1,sockets=4,maxcpus=4` **问题** ``` 怎么进入到qemu创建的虚拟机中? virsh 、ssh 、vnc ``` **加入“-serial stdio”** `/opt/confidential-containers/bin/qemu-system-x86_64 -machine q35,accel=kvm,nvdimm=on -cpu host,pmu=off -m 2048M,slots=10,maxmem=4913M -device pci-bridge,bus=pcie.0,id=pci-bridge-0,chassis_nr=1,shpc=off,addr=2,io-reserve=4k,mem-reserve=1m,pref64-reserve=1m -device virtio-serial-pci,disable-modern=true,id=serial0 -device nvdimm,id=nv0,memdev=mem0,unarmed=on -object memory-backend-file,id=mem0,mem-path=/opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image,size=268435456,readonly=on -device virtio-scsi-pci,id=scsi0,disable-modern=true -object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0 -rtc base=utc,driftfix=slew,clock=host -global kvm-pit.lost_tick_policy=discard -vga none -no-user-config -nodefaults -nographic --no-reboot -object memory-backend-file,id=dimm1,size=2048M,mem-path=/dev/shm,share=on -numa node,memdev=dimm1 -kernel /opt/vmlinux-5.19.2 -smp 1,cores=1,threads=1,sockets=4,maxcpus=4 -serial stdio` **查看运行中的qemu虚拟机** `ps aux | grep /opt/confidential-containers/bin/qemu-system-x86_64` # IMA模块 参考文档: [https://www.neko.ooo/linux-ima-enable-test/](https://www.neko.ooo/linux-ima-enable-test/) [https://sourceforge.net/p/linux-ima/wiki/Home/](https://sourceforge.net/p/linux-ima/wiki/Home/) # 重新构建内核 **获取源码** `wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.19.2.tar.xz` **解压** `tar xvf linux-5.19.2.tar.xz` **下载工具包** ``` sudo yum groupinstall "Development Tools" sudo yum install ncurses-devel ``` **配置内核** ``` cd linux-5.19.2 make menuconfig ``` **报错1** `-bash: make: 未找到命令` **解决** `sudo dnf install -y cmake gcc gcc-c++` **报错2** ``` HOSTCC scripts/basic/fixdep * * Unable to find the ncurses package. * Install ncurses (ncurses-devel or libncurses-dev * depending on your distribution). * * You may also need to install pkg-config to find the * ncurses installed in a non-default location. * make[1]: *** [scripts/kconfig/Makefile:212:scripts/kconfig/mconf-cfg] 错误 1 make: *** [Makefile:629:menuconfig] 错误 2 ``` **解决** `sudo yum install ncurses-devel` **启用 IMA 后保存配置并退出** ![image.png](https://cos.easydoc.net/36024082/files/ludkc63p.png) ![1 1.png](https://cos.easydoc.net/36024082/files/ludm43jf.png) ![1 1.png](https://cos.easydoc.net/36024082/files/ludm5y6z.png) **把配置文件复制到内核源目录下** `cp /opt/config-5.19.2 linux-5.19.2 ` **重命名** `mv config-5.19.2 .config ` **编译内核** `make vmlinux` **清除原来安装的内核** `make clean` # 构建根文件系统 **创建一个空白磁盘映像** `dd if=/dev/zero of=image/kata.image bs=1M count=256` **创建分区** ``` fdisk image/kata.image n:创建新分区 d:删除分区 q:不保存退出 w:保存退出 a:设置分区为active ``` **查看分区** `fdisk -l image/kata.image` **将文件设置为循环设备** ``` losetup -fP /opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image /opt/kata.image ``` **查看循环设备** `losetup -a` **格式化磁盘映像文件的分区** ``` mkfs -t ext4 /dev/loop0p1 mkfs -t ext4 /dev/loop0p2 ``` **创建挂载目录** ``` mkdir /mnt/kata-p1 mkdir /mnt/kata-p2 ``` **挂载** ``` mount /dev/loop0p1 /mnt/kata-p1 mount /dev/loop0p2 /mnt/kata-p2 ``` **查看挂载信息** `df -h` **解除挂载** ``` umount /mnt/kata-p1 umount /mnt/kata-p2 ``` **取消循环设备** `losetup -d /dev/loop0` **查看文件信息** ``` file -s /dev/loop0p1 file -s /dev/loop0p2 ``` ![image.png](https://cos.easydoc.net/36024082/files/ludkdo6a.png) **磁盘镜像文件具体信息** ``` /opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x30,0,1), end-CHS (0x3ff,3,32), startsector 6144, 487424 sectors; partition 2 : ID=0x83, start-CHS (0x3ff,3,32), end-CHS (0x3ff,3,32), startsector 493568, 28672 sectors /opt/kata/share/kata-containers/kata-ubuntu-latest.image: DOS/MBR boot sector; partition 1 : ID=0x83, start-CHS (0x30,0,1), end-CHS (0x3ff,3,32), startsector 6144, 516096 sectors image/kata.image: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,97,34), end-CHS (0x1e,184,26), startsector 6144, 487424 sectors; partition 2 : ID=0x83, start-CHS (0x1e,184,27), end-CHS (0x20,129,33), startsector 493568, 28672 sectors ``` **下一步工作** ``` - 看论文 - 将IMA与容器关联起来 - 然后再实现aa ``` **继续试验qemu虚拟机** `/opt/confidential-containers/bin/qemu-system-x86_64 -m 2048M -cpu host -kernel /opt/bzImage -drive file=/opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image,format=raw -nographic -no-reboot` `qemu-system-x86_64 -kernel /opt/bzImage -hda /opt/confidential-containers/share/kata-containers/kata-ubuntu-latest.image` # 检查IMA是否启动 `ssh -i ccv0-ssh root@10.101.47.128` **查看内核配置** `zcat /proc/config.gz | grep CONFIG_IMA` ![2 1.png](https://cos.easydoc.net/36024082/files/ludm7zdh.png) **查看 IMA 日志** `dmesg | grep -i ima` ![image.png](https://cos.easydoc.net/36024082/files/ludkebkx.png) **查找ima文件** `find / -name "ima"` ![image.png](https://cos.easydoc.net/36024082/files/ludkeoxo.png) **进入ima文件** ![image.png](https://cos.easydoc.net/36024082/files/ludkfelm.png) **应有的文件** ``` ascii_runtime_measurements binary_runtime_measurements policy runtime_measurements_count violations ``` **查看security文件** ![image.png](https://cos.easydoc.net/36024082/files/ludkfrdd.png) **启动IMA模块** ![image.png](https://cos.easydoc.net/36024082/files/ludkfv6g.png) **问题** ``` 内核编译可能有问题,IMA模块并未正确加载 该容器镜像不支持IMA ``` **思路** ``` Kata如何给内核传参数 必须进入虚拟机,查看文件组成 ``` # 启动kata虚拟机的IMA测量与评估功能 **给内核传参** **进入配置文件** ``` vim /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu.toml ``` **添加内核** ```yaml [hypervisor.qemu] path = "/opt/confidential-containers/bin/qemu-system-x86_64" #kernel = "/opt/confidential-containers/share/kata-containers/vmlinux.container" kernel = "/opt/bzImage" image = "/opt/confidential-containers/share/kata-containers/kata-containers.img" # initrd = "/opt/confidential-containers/share/kata-containers/kata-containers-initrd.img" machine_type = "q35" ``` **找到kernel_params** ![image.png](https://cos.easydoc.net/36024082/files/lufhaj6e.png) **添加参数ima_tcb ima_appraise_tcb ima_appraise=fix ima_template=ima-ng ima_hash=sha256** ``` kernel_params = "ima_tcb ima_appraise_tcb ima_appraise=fix ima_template=ima-ng ima_hash=sha256 cc_rootfs_verity.scheme=dm-verity cc_rootfs_verity.hash=7c45fe8a04c18da806b37a2e760966980d487387aa54d177d11cae108bc75d98 agent.enable_signature_verification=false agent.config_file=/etc/agent-config.toml" ``` **ima目录挂载** **进入配置文件** ``` vim coco-demo.yaml ``` **添加volumes和volumeMounts** ``` kind: Service apiVersion: v1 metadata: name: coco-demo spec: selector: app: coco-demo ports: - port: 22 --- kind: Deployment apiVersion: apps/v1 metadata: name: coco-demo spec: selector: matchLabels: app: coco-demo template: metadata: labels: app: coco-demo spec: runtimeClassName: kata-qemu containers: - name: coco-demo image: docker.io/katadocker/ccv0-ssh imagePullPolicy: Always volumeMounts: - name: ima-config-volume mountPath: /sys/kernel/security volumes: - name: ima-config-volume hostPath: path: /sys/kernel/security type: Directory ``` **进入机密容器** ``` ssh -i ccv0-ssh root@10.103.150.221 ``` **找到ima目录** ``` ls /sys/kernel/security/ima ``` ![image.png](https://cos.easydoc.net/36024082/files/lufhokct.png) **输出测量日志** ``` cat /sys/kernel/security/ima/ascii_runtime_measurements ``` ![image.png](https://cos.easydoc.net/36024082/files/lufhqibc.png) **输出日志数量** ``` cat /sys/kernel/security/ima/runtime_measurements_count ``` ![image.png](https://cos.easydoc.net/36024082/files/lufi1msq.png) # 测量容器 **获取源码** ``` git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git ``` **进入目录** ``` cd linux-stable git checkout linux-5.13.y ``` **编辑ima_template.c文件** ```c vim ./security/integrity/ima/ima_template.c static const struct ima_template_field supported_fields[] = { ... {.field_id = "cg-path", .field_init = ima_eventcg_path_init, .field_show = ima_show_template_string}, }; static struct ima_template_desc builtin_templates[] = { ... {.name = "ima-cgpath", .fmt = "dep|cg-path|d-ng|n-ng"}, }; ``` **编辑ima_template_lib.h文件** ```c vim ./security/integrity/ima/ima_template_lib.h int ima_eventcg_path_init(struct ima_event_data *event_data, struct ima_field_data *field_data); ``` **编辑ima_template_lib.c文件** ```c vim ./security/integrity/ima/ima_template_lib.c int ima_eventcg_path_init(struct ima_event_data *event_data,struct ima_field_data *field_data) { char *cgroup_path_str = NULL; struct cgroup *cgroup = NULL; int rc = 0; cgroup_path_str = kmalloc(PATH_MAX, GFP_KERNEL); if (!cgroup_path_str) return -ENOMEM; cgroup = task_cgroup(current, 1); if (!cgroup) goto out; rc = cgroup_path(cgroup, cgroup_path_str, PATH_MAX); if (!rc) goto out; rc = ima_write_template_field_data(cgroup_path_str,strlen(cgroup_path_str), DATA_FMT_STRING, field_data); kfree(cgroup_path_str); return rc; out: return ima_write_template_field_data("-", 1, DATA_FMT_STRING, field_data); } ``` **编辑Kconfig文件** ```c vim ./security/integrity/ima/Kconfig choice prompt "Default template" default IMA_NG_TEMPLATE depends on IMA ... config IMA_DEP_CGN_TEMPLATE bool "ima-dep-cgn" config IMA_CGPATH_TEMPLATE bool "ima-cgpath" endchoice config IMA_DEFAULT_TEMPLATE string depends on IMA default "ima" if IMA_TEMPLATE ... default "ima-dep-cgn" if IMA_DEP_CGN_TEMPLATE default "ima-cgpath" if IMA_CGPATH_TEMPLATE ``` **添加补丁** ``` git config --global user.email "you@example.com" git config --global user.name "Your Name" git am --signoff < /patches_dir/0001-ima_cgn_template.patch git am --signoff < /patches_dir/0002-ima_mns_template.patch git am --signoff < /patches_dir/0003-entry_hash_256_bit.patch git am --signoff < /patches_dir/0004-ima_dep_cgn_template.patch git am --signoff < /patches_dir/0005-ima_cache_clp_patch.patch git am --signoff < /patches_dir/0006-ima_cgpath_template.patch ``` ==**找不到补丁**== ![图片.png](https://cos.easydoc.net/36024082/files/luqwuf66.png) **复制内核配置文件** ``` cp -v /opt/config-5.19.2 .config ``` **配置文件** ``` make menuconfig ``` **注释以下内容** ``` CONFIG_MODULE_SIG_KEY="certs/signing_key.pem" CONFIG_SYSTEM_TRUSTED_KEYRING=y CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem" ``` **编译** ``` make ``` **使用编译好的内核,发现IMA没有工作** ![图片.png](https://cos.easydoc.net/36024082/files/luqwy8sc.png) **获取Linux源码** ``` git clone https://github.com/stefanberger/linux-ima-namespaces.git ``` **启用IMA** ``` cp -v /opt/config-5.19.2 .config make menuconfig ``` **IMA代码修改** ``` struct ima_namespace { int id; ... } __randomize_layout; static inline u32 ima_ns_id_from_user_ns(struct user_namespace *user_ns) { struct ima_namespace *ima_ns = ima_ns_from_user_ns(user_ns); return ima_ns->id; } static struct ima_template_desc builtin_templates[] = { ... {.name = "ima-nsid-cnt", .fmt = "d-ng|n-ng|id|num_mes"}, }; static const struct ima_template_field supported_fields[] = { ... {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init, .field_show = ima_show_template_digest_ng}, {.field_id = "n-ng", .field_init = ima_eventname_ng_init, .field_show = ima_show_template_string}, {.field_id = "id", .field_init = ima_id_init, .field_show = ima_show_template_id}, {.field_id = "num_mes", .field_init = ima_num_mes_init, .field_show = ima_show_template_id}, }; if(starting_ima_ns_id == ns->id) { mutex_lock(&vett_queue_mutex); vett_queue[next_empty_slot] = ns->id; next_empty_slot = (next_empty_slot + 1)% MAX_VETT_QUEUE_LEN; mutex_unlock(&vett_queue_mutex); } while(vett_queue[actual_id] != starting_ima_ns_id); if(user_ns != NULL) { starting_ima_ns = ima_ns_from_user_ns(user_ns); while(starting_ima_ns == NULL) { starting_ima_ns = ima_ns_from_user_ns(father->parent); father = father->parent; } starting_ima_ns_id = starting_ima_ns->id; } while (user_ns) { ns = ima_ns_from_user_ns(user_ns); if (ns_is_active(ns)) { num_measurements++; rc = __process_measurement(ns, file, cred, secid, buf, size, mask, func, num_measurements, starting_ima_ns_id); ... } user_ns = user_ns->parent; } static DEFINE_MUTEX(atomic_parent_extension_mutex); struct ns_common *imans_get(struct task_struct *task) void userns_put(struct ns_common *ns) int userns_install(struct nsset *nsset, struct ns_common *ns) struct user_namespace *userns_owner(struct ns_common *ns) struct mutex * ``` **第一个解决方案** ``` #代码不全,无法编译 {.field_id = "id", .field_init = ima_id_init, .field_show = ima_show_template_id}, {.field_id = "num_mes", .field_init = ima_num_mes_init, .field_show = ima_show_template_id}, ``` ``` #添加ima_show_template_id函数 void ima_show_template_id(struct seq_file *m, enum ima_show_type show,struct ima_field_data *field_data) { ima_show_template_field_data(m, show, DATA_FMT_UINT, field_data); } ``` ![捕获.PNG](https://cos.easydoc.net/36024082/files/lvddccjk.PNG) **第二个解决方案** **编译成功,但输出结果不对** ![图片.png](https://cos.easydoc.net/36024082/files/lv249wdr.png) **第三个解决方案** ``` vim ./security/integrity/ima/ima_fs.c 添加 #include "../include/linux/proc_ns.h" 查找 find ./ -type f -name "*.c" | xargs grep -H "lookup_template_field" ``` ``` vim ./security/integrity/ima/ima.h 添加 struct ima_namespace { int id; struct mutex npcr_lock; u8 *vPCR; } struct ima_event_data { u32 ima_ns_id; u8 *template_start_digest; }; struct ns_common *imans_get(struct task_struct *task); void userns_put(struct ns_common *ns); int userns_install(struct nsset *nsset, struct ns_common *ns); struct user_namespace *userns_owner(struct ns_common *ns); ``` ``` vim ./security/integrity/ima/ima_template_lib.h 添加 int vprc_extension(u8 *vpcr_value, u8 *value_to_extend); void host_extension_vpcr(int start_ima_ns_id, u8 *template_digest); int digest_namespace_event_init(struct ima_event_data *event_data, struct ima_field_data *field_data); int ima_id_init(struct ima_event_data *event_data, struct ima_field_data *field_data); ``` ``` vim ./security/integrity/ima/ima_template_lib.c 添加 void host_extension_vpcr(int start_ima_ns_id, u8 *template_digest) { int result = -ENOMEM; struct ima_event_data *event_data; struct ima_template_desc *template_desc; int template_num_fields = 2; int violation = 0; struct ima_template_entry *entry; int PCR = 10; const struct ima_template_field *info_ev = lookup_template_field("digev"); const struct ima_template_field *creator = lookup_template_field("imansid"); const struct ima_template_field **fields_const = (const struct ima_template_field**)kzalloc(template_num_fields * sizeof(struct ima_template_field*), GFP_NOFS); fields_const[0] = info_ev; fields_const[1] = creator; event_data->ima_ns_id = start_ima_ns_id; event_data->template_start_digest = template_digest; template_desc->num_fields = template_num_fields; template_desc->fields = fields_const; result = ima_alloc_init_template(event_data, &entry, template_desc); result = ima_store_template(&init_ima_ns, entry, violation, NULL, NULL, PCR); return; } ``` static struct ima_algo_desc *ima_algo_array; **代码不全,编译出现大量报错** ![捕获1.PNG](https://cos.easydoc.net/36024082/files/lvddcu09.PNG) ![图片.png](https://cos.easydoc.net/36024082/files/lv24bwx7.png) **使用ima-nsid-cnt模板** ![图片.png](https://cos.easydoc.net/36024082/files/lvxe9cy9.png) **使用ima-ng模板也可以度量** ![图片.png](https://cos.easydoc.net/36024082/files/lvxe9wsk.png) **容器和kata虚拟机在同一命名空间**