内核与镜像
# 架构图

# clh配置文件
```
vim /etc/containerd/config.toml
```

****找到下面一行****
```
ConfigPath = "/opt/confi- dential-containers/share/defaults/kata-containers/configuration-clh.toml"
```

**进入配置文件**
```
vim /opt/confidential-containers/share/defaults/kata-containers/configuration-clh.toml
```

**配置文件内容**
```
[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
```

**配置文件内容**
```
[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 后保存配置并退出**



**把配置文件复制到内核源目录下**
`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
```

**磁盘镜像文件具体信息**
```
/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`

**查看 IMA 日志**
`dmesg | grep -i ima`

**查找ima文件**
`find / -name "ima"`

**进入ima文件**

**应有的文件**
```
ascii_runtime_measurements
binary_runtime_measurements
policy
runtime_measurements_count
violations
```
**查看security文件**

**启动IMA模块**

**问题**
```
内核编译可能有问题,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**

**添加参数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
```

**输出测量日志**
```
cat /sys/kernel/security/ima/ascii_runtime_measurements
```

**输出日志数量**
```
cat /sys/kernel/security/ima/runtime_measurements_count
```

# 测量容器
**获取源码**
```
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
```
==**找不到补丁**==

**复制内核配置文件**
```
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没有工作**

**获取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);
}
```

**第二个解决方案**
**编译成功,但输出结果不对**

**第三个解决方案**
```
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;
**代码不全,编译出现大量报错**


**使用ima-nsid-cnt模板**

**使用ima-ng模板也可以度量**

**容器和kata虚拟机在同一命名空间**