第1页
依赖类型的可靠性
(或使用相关类型进行扫视和扑克)
托马斯·哈格伦
SICS,2008年10月21日
(基于2006年12月Chalmers的ProgLog会议演讲)
第2页
豪斯有多安全?
使用GHC(Glasgow Haskell编译器)
- 编译器很大!
- 运行时系统很大!
- 如果我们在Haskell中实现微内核,这将是最大的部分。
- 它能被信任吗?
- 能否正式验证关键属性?
第3页
豪斯有多安全?
Haskell类型的系统能满足我们的需要吗?
- H(硬件)monad接口[1]依赖于运行时检查为了安全
- 虽然安全性没有受到影响,但直到运行时。
- 对于某些事情,无声截断被使用,所以bug会导致错误行为,而不是错误消息。
- 我们不知道如何安全地处理DMA。
第4页
第5页
通过抽象实现安全
- 安全=维护不变量。。。
- 构建保证保持不变量的抽象层
- 显然,大多数代码应该写在安全抽象之上!
第6页
硬件Monad示例
- 安全依据抽象数据类型+无声截断以下为:
类型PAddr=(PhysPage,POffset)类型PhysPage--摘要类型POffset=Word12getPAddr∈PAddr→ H字8setPAddr∈PAddr→ 单词8→ H()allocPhysPage∈H(可能是PhysPage)
- 安全依据抽象数据类型+运行时边界检查以下为:
data MemRegion——抽象类型偏移=字32pokeByteOff∈Storable存储字节⇒ MemRegion(MemRegion)→ 偏移→ 一→ H()peekByteOff∈Storable可存储⇒ MemRegion(MemRegion)→ 抵消→ H a公司
第7页
安全屋:一项实验
- (1) 从一个最小编译器和运行时系统
- 希望可以正式验证关键属性
- 在不牺牲正式验证的情况下扩展它
- (2) 利用依赖类型
- 更多的安全约束可以被捕获为类型安全
- 更多的安全检查可以从运行时转移到编译时
第8页
一个最小编译器和运行时系统
- 编译器:
- Front-end:Alfa[6](编程环境,类型检查)
- Back-end:~750行Haskell代码(不包括标准库)
- 输入:Alfa支持的语言的有用子集
- 输出:C的一个小子集
- 运行时系统大小:~630行C
- 包括一个简单的复制垃圾收集器:约120行C
- 编译时可配置为托管和裸机使用
第9页
编译器和运行时系统
基于<ν,G>机器[2]
- 设计用于支持多处理器机器上的并行执行
- 非常简单的内存管理
- 没有堆栈,一切都在堆中
- GC的根集:只有一个指针(ν,当前的redex)
第10页
一个例子
你好,世界!
- 在电脑屏幕上显示消息的可引导可执行文件。
- 需要写入位于特定位置的文本屏幕缓冲区PC物理内存布局中的绝对地址。
第11页
第12页
第13页
文本屏幕缓冲区访问(1)
- 限制对文本屏幕缓冲区的访问
数据范围=范围{lo,hi∈Addr}屏幕∈范围屏幕=范围0xb8000 0xb8ffeInRange∈范围→ 加法器→ 道具screenPoke∈(a∈Addr)→ InRange屏幕a→ 单词16→ H()
- 实施
screenPoke游戏
可写屏幕∈(a∈Addr)→ InRange屏幕a→ 可写awritableScreen a r=不安全.writablescreenPoke∈(a∈Addr)→ InRange屏幕a→ 单词16→ H()screenPoke a r d=poke16 a(可写Screen a r)d
第14页
第15页
用于显示文本的抽象
- 在特定屏幕位置放置具有属性的字符
- 输出文本(必要时滚动)
- 需要处理额外安全约束的代码是小而本地化!
第16页
第17页
第18页
你好,世界!
main=输入35 12“你好,世界!”()()
- 静态检查:
- 文本屏幕缓冲区外没有戳。
- 消息会显示在屏幕上(不会换行到下一行)。
第19页
问题
- 模运算
- 简单的不等式不成立!
- i<基础+尺寸⇔ i-base<尺寸?
- 基数≤i⇒ 基数≤i+1?
- 终止检查
第20页
未来的工作?
- 对当前的H monad接口进行更多操作。
- 使更复杂的内存访问模式安全:
- 一个独立类型的H单子(略图)?
- 类型中的分离逻辑?[4]
- 验证编译器和运行时系统属性。(使用[5]中的想法?)
第21页
结束
还有问题吗?
第22页
第23页