第10章 安全性

贾尔斯:哎呀,看在老天的份上,小心点…… 要是你受伤或者送命,我会很生气的。 薇洛:嗯,我们尽量不送命。这可是我们使命宣言的一部分:别送命。 贾尔斯:很好。

——《吸血鬼猎人巴菲》第三季,“安妮” 一集

“不造成人员伤亡” 应成为每位软件架构师使命宣言的一部分。

软件可能导致人员伤亡、造成损害,这种想法曾一度只存在于计算机失控的科幻小说领域。想想在经典老片《2001:太空漫游》中,哈尔彬彬有礼地拒绝打开舱门,致使戴夫被困太空。

遗憾的是,如今这已不再仅仅是科幻情节。随着软件在我们生活中控制的设备越来越多,软件安全已成为一个至关重要的问题。

软件(由 0 和 1 组成的字符串)竟能造成伤亡或破坏,这一概念仍让人觉得匪夷所思。公平地说,造成破坏的并非这些 0 和 1—— 至少不是直接造成的。而是它们所连接的事物。软件及其运行的计算机,必须以某种方式与外部世界相连,才可能造成损害。这算是个好消息。但坏消息是,这个好消息也没那么好。软件始终与外部世界相连。如果你的程序对外部毫无可观测的影响,那它可能毫无用处。

2009 年,舒申斯卡亚水电站的一名员工通过网络远程操作时,因几个错误的按键,意外启动了一台闲置的涡轮机。这台离线的涡轮机引发了 “水锤效应”,导致电站被洪水淹没并遭到破坏,数十名工人丧生。

类似的臭名昭著的例子还有很多。Therac 25 放射治疗仪导致的致命辐射过量事故、阿丽亚娜 5 型火箭爆炸,以及其他许多不太知名的事故,都是因为计算机与外部环境相连而造成了危害:上述例子中分别是涡轮机、X 射线发射器和火箭的转向控制系统。臭名昭著的 “震网” 病毒则是被蓄意制造出来造成破坏的。在这些案例中,软件指令其所处环境中的某些硬件采取了灾难性的行动,而硬件照做了。执行器是连接硬件与软件的设备,它们是 0 和 1 的数字世界与运动和控制的现实世界之间的桥梁。向执行器发送一个数字值(或在与执行器对应的硬件寄存器中写入一个位串),这个值就会转化为某种机械动作,无论好坏。

但与外部世界相连并不一定意味着连接机械臂、铀离心机或导弹发射器:连接一个简单的显示屏就足够了。有时,计算机只需向操作人员发送错误信息。1983 年 9 月,一颗苏联卫星向其地面系统计算机发送数据,该计算机将这些数据解读为美国发射了一枚瞄准莫斯科的导弹。几秒钟后,计算机又报告有第二枚导弹在飞行。很快,第三枚、第四枚、第五枚导弹的信号相继出现。苏联战略火箭军中校斯坦尼斯拉夫・叶夫格拉福维奇・彼得罗夫做出了惊人的决定,他认为计算机出错,选择无视这些信息。他觉得美国不太可能只发射几枚导弹,从而引发大规模报复性破坏。他决定等待,看看这些导弹是否真的存在,也就是说,看看自己国家的首都是否会被焚毁。如我们所知,并没有导弹来袭。苏联的系统把一种罕见的阳光反射条件误判为飞行中的导弹。你和(或)你的父母很可能要感谢彼得罗夫中校的救命之恩。

当然,当计算机出错时,人类也并非总能做出正确判断。2009 年 6 月 1 日暴风雨的夜晚,法国航空 447 号航班从里约热内卢飞往巴黎,尽管飞机发动机和飞行控制系统运行正常,但飞机仍坠入大西洋,机上 228 人全部遇难。这架空客 A - 330 的飞行记录器直到 2011 年 5 月才找到,记录显示飞行员始终未察觉飞机进入了高空失速状态。测量空速的传感器被冰堵塞,导致数据不可靠,自动驾驶仪因此解除了。人类飞行员以为飞机飞得太快(有结构损坏的危险),而实际上飞机飞得太慢(正在坠落)。在飞机从 35000 英尺高空坠落的 3 分多钟里,飞行员一直试图拉起机头并减小油门以降低速度,而他们真正需要做的是压低机头以提高速度,恢复正常飞行。很可能加剧混乱的是 A - 330 失速警告系统的工作方式。当系统检测到失速时,会发出响亮的警报声。当软件 “认为” 仰角测量值无效时,就会停用失速警告。空速读数很低时就会出现这种情况。法航 447 号航班就是如此:其前进速度降至 60 节以下,仰角极高。由于这种飞行控制软件规则,失速警告多次响起又停止。更糟糕的是,每当飞行员向前推杆(增加空速,使读数进入 “有效” 范围,但仍处于失速状态)时,警报就会响起,而当他向后拉杆时,警报就会停止。也就是说,做正确的操作却得到了完全错误的反馈,反之亦然。这是一个不安全的系统,还是一个被不安全操作的安全系统呢?最终,这类问题要由法庭来裁决。

在本书即将出版之时,波音公司仍因 737 MAX 飞机停飞而陷入困境。两起坠机事故似乎至少部分是由一个名为 MCAS 的软件造成的,该软件在错误的时间将飞机机头向下推。这里似乎也涉及传感器故障,以及一个令人费解的设计决策,即该软件仅依赖一个传感器来决定其运行状态,而飞机上其实有两个可用传感器。此外,波音公司似乎从未在传感器故障的条件下测试过该软件。该公司确实提供了一种在飞行中禁用该系统的方法,但当飞机几乎要坠毁时,要求机组人员记住如何操作,这可能有些强人所难 —— 尤其是他们一开始根本不知道 MCAS 的存在。737 MAX 的两起坠机事故共造成 346 人死亡。

好了,恐怖的故事讲得够多了。让我们来谈谈这些故事背后影响软件和架构的原理。

安全性涉及系统避免陷入导致其环境中的参与者受到损害、伤害或生命损失的状态的能力。这些不安全状态可能由多种因素引起:

  • 遗漏(某个事件未发生)。
  • 错误执行(出现了不期望的事件)。该事件在某些系统状态下可能是可以接受的,但在其他状态下则不可接受。
  • 时间问题。时间过早(事件在规定时间之前发生)或过晚(事件在规定时间之后发生)都可能引发潜在问题。
  • 系统值问题。这分为两类:明显错误的值虽然错误但容易被检测,而细微错误的值通常难以察觉。
  • 序列遗漏和错误执行。在一系列事件中,要么某个事件缺失(遗漏),要么插入了意外事件(错误执行)。
  • 顺序错误。一系列事件到达,但顺序与规定不符。

安全性还涉及检测这些不安全状态并从中恢复,以防止或至少尽量减少由此造成的损害。

系统的任何部分都可能导致不安全状态:软件、硬件部分或环境都可能以意想不到的、不安全的方式运行。一旦检测到不安全状态,系统可能的响应与 第 4 章 中列举的可用性响应类似。应识别不安全状态,并通过以下方式使系统恢复安全:

  • 从不安全状态恢复后继续运行,或将系统置于安全模式,或者
  • 关闭(故障安全),或者
  • 转换到需要手动操作的状态(例如,如果汽车的动力转向系统故障,则采用手动转向)。

此外,应立即报告和(或)记录不安全状态。

为实现安全性而进行架构设计,首先要通过故障模式与影响分析(FMEA,也称为危害分析)和故障树分析(FTA)等技术,识别系统的安全关键功能 —— 即那些可能如前文所述造成危害的功能。FTA 是一种自上而下的演绎方法,用于识别可能导致系统进入不安全状态的故障。一旦确定了故障,架构师就需要设计机制来检测和减轻故障(最终减轻危害)。

本章概述的技术旨在发现系统运行可能导致的潜在危害,并帮助制定应对这些危害的策略。

10.1 安全性通用场景

基于上述背景,我们可以构建如 表 10.1 所示的安全性通用场景。

表10.1 安全性通用场景

场景部分 描述 可能的值
来源 数据源(传感器、计算数值的软件组件、通信信道)、时间源(时钟),或者一次用户操作 以下各项的具体实例:
<li>传感器
<li>软件组件
<li>通信通道
<li>设备(如时钟)
触发事件 遗漏、错误执行,或出现不正确的数据或时间问题 遗漏的具体示例:
<li>一个值始终未送达。
<li>一项功能始终未执行。

错误执行的具体示例:
<li>一项功能执行错误。
<li>设备产生了虚假事件。
<li>设备生成不正确的数据。

数据错误的具体示例:
<li>传感器报告了错误数据。
<li>软件组件产生了错误结果。

时间故障:
<li>数据到达太晚或太早。
<li>生成的事件发生得太晚、太早或速率错误。
<li>事件的发生顺序错误。
环境 系统运行模式 <li>正常运行
<li>降级的运行
<li>手动运行
<li>恢复模式
构件 构件是系统的某个部分。 系统中关乎安全的关键部分
响应 系统不会脱离安全状态空间,或者系统返回安全状态空间,又或者系统以降级模式继续运行,以防止(进一步的)伤害或损坏,或将伤害或损坏降至最低。告知用户不安全状态或已防止进入不安全状态。同时记录该事件。 识别不安全状态,并采取以下一项或多项措施:
<li>避免进入不安全状态
<li>恢复
<li>以降级模式或安全模式继续运行
<li>关闭
<li>切换到手动操作
<li>切换到备用系统
<li>通知相关实体(人员或系统)
<li>记录不安全状态(及其应对措施)
响应度量 返回安全状态空间所需时间;已造成的损害或伤害 以下一项或多项指标:
<li>避免进入不安全状态的次数或比例
<li>系统能够(自动)从中恢复的不安全状态的次数或比例
<li>风险暴露的变化:损失规模 * 损失概率
<li>系统能够恢复的时间占比
<li>系统处于降级模式或安全模式的时长
<li>系统关闭的时长或时间占比
<li>进入(手动操作、安全或降级模式)以及从中恢复所花费的时间

安全场景示例:“患者监护系统中的一个传感器在100毫秒后未能报告危及生命的值。系统记录该故障,控制台上的警示灯亮起,同时启用备用(精度较低)的传感器。不超过300毫秒后,系统使用备用传感器对患者进行监测。” 图10.1 展示了此场景。

A sample concrete safety scenario is presented.

图10.1 安全性场景的具体示例

10.2 安全性策略

安全性策略大致可分为避免不安全状态、检测不安全状态或纠正不安全状态。图10.2 展示了这一系列安全性策略的目标。

The goal of safety tactics to control response diagram is presented. The stimulus is the unsafe state entered or imminent. The response is unsafe state detected, avoided, or contained; recovery occurs; and safe operation continues.

图10.2 安全性策略的目标

要避免或检测到进入不安全状态,一个逻辑前提是能够识别什么构成不安全状态。以下策略假定具备这种能力,这意味着一旦你有了架构,就应该自行开展危害分析或故障树分析。你的设计决策本身可能引入了需求分析阶段未考虑到的新安全性漏洞。

你会注意到,此处介绍的策略与 第 4 章 中关于可用性的策略有大量重叠。之所以出现这种重叠,是因为可用性问题往往会导致安全性问题,而且修复这些问题的许多设计解决方案在这两种质量属性方面是通用的。

图10.3 总结了实现安全性的架构策略。

A flowchart of the safety tactics.

图10.3 安全性策略

避免不安全状态

替换

此策略针对潜在危险的软件设计特性采用保护机制,这类机制通常基于硬件。例如,诸如看门狗、监视器和联锁装置等硬件保护设备可用来替代软件版本。这些机制的软件版本可能会缺乏资源,而单独的硬件设备能自行提供和控制自身资源。仅当被替换的功能相对简单时,替换策略通常才会有成效。

预测模型

第 4 章 所介绍的,预测模型策略通过(基于对状态的监测)预测系统进程、资源或其他属性的健康状态,不仅确保系统在其标称运行参数范围内运行,还能对潜在问题发出早期预警。例如,一些汽车巡航控制系统会计算车辆与前方障碍物(或另一辆车)之间的接近速度,并在距离和时间过小到可能导致碰撞之前向驾驶员发出警告。预测模型通常与状态监测相结合,我们稍后会讨论状态监测。

检测不安全状态

超时

超时策略用于判断组件的操作是否满足其时间约束。这可以通过引发异常的形式实现,以表明如果组件未满足其时间约束则发生了失效。因此,此策略可检测到时间过晚和遗漏故障。超时在实时或嵌入式系统以及分布式系统中是一种尤为常见的策略。它与系统监控、心跳和 ping - echo 等可用性策略相关。

时间戳

第 4 章 所述,时间戳策略主要用于检测分布式消息传递系统中事件的错误顺序。在事件发生后,可通过将本地时钟的状态立即赋给该事件来确定事件的时间戳。序列号也可用于此目的,因为分布式系统中的时间戳在不同处理器之间可能不一致。

状态监测

此策略涉及检查进程或设备中的状态,或通过使用断言等方式验证设计过程中做出的假设。状态监测可识别可能导致危险行为的系统状态。然而,监测器应简单(理想情况下可证明其正确性),以确保它不会引入新的软件错误,也不会显著增加总体工作量。状态监测为预测模型和合理性检查提供输入。

合理性检查

合理性检查策略用于检查特定操作结果、组件的输入或输出的有效性或合理性。此策略通常基于对内部设计、系统状态或所审查信息性质的了解。它最常在接口处使用,以检查特定的信息流。

比较

比较策略通过比较多个同步或复制元素产生的输出,使系统能够检测到不安全状态。因此,比较策略通常与冗余策略协同工作,典型的是在可用性讨论中提到的主动冗余策略。当复制元素数量为三个或更多时,比较策略不仅能检测到不安全状态,还能指出是哪个组件导致了该状态。比较与可用性中使用的表决策略相关。然而,比较并不总是会导致表决;另一种选择是如果输出不同则直接关闭系统。

遏制

遏制策略旨在限制已进入的不安全状态所带来的危害。这一类别包括三个子类别:冗余、限制后果和屏障。

冗余

乍一看,冗余策略似乎与可用性讨论中提到的各种备用 / 冗余策略类似。显然,这些策略存在重叠,但由于安全性和可用性的目标不同,备份组件的使用方式也有所差异。在安全领域,冗余使系统在不希望完全关闭或进一步降级的情况下能够继续运行。

复制是最简单的冗余策略,它仅仅涉及拥有组件的克隆体。拥有多个相同组件的副本对于防范硬件随机故障可能是有效的,但它无法防范硬件或软件中的设计或实现错误,因为此策略中没有任何形式的多样性。

相比之下,功能冗余旨在通过实现设计多样性来解决硬件或软件组件中的共模失效问题(即由于副本具有相同的实现,它们会同时出现相同的故障)。此策略试图通过在冗余中增加多样性来应对设计故障的系统性。在相同输入的情况下,功能冗余组件的输出应该相同。然而,功能冗余策略仍然容易受到规范错误的影响,当然,开发和验证功能副本的成本会更高。

最后,解析冗余策略不仅允许组件具有多样性,还允许在输入和输出级别体现更高级别的多样性。因此,它可以通过使用单独的需求规范来容忍规范错误。解析冗余通常涉及将系统划分为高保证和高性能(低保证)部分。高保证部分被设计得简单且可靠,而高性能部分通常被设计得更复杂、更精确,但稳定性较差:它变化更快,可能不如高保证部分可靠。(因此,这里所说的高性能并非指延迟或吞吐量方面的高性能;而是指这部分比高保证部分 “更好地执行” 其任务。)

限制后果

遏制策略的第二个子类别称为限制后果。这些策略旨在限制系统进入不安全状态可能产生的不良影响。

在概念上,中止策略最为简单。如果确定某项操作不安全,则在其造成损害之前将其中止。这种技术被广泛应用以确保系统安全地发生故障。

降级策略在组件发生故障时维持最关键的系统功能,以可控的方式放弃或替换部分功能。这种方法允许单个组件失效以一种有计划、慎重且安全的方式适度降低系统功能,而不是导致系统完全瘫痪。例如,汽车导航系统在失去 GPS 卫星信号的长隧道中,可能会继续使用(不太精确的)航位推算算法运行。

屏蔽策略通过比较多个冗余组件的结果,并在一个或多个组件结果不同时采用表决程序来屏蔽故障。为使此策略按预期工作,表决器必须简单且高度可靠。

屏障

屏障策略通过阻止问题传播来控制问题。

防火墙策略是限制访问策略的一种具体实现,这在 第 11 章 中有描述。防火墙限制对特定资源(通常是处理器、内存和网络连接)的访问。

联锁策略防范因事件顺序不正确而产生的故障。此策略的实现通过控制对受保护组件的所有访问,包括控制影响这些组件的事件的正确顺序,来提供精细的保护方案。

恢复

最后一类安全策略是恢复,其作用是使系统进入安全状态。它包括三个策略:回滚、修复状态和重新配置。

回滚策略允许系统在检测到故障时恢复到先前已知良好状态的保存副本 —— 回滚线。此策略通常与检查点和事务相结合,以确保回滚完整且一致。一旦达到良好状态,执行可以继续,可能会采用重试或降级等其他策略,以确保故障不再发生。

修复状态策略修复错误状态 —— 有效地增加组件能够正确处理(即无故障)的状态集 —— 然后继续执行。例如,车辆的车道保持辅助功能会监测驾驶员是否保持在车道内,如果车辆偏离,会主动将其恢复到车道线之间的位置 —— 安全状态。此策略不适合作为从意外故障中恢复的方法。

重新配置试图通过将逻辑架构重新映射到(可能有限的)仍在运行的资源上,从组件故障中恢复。理想情况下,这种重新映射可维持全部功能。当无法做到这一点时,系统可以结合降级策略维持部分功能。

10.3 基于策略的安全性调查问卷

基于 10.2 节 中描述的策略,我们可以设计一系列受这些策略启发的问题,如 表 10.2 所示。为全面了解为保障安全性而做出的架构选择,分析师需提出每个问题,并将答案记录在表格中。这些问题的答案随后可作为进一步工作的重点,如研究文档、分析代码或其他工件、对代码进行逆向工程等。

表10.2 基于策略的安全性调查问卷

策略组 策略问题 支持与否(是/否) 风险 设计决策和定位 推理和假设
避免不安全状态 是否采用替换策略,即为潜在危险的软件设计特性采用更安全的、通常基于硬件的保护机制?        
  是否使用预测模型,基于所监测的信息,对系统进程、资源或其他属性的健康状态进行预测,以便不仅能确保系统在其标称运行参数范围内运行,还能对潜在问题发出早期预警?        
检测不安全状态 是否使用超时机制来判断组件的运行是否满足其时间约束条件?        
  是否使用时间戳来检测事件的错误顺序?        
  是否采用状态监测来检查流程或设备中的状况,尤其是验证设计过程中所做的假设?        
  是否采用合理性检查来检验特定操作结果,或组件的输入与输出的有效性或合理性?        
  系统是否通过比较基于多个同步或复制元素产生的输出,采用比较方法来检测不安全状态?        
遏制:冗余 是否使用复制(即组件的克隆体)来防范硬件的随机故障?        
  是否使用功能冗余,通过实现设计多样的组件来应对共模故障?        
  是否使用解析冗余(即包含高保证/高性能和低保证/低性能选项的功能 “副本”)来容忍规范错误?        
遏制:限制后果 系统能否在确定某项操作不安全时,在其造成损害之前将其中止        
  系统是否提供可控的降级功能,即在组件发生故障时维持最关键的系统功能,同时放弃或降低不太关键的功能?        
  系统是否通过比较多个冗余组件的结果来屏蔽故障,并在一个或多个组件结果不同时采用表决程序?        
遏制:屏障 系统是否支持通过防火墙限制对关键资源(如处理器、内存和网络连接)的访问?        
  系统是否通过联锁装置来控制对受保护组件的访问,并防范因事件顺序错误而引发的故障?        
恢复 系统在检测到故障时,是否能够回滚,即恢复到先前已知的良好状态?        
  系统能否修复被判定为错误的状态,在不出现故障的情况下继续执行?        
  系统在发生失效时,能否通过将逻辑架构重新映射到仍在运行的资源上,对资源进行重新配置        

在开始基于策略的安全调查问卷之前,你应评估所审查的项目是否已进行危害分析或故障树分析,以确定在你的系统中,哪些情况构成不安全状态(需检测、避免、控制或从中恢复)。若未进行此分析,安全设计可能效果欠佳。

10.4 安全性模式

一个系统若意外停止运行、开始错误运行或进入降级运行模式,即便不会造成灾难性后果,也很可能对安全性产生负面影响。因此,寻找安全性模式首先可着眼于可用性模式,比如在 第 4 章 中描述的那些模式。它们在此处同样适用。

  • 冗余传感器:如果某个传感器产生的数据对于判断一种状态是否安全至关重要,那么该传感器应设置为冗余配置。这能防止单个传感器出现故障。此外,应使用独立的软件监控每个传感器 —— 本质上,这就是将 第 4 章 中的冗余备用策略应用于安全关键型硬件。

    优点

  • 这种应用于传感器的冗余形式可防范单个传感器故障。

权衡:

  • 冗余传感器会增加系统成本,而且处理多个传感器的输入比处理单个传感器的输入更为复杂。

  • 监控 - 执行器:此模式聚焦于两个软件元素 —— 一个监控器和一个执行器控制器,在向物理执行器发送命令之前使用它们。执行器控制器进行必要的计算,以确定要发送给物理执行器的值。监控器在发送这些值之前会检查其合理性。这将值的计算与值的测试分离开来。

    优点

  • 在这种应用于执行器控制的冗余形式中,监控器对执行器控制器的计算起到冗余检查的作用。

    权衡:

    • 开发和维护监控器需要耗费时间和资源。
    • 由于该模式实现了执行器控制与监控的分离,通过根据需要使监控器尽可能简单(易于开发,但可能会遗漏错误)或尽可能复杂(更复杂,但能捕获更多错误),这种特定的权衡很容易进行调整。
  • 安全分离:安全关键型系统通常必须由某个权威机构认证为安全。认证一个大型系统成本高昂,但将系统划分为安全关键部分和非安全关键部分可降低这些成本。安全关键部分仍必须经过认证。同样,对系统进行安全关键和非关键部分的划分也必须经过认证,以确保非安全关键部分不会对安全关键部分产生影响。

    优点

    • 由于只需认证整个系统的(通常较小的)一部分,系统认证成本得以降低。
    • 由于工作重点仅放在与安全密切相关的系统部分,成本和安全方面都能受益。

    权衡:

    • 进行分离所涉及的工作可能成本高昂,例如在系统中安装两个不同的网络,以区分安全关键和非安全关键消息。然而,这种方法限制了非安全关键部分中的错误影响安全关键部分的风险和后果。
    • 将系统分离,并说服认证机构相信分离操作正确执行,且非安全关键部分对安全关键部分没有影响,这具有一定难度,但远比另一种选择容易得多:让认证机构对所有内容都按照相同的严格标准进行认证。

设计保证等级

安全分离模式强调将软件系统划分为安全关键部分和非安全关键部分。在航空电子领域,这种区分更为细致。DO - 178C《机载系统和设备认证中的软件考量》是美国联邦航空管理局(FAA)、欧盟航空安全局(EASA)以及加拿大运输部等认证机构批准所有基于商业软件的航空航天系统时所依据的主要文件。它为每个软件功能定义了一种名为设计保证等级(DAL)的分级。DAL 是通过安全评估流程和危害分析,研究系统中故障状况的影响来确定的。故障状况根据其对飞机、机组人员和乘客的影响进行分类:

  • A 级:灾难性的。失效可能导致人员死亡,通常伴随着飞机失事。
  • B 级:危险性的。失效对安全性或性能有重大负面影响,或因身体不适或更高的工作负荷降低机组人员操作飞机的能力,或导致乘客严重受伤甚至死亡。
  • C 级:重大的。失效显著降低安全裕度或显著增加机组人员工作负荷,并可能导致乘客不适(甚至轻微受伤)。
  • D 级:较小的。失效略微降低安全裕度或略微增加机组人员工作负荷。例如,可能会给乘客带来不便或导致常规飞行计划变更。
  • E 级:无影响。失效对安全、飞机运行或机组人员工作负荷无影响。

软件验证和测试是一项成本极高的任务,而预算非常有限。DAL 有助于确定将有限的测试资源投入到何处。下次你乘坐商业航班时,如果你看到娱乐系统出现故障,或者阅读灯一直闪烁,不妨想想为确保飞行控制系统正常运行所投入的大量验证资金,这样心里会好受些。

—PC

10.5 扩展阅读

为了认识到软件安全的重要性,我们建议阅读一些因软件故障引发的灾难故事。一个不错的信息来源是 ACM 风险论坛,网址为risks.org 。自 1985 年起,该论坛由彼得・诺伊曼(Peter Neumann)主持,至今依然活跃。

有两个著名的标准安全 流程 ,分别在以下文件中有所描述:由国际自动机工程师学会(SAE International)制定的 ARP - 4761《民用机载系统和设备安全评估流程指南与方法》,以及由美国国防部制定的 MIL STD 882E《标准实践:系统安全》。

2004 年,吴(Wu)和凯利(Kelly)[Wu 04] 基于对现有架构方法的调研,发布了一系列安全策略,这为本章的诸多思考带来了启发。

南希・莱夫森(Nancy Leveson)是软件与安全领域的思想领袖。如果你从事安全关键系统方面的工作,就应该熟悉她的研究成果。你可以先从类似 [Leveson 04] 这样的论文入手,该论文探讨了一些导致航天器事故的软件相关因素。或者你也可以直接研读她的著作 [Leveson 11],这本书探讨了在当今复杂的、社会技术融合且软件密集型系统背景下的安全问题。

美国联邦航空管理局(Federal Aviation Administration)是负责监管美国空域系统的政府机构,极其重视安全问题。其 2019 年版的《系统安全手册》很好地对该主题进行了实用性概述。这本手册的 第 10 章 涉及软件安全内容。可以从http://faa.gov/regulations_policies/handbooks_manuals/aviation/risk_management/ss_handbook/下载。

菲尔・库普曼(Phil Koopman)在汽车安全领域颇负盛名。他有几个在线教程涉及安全关键模式。例如,可以查看http://youtube.com/watch?v=JA5wdyOjoXg和http://youtube.com/watch?v=4Tdh3jq6W4Y 。库普曼所著的《更好的嵌入式系统软件》[Koopman 10] 对安全模式有更详细的阐述。

故障树分析起源于 20 世纪 60 年代初,其经典参考资料是美国核管理委员会 1981 年发布的《故障树手册》。美国国家航空航天局(NASA)2002 年发布的《航空航天应用故障树手册》是对核管理委员会那本手册的更新版综合入门指南。这两本手册都可在网上以 PDF 格式下载。

与设计保证等级类似,安全完整性等级(SILs)对各类功能的安全关键程度给出了定义。这些定义不仅有助于参与系统设计的架构师达成共识,还能辅助安全评估工作。国际电工委员会(IEC)61508 标准《电气 / 电子 / 可编程电子安全相关系统的功能安全》定义了四个安全完整性等级,其中 SIL 4 可靠性最高,SIL 1 可靠性最低。该标准通过特定领域的标准得以具体应用,比如铁路行业的 IEC 62279 标准《铁路应用:通信、信号和处理系统:铁路控制与保护系统软件》。

在半自动驾驶和自动驾驶汽车成为大量研发主题的当下,功能安全正变得愈发重要。长期以来,ISO 26262 一直是道路车辆功能安全方面的标准。此外,也涌现出一批新规范,如 ANSI/UL 4600《自动驾驶汽车及其他产品评估的安全标准》,该标准旨在应对软件在实际和象征意义上 “掌控方向盘” 时所出现的各种挑战。

10.6 问题讨论

1. 列出目前你日常生活中使用的 10 种计算机控制设备,并设想恶意或出现故障的系统可能会如何利用它们来伤害你。

2. 编写一个安全场景,旨在防止静止的机器人设备(如生产线上的装配臂)伤人,并讨论实现该场景的策略。

3. 美国海军的 F/A - 18 “大黄蜂” 战斗机是早期应用电传飞控技术的机型之一,机上计算机根据飞行员对操纵杆和方向舵踏板的输入,向控制面(副翼、方向舵等)发送数字指令。飞行控制软件经过编程,可防止飞行员做出某些可能导致飞机进入不安全飞行状态的剧烈机动动作。在早期飞行测试中,常常需要将飞机推向(甚至超越)其极限状态,有一次一架飞机进入了不安全状态,而此时恰恰需要 “剧烈机动动作” 来挽救飞机,但计算机却尽职地阻止了这些操作。最终,这架飞机因旨在保障其安全的软件而坠入大海。编写一个安全场景来解决这种情况,并讨论本可避免这种结果的策略。

4.slate.com及其他消息来源报道,德国一名少女 “因忘记将 Facebook 生日邀请设为私密,意外地向全网发出邀请,随后便躲了起来。在 15000 人确认会参加后,女孩的父母取消了派对,通知了警方,并雇佣私人安保人员守护家门。” 然而,仍有 1500 人到场,导致数人受轻伤,现场一片混乱。Facebook 不安全吗?请讨论。

5. 编写一个安全场景,保护这位德国不幸少女免受 Facebook 类似事件的困扰。

6. 1991 年 2 月 25 日,海湾战争期间,一套美国 “爱国者” 导弹系统未能拦截一枚来袭的 “飞毛腿” 导弹,该导弹击中了一座兵营,造成 28 名士兵死亡,数十人受伤。失效原因是由于软件中的算术误差,随着时间推移积累导致对系统启动后时间的计算不准确。编写一个安全场景来解决 “爱国者” 导弹的失效问题,并讨论可能避免该失效的策略。

7. 作家詹姆斯・格雷克(James Gleick)在《一个漏洞与一次坠毁》(“A Bug and a Crash,” http://around.com/ariane.html)中写道:“欧洲航天局花了 10 年时间和 70 亿美元打造出阿丽亚娜 5 型火箭,这是一种巨型火箭,每次发射都能将两颗重达三吨的卫星送入轨道…… 而在其首次航行不到一分钟后,导致火箭爆炸的…… 仅仅是一个小计算机程序试图将一个 64 位数字塞进一个 16 位空间。一个漏洞,一次坠毁。在计算机科学史上记载的所有粗心代码行中,这一行可能堪称破坏力最强的。” 编写一个安全场景来解决阿丽亚娜 5 型火箭的灾难问题,并讨论可能避免该灾难的策略。

8. 讨论你认为安全性通常是如何与性能、可用性和互操作性等质量属性进行 “权衡” 的。

9. 讨论安全性与可测试性之间的关系。

10. 安全性和可修改性之间有什么关系?

11. 结合法航 447 航班的事件,讨论安全性与可用性之间的关系。

12. 为自动取款机创建一份故障列表或故障树。其中应包括硬件组件故障、通信故障、软件故障、耗材用尽、用户错误和安全攻击等方面的故障。你将如何运用策略来应对这些故障?