云厂商普遍用虚拟化来隔离
- 优势
- 可以运行完整的软件栈,包括不同的操作系统
- 灵活的整体资源分配(支持动态迁移)
- 方便的添加、删除、备份(只需文件操作)
- 虚拟机之间的强隔离(唯一能抵御 fork bomb 的方法)
- 问题:太重
- 云:性能损失,尤其是I/O虚拟化
- 用户:两层操作系统导致资源浪费
函数即服务的特点
- orkload特点 –
- 无状态(stateless)
- 运行时间非常短(秒级)
- 两个重要的性能指标
- 启动时间
- 运行密度
Chroot效果
- 控制进程能够访问哪些目录子树
- 改变进程所属的根目录
- 进程只能看到根目录下属的文件
Chroot原理
- 进程只能从根目录向下开始查找文件
- 操作系统内部修改了根目录的位置
- 一个简单的设计
- 内核为每个用户记录一个根目录路径
- 进程打开文件时内核从该用户的根目录开始查找
- 上述设计有什么问题?
- 遇到类似“..”的路径会发生什么?
- 特殊检查根目录下的“..”
- 使得“/..”与“/”等价
- 无法通过“..”打破隔离
- 一个用户想要使不同进程有不同的根目录怎么办?
- 每个TCB都指向一个root目录
- 一个用户可以对多个进程chroot
- 遇到类似“..”的路径会发生什么?
- 安全隔离 – 基于namespace机制
- 性能隔离 – Linux cgroup
- ![LinuX Container资源](图片\LinuX Container资源.png)
- 容器内外可部分共享文件系
- 假设主机操作系统上运行了一个容器
- Step-1:主机OS准备从/mnt目录下的ext4文件系统中读取数据
- Step-2:容器中进程在/mnt目录下挂载了一个xfs文件系统
- Step-3:主机操作系统可能读到错误数据
实现
- 设计思路
- 在内核中分别记录每个NS中对于挂载 点的修改
- 访问挂载点时,内核根据当前NS的记 录查找文件
- 每个NS有独立的文件系统树
- 新NS会拷贝一份父NS的文件系统树
- 修改挂载点只会反映到自己NS的文件系统树
- 假设有两个容器A和B
- A中进程使用名为“ my_mem ”共享内存进行数据共享
- B中进程也使用名为“ my_mem ”共享内存进行通信
- B中进程可能收到A中进程的数据,导致出错以及数据泄露
不好的设计
- 在内核中创建IPC对象时,贴上对应NS的标签
- 进程访问IPC对象时内核来判断是否允许访问该对象
- 问题:可能有timing side channel隐患 ;对于同名的IPC对象不好处理
IPC Namespace的实现
- 假设有两个容器均提供网络服务
- 两个容器的外部用户向同一IP发送网络服务请求
- 主机操作系统不知道该将网络包转发给哪个容器
虚拟机
Network Namespace的实现
- 每个NS拥有一套独立的网络资源
- 包括IP地址、网络设备等
- 新NS默认只有一个loopback设备
- 其余设备需后续分配或从外部加入
- 图例
- 创建相连的veth虚拟设备对
- 一端加入NS即可连通网络
- 分配IP后可分别与外界通信
-
假设有容器内存在一个恶意进程
- 恶意进程向容器外进程发送SIGKILL信号
- 主机操作系统或其他容器中的正常进程会被杀死
-
直接的想法
- 将每个NS中的进程放在一起管理,不同NS中的进程相互隔离
-
存在的问题
- 进程间关系如何处理(比如父子进程)?
-
更进一步
-
允许父NS看到子NS中的进程,保留父子关系
PID Namespace的实现
- 假设一个恶意用户在容器内获取了root权限
- 恶意用户相当于拥有了整个系统的最高权限
- 可以窃取其他容器甚至主机操作系统的隐私信息
- 可以控制或破坏系统内的各种服务
User Namespace的实现
- 对NS内外的UID和GID进行映射
- 允许普通用户在容器内有更高权限
- 基于Linux Capability机制
- 容器内root用户在容器外无特权
- 只是普通用户
- 允许普通用户在容器内有更高权限
- 图例 – 普通用户在子NS中是root用户
如果容器内root要执行特权操作怎么办?
- insmod?一旦允许在内核中插入驱动,则拥有最高权限
- 关机/重启?整个云服务器会受影响
-
从内核角度来看,仅仅是普通用户
-
限制系统调用 – Seccomp机制
- 每个NS拥有独立的hostname等名称
- 便于分辨主机操作系统及其上的多个容器
- cgroupfs的实现向容器内暴露cgroup根目录
- 增强隔离性:避免向容器内泄露主机操作系统信息
- 增强可移植性:取消cgroup路径名依赖
- Cgroups是Linux内核(从Linux2.6.24开始)提供的一种资源隔离的功能
- Cgroups可以做什么
- 将线程分组
- 对每组线程使用的多种物理资源进行限制和监控
- 怎么用Cgroups
- 名为cgroupfs的伪文件系统提供了用户接口
硬件提供不同粒度的隔离环境
Enclave的隔离方法
- 基于权限控制 – 使操作系统没有权限访问用户的数据
- 基于加密 – 操作系统即使访问用户数据,也无法解密
- 基于权限控制+加密 – 隔离防御软件攻击,加密防御硬件攻击
- 基于预留的隔离(硬件)
- 例如:PRM(Processor Reserved Memory)
- CPU预留一部分物理内存,不提供给操作系统
- 基于页表的隔离(操作系统)
- 例如:保证操作系统无法映射应用的物理内存页
- 问题:页表是由操作系统自己管理的,监守自盗?
- 基于插桩的隔离(编译器)
- 例如:SFI(Software Fault Isolation)
- 在每次访存前插入边界检查,性能损失较大
Intel SGX
- SGX: Software Guard eXtension
- 2015年首次引入Intel Skylake架构
- 保护程序和代码在运行时的安全(data in-run)
- 其他安全包括:存储时安全和传输时安全
- 关键技术 – Enclave内部与外部的隔离 – 内存加密与完整性保护 – 远程验证
- 硬件加密保护隐私性
- CPU外皆为密文,包括内存、存储、网络等
- CPU内部为明文,包括各级Cache与寄存器
- 数据进出CPU时,由进行加密和解密操作
- 硬件Merkle Tree保护完整性
- 对内存中数据计算一级hash,对一级hash计算二级hash,形成树
- CPU内部仅保存root hash,其它hash保存在不可信的内存中
- 当内存中的数据被修改时,更新Merkle Tree
-
Enclave是进程的一部分
- Enclave内外共享一个虚拟地址空间
- Enclave内部可以访问外部的内存 • 反之则不行
-
创建Enclave的过程
-
OS创建进程
-
OS分配虚拟地址空间
-
OS将Enclave的code加载到EPC中
并将EPC映射到Enclave的虚拟地址
循环3,完成所有code加载和映射
- 完成进程创建
-
要解决的问题:如何远程判断某个主体是Enclave?
![AMD SEV](图片\AMD SEV.png)
假设同一台物理机上运行着20台虚拟机,每台虚拟机内部有20个进程。若我们采用影子页表(Shadow Page Table)的方式实现内存虚拟化,则共需要多少个影子页表?若采用第二阶段页表的方式来实现内存虚拟化,则共需要多少个第二阶段页表?
影子页表:20*20=400(每个进程一个影子页表)
第二阶段页表:20(每个虚拟机一个第二阶段页表)。
第二阶段页表和影子页表的性能表现在不同种类的应用上各有千秋,请列举两者各适用于什么种类的应用并说明原因。
对于第二阶段页表而言,由于其内存地址翻译既需要查询第一阶段页表有需要查询第二阶段页表,将GVA转化为HPA的过程要更慢;
对于影子页表而言,每当从GVA到GPA的内存映射发生改变时,都需要虚拟机管理器对影子页表进行修改,修改过程开销更高。
因此,对于TLB miss经常发生,需要经常查询页表进行地址翻译的应用而言,采用影子页表更加高效;对于内存映射经常改变的应用而言,则更适合采用第二阶段页表
IOMMU是在IO虚拟化中广泛应用的一类硬件。为何在IO虚拟化中要引入IOMMU这类硬件
IOMMU用于保护虚拟机的隐私内存不会被其他虚拟机发起的恶意DMA请求所访问。SMMU内存储着GPA与HPA,负责从IOVA->GPA->HPA的地址翻译。
容器或虚拟机两种技术通常被用于位于同一物理机上的不同执行环境之间的隔离,此外,近年来新出现的gVisor、AWS Firecracker也已被广泛应用与隔离执行环境中。请尝试分析四种方法在隔离性上的区别
通常而言,操作系统提供给用户程序的接口多于虚拟机管理器提供给虚拟机的接口数目,且操作系统内核的代码相较于虚拟机的代码更为复杂,因此,共享同一个操作系统内核的容器相较于传统的虚拟机而言隔离性更弱。
为了解决共享操作系统内核的问题,gVisor通过插桩系统调用等方式,在容器的基础上减少了不同实例间共享的接口的数目,因此,隔离性相对于容器而言更强。
而AWS Firecracker则采用了在host的用户空间内共享网桥等方式减少虚拟机的启动等开销,作为代价,不同实例间共享了更多接口的Firecracker的隔离性可能弱于传统的虚拟机。