在 1976 年电影“马拉松人”中的一个悬疑场景中,一个虐待狂的纳粹牙医(劳伦斯·奥利维尔爵士)用他的各种工具摆出威胁性的姿势。谈到他来收集的一批被盗钻石,奥利维尔反复问他害怕的俘虏(达斯汀霍夫曼),“它安全吗?” 霍夫曼不知道这意味着什么,但他的无知远非幸福,因为他遭受了未经麻醉的后果。
作为现代软件的生产者,我们还需要面对这个问题,“它安全吗?” 不知道答案很容易导致灾难——即使它不会带来牙齿折磨。实际上,软件开发人员的问题不是“安全吗?” 而是,“它足够安全吗?” 安全不是布尔条件;这是一个连续统一体,反映了我们对系统的安全特性得到满足的信心。安全意味着安全,因为漏洞可以被利用来产生不可接受的危害。在最高的保证级别上,我们需要相应地高度确信我们的软件做了它应该做的事情,而不做它不应该做的事情。
软件安全和安保历来在电子产品领域受到不同程度的关注。对这些要求的高度重视显然与医疗器械相关;然而,有时会发生重大失误,造成伤害或死亡。在 1980 年代的 Therac-25 放射治疗机事件中,并发活动之间的“竞争条件”导致要进行大量放射治疗,几年前,胰岛素输液泵的软件缺陷也导致剂量不当,有时甚至是致命的剂量。
在更一般的小型电子产品领域中,软件的安全和安保要求是相当新的。以前,此类系统中的软件相对简单,设备通常是独立的,并且通过机械手段强制执行安全性。但如今,该软件执行的功能越来越复杂,连接到互联网的“智能”设备可以被远程控制。
本文重点介绍了软件开发人员需要面对的主要问题,重点关注DO-178C认证标准(机载系统和设备认证中的软件注意事项)作为一个行业方法的示例。DO-178C 中的指南并非专门针对航空,文章建议如何将其调整到需要高度保证的其他领域。
大图 图 1摘自 DO-178C 中的一个图,显示了 系统生命周期过程 与 软件和硬件生命周期过程之间的关系。关键要点是,必须在系统级别确定安全(以及隐含的安全)要求和责任,但要得到其他生命周期过程的反馈。每个软件组件都有一个相应的软件级别(也称为开发保证级别,或 DAL),基于该组件的异常行为对飞机持续安全运行的影响。正如Rick Hearn在 2016 年 10 月号 电子产品中关于 DO-254 的文章中所述,A 级是最苛刻的,因为异常行为可能会导致灾难性故障,从而导致飞机失事。
许多标准为执行系统生命周期过程提供了推荐做法,例如ARP 4754A和IEC 61508。危害和安全评估方法包括官方标准中提出的方法,例如ARP 4761。
可以在通用标准中找到安全功能和保证要求的目录。保证要求分为评估保证级别 (EAL),最高级别 (EAL 7) 要求对安全功能进行形式验证。更具体地说,一个国际工作组已经准备好 DO-326A(适航安全流程规范),以“增强当前的飞机认证指南,以处理故意未经授权的电子交互对飞机安全的威胁。” 此类系统级分析可作为 DO-178C 流程的输入,但反过来可能会受到 DO-178C 活动反馈的影响。
软件工程常识 DO-178C 面向飞机软件供应商,包含与各种软件生命周期过程相关的特定目标形式的指南。组件的 DAL 确定哪些目标是相关的、配置管理控制的严格性以及负责实现目标和验证目标是否已实现的各方是否需要独立。目标列在一组表格中,详细信息请参考文档正文;作为说明, 图 2 显示了表 A-5 中的目标 6。
系统提供商需要通过提供各种工件(“数据项”)来证明符合目标,这些工件将由国家机构认证机构授权的指定工程代表 (DER) 进行审查。在接受数据项后,系统被认为是经过认证的。
图 3 显示 DO-178C 的主要元素;即各种软件生命周期过程,包括规划、开发和几个相关的“整体”过程。这不是火箭科学。本质上,该标准是软件工程常识的实例化。任何软件都是针对一组需求设计和实现的,因此开发包括从系统需求中细化软件需求(高级和低级),并可能梳理出额外的(“派生的”)需求,指定软件架构,并实现设计。每个步骤都需要验证(其中一个不可或缺的过程)。例如,软件需求是否完整且一致?实施是否满足要求?验证涉及可追溯性:
补充实际开发过程的是各种外围活动。该软件不仅仅是代码、数据和文档的静态集合;它随着检测到的缺陷、客户变更请求等而发展。因此,完整的过程包括配置管理和质量保证,并且定义良好的程序至关重要。
DO-178C 不偏向或反对任何特定的软件开发方法。尽管它似乎面向新的开发工作,但可以采用现有系统并追溯执行相关活动以获取必要的数据项。该标准还处理诸如商业现货 (COTS) 组件的合并和使用服务历史来获得认证信用等问题。
软件验证 DO-178C 中的大部分指南都涉及验证:审查、分析和测试的组合,以证明每个软件生命周期过程的输出相对于其输入是正确的。在 A 级软件的 71 个总目标中,43 个适用于验证,其中一半以上涉及源代码和目标代码。出于这个原因,DO-178C 有时被称为“正确性”标准而不是安全标准;通过认证获得的主要保证是对软件满足其要求的信心。代码验证目标的重点是测试。
但是测试有一个众所周知的内在缺陷。正如已故计算机科学家 Edsger Dijkstra 所说,它可以显示 bug 的存在,但永远不会显示它们的缺失。DO-178C 通过多种方式缓解了这个问题:
• 通过检查和分析增强测试,以增加及早发现错误的可能性。
• DO-178C 要求进行基于需求的测试,而不是“白盒”或单元测试。每个需求都必须有相关的测试,执行正常处理和错误处理,以证明需求得到满足并且无效输入得到了正确处理。测试的重点是系统应该做什么,而不是每个模块的整体功能。
• 源代码必须完全被基于需求的测试所覆盖。不允许使用“死代码”(测试未执行且不符合要求的代码)。
• 代码覆盖目标适用于 DAL C 的语句级别。在更高的 DAL 中,需要更精细的粒度,在完整的布尔表达式(“决策”)及其原子成分(“条件”)级别也需要覆盖。DAL B 需要决策覆盖(测试需要同时验证真假结果)。DAL A 需要修改条件/决策覆盖。给定决策的一组测试必须满足以下条件 : o 对于决策中的每个条件,条件在某些测试中为真,在另一个测试中为假;和 o 每个条件都需要独立影响决策的结果。也就是说,对于每个条件,必须有两个测试,其中: 》 一个条件为真,另一个条件为假, 》 其他条件在两个测试中具有相同的值, 》 两个测试中的决定结果是不同的。
MC/DC 测试将检测某些类型的逻辑错误,这些错误不一定会出现在决策覆盖范围内,但如果在多条件决策中需要 True 和 False 的所有可能组合,则不会出现测试的指数爆炸式增长。它还具有强制开发人员制定明确的低级需求的好处,这些需求将适用于各种条件。
图 4 显示了与示例“if”语句的不同级别的源代码覆盖相关的可能测试用例集。
软件方法学 软件方法学 的进步为验证带来了机遇和挑战:
• 基于模型的开发以图形语言表达控制逻辑,自动生成源代码,可能与手动生成的代码混合。鉴于该计划的多种形式,尚不清楚哪些目标适用于哪种形式。
• 面向对象编程的主要特性——继承、多态性和动态绑定——引发了包括代码覆盖率和时间和空间可预测性在内的目标问题。
• 对于最高级别的安全关键性,应用形式化方法可以帮助提高保证(例如,证明没有运行时错误等安全属性)并消除对一些低级别需求测试的需要。但是,目前尚不清楚如何向认证机构证明正式证明可以取代此类测试。
这些问题是修订早期 DO-178B 标准的主要动力,它们在 DO-178C 的补充中得到了解决:
• DO-331用于基于模型的开发和验证, • DO-332用于面向对象技术和相关技术,以及 • DO-333用于形式方法。
工具鉴定 工具在软件生命周期中有一系列用途。一些辅助验证,例如检查源代码是否符合编码标准、计算最大堆栈使用量或检测对未初始化变量的引用。其他影响可执行代码,例如基于模型的设计的代码生成器。工具可以节省大量劳动力,但我们需要确信它们的输出是正确的;否则,我们将不得不手动验证输出。
使用 DO-178C,我们通过称为工具鉴定的过程获得了这种信心,这基本上证明了该工具满足其操作要求。所需的工作量——所谓的工具认证级别,或 TQL——取决于工具将要处理的软件的 DAL 以及在存在工具缺陷:
• 标准1:工具输出是机载软件的一部分,工具可能会插入错误。 • 标准2:该工具可能无法检测到错误,其输出用于减少其他开发或验证活动。 • 标准3:该工具可能无法检测到错误。
TQL 的重要性范围从 5(最低)到 1(最高)。TQL-1 适用于满足标准 1 的工具,用于 DAL A 的软件。大多数静态代码分析工具将采用 TQL-4 或 TQL-5。
辅助标准DO-330(工具鉴定注意事项)定义了与各种 TQL 相关的特定目标、活动和数据项。DO-330 可与其他软件标准结合使用;它不是特定于 DO-178C。
有什么问题? 尽管已经发生了一些危急关头,但迄今为止,还没有发现软件出现故障的商用飞机事故造成人员伤亡。所以 DO-178C(及其前身 DO-178B)似乎很有效。尽管如此,还是出现了一些问题。
正确是否意味着安全? 如上所述,DO-178C 确实是一个正确性标准,可以确保软件满足其要求。这如何转化为整体系统安全性以及由此产生的低故障概率?约翰·拉什比 ( John Rushby) 的一篇论文认为,机载系统的成功记录与其说归功于软件标准,不如说归功于该行业的企业安全文化以及技术相对不频繁的变化。其他行业使用 DO-178C 指南可能不会产生相同的好处。
软件正确性和系统安全之间的关系确实不是那么简单;许多因素会影响飞机或任何其他基于计算机的系统的整体安全(例如,也许最明显的是,操作员的培训和技能)。然而,即使代码正确性显然不足以实现安全,但在电传操纵等没有“B 计划”后备的情况下,这是必要的。即使暂时忽略安全问题,许多行业中的错误软件也可能导致代价高昂的召回,从而产生直接的财务成本并损害公司的声誉。底线:对代码正确性有信心的原则和实践值得遵循,因为它们可以帮助挽救生命和金钱。
认证过程是否不必要地繁重? 系统认证并不便宜。应将注意力集中在出现最严重问题的领域;即,在需求阶段而不是在编码级别。一个自然的问题是是否可以以更低的成本实现 DO-178C 的优势。系统供应商和美国国会都提出了这个成本与收益的问题,因为机载软件的安全认证过程被认为对新进入者来说过于复杂,但未能充分解决如何处理新方法和新技术。FAA 负责调查此问题的工作组举办了简化保证流程研讨会在 2016 年 9 月,他们提出了三个高级别的“总体属性”,这些属性可能构成更简单的认证方法的基础:
• 意图——定义的预期功能对于所需的系统行为是正确和完整的。 • 正确性——在可预见的操作条件下,就其定义的预期功能而言,实施是正确的。 • 必要性——所有实施要么是所定义的预期功能所要求的,要么没有不可接受的安全影响。
正在进行的这项工作可能会导致用于认证机载软件的替代框架。
经验教训 总之,DO-178C 中的指南主要用于提供软件满足其要求的信心——而不是验证要求实际上反映了系统的预期功能。因此,获得正确的代码是不够的,但这是必要的,而且 DO-178C 方法的许多好处可以在不经过正式认证的情况下实现。以下是一些建议:
• 注意整个软件生命周期。源代码版本控制和配置管理可能看起来并不性感,但它们是必不可少的。实施源签入“挂钩”(例如,调用静态分析工具来强制执行代码质量的某些方面)并定期安排完整的回归测试运行。实施处理缺陷报告和变更控制的流程,以便在不引入新问题的情况下提供软件更新。确保已知问题有解决方法。
• 审查 DO-178C 中的目标并决定要达到的目标。在没有官方认证的情况下,不需要提供各种数据项,但是如果故意遗漏某个目标,请确保您了解遗漏的原因以及不遵守可能造成的后果。
• 使用能够及早发现潜在问题的编程语言。如 DO-178C 第 4.4 节所述:
基本原则是选择限制引入错误机会的需求开发和设计方法、工具和编程语言,以及确保检测到引入的错误的验证方法。
Ada 编程语言特别适用 ,因为它旨在促进健全的软件工程实践,并强制执行检查以防止诸如“缓冲区溢出”和整数溢出等弱点。该语言的最新版本 Ada 2012 包括一个特别相关的功能,称为基于合同的编程,它有效地将低级软件需求嵌入到源代码中,可以在其中静态验证它们(使用适当的工具支持)或在运行时(使用编译器生成的检查)。
• 无论选择哪种语言,都要选择适合您应用程序需求的子集。C、C++、Ada 和 Java 等通用语言提供的特性在高保证上下文中可能存在问题。一个特性可能容易出错,它的语义可能没有完全指定,或者它可能需要复杂的运行时支持。选择并执行合适的子集(或 DO-178C 用语中的“软件代码标准”)。
例如,MISRA-C中的规则旨在解决 C 语言的各种有问题的特性。但是,某些 MISRA 规则是不可检查的(例如,文档要求),而其他规则可能会以不同的方式执行(例如,禁止悬空引用)。在 Ada 中,称为“pragma Restrictions”的标准功能允许程序员指定要禁止的功能。因此,相关子集可以按 点菜的 方式定义,几乎所有的限制都由编译时而不是运行时检查强制执行。Ada 语言标准还定义了一组对并发(任务)特性的特定限制,称为Ravenscar 配置文件。 Ravenscar 任务子集的表现力足以在实践中使用,但对于安全或安全认证系统来说足够简单。
• 考虑高保证应用的正式方法。基于形式化方法的静态分析工具可以证明程序属性(包括安全性和安全性),范围从不存在运行时错误到符合正式规定的要求。使用这些工具提供了基于数学的保证,同时也消除了对一些基于需求的低级测试的需要。
一个例子是Frama C技术,它可以证明 C 程序的属性,尽管在 C 中普遍使用指针是一个挑战。SPARK是 Ada 的一个形式上可分析的子集;诸如指针和异常等难以分析的特性不存在,证明技术可以利用 Ada 的基本特性,如强类型、标量范围和基于合约的编程。
• 使用合格的工具自动化手动流程。静态分析工具是你的朋友;除其他外,他们可以检查编码标准的合规性、计算复杂性指标,并检测潜在的错误或潜在漏洞(例如对未初始化变量的引用、缓冲区溢出、整数溢出以及在没有保护的情况下对共享变量的并发访问)。用于识别此类错误的 Ada 静态分析工具的一个示例是 AdaCore 的CodePeer. 要考虑的实用性包括可靠性(该工具是否检测到它正在寻找的所有错误实例?),“误报”率(报告的问题,实际上是真正的错误吗?)和可用性(例如可扩展性到大系统,无需完整代码库即可分析系统部分的能力,以及易于集成到组织的软件生命周期基础架构中)。
对于动态分析,代码覆盖工具在源和对象级别都是必不可少的。该领域的典型技术会在可执行文件中生成特殊的跟踪代码,但这意味着真正的可执行文件与派生覆盖数据的可执行文件不同。因此,需要额外的工作来证明为检测的可执行文件和实际的可执行文件获得的覆盖结果是等效的。另一种方法是非侵入式的,编译器与可执行文件分开生成源覆盖义务数据。使用从具有适当跟踪功能的目标板或仪表仿真环境生成的跟踪数据,覆盖工具可以识别和报告哪些源构造和目标代码指令已经执行或未执行。GNATcoverage,它可以导出高达 MC/DC 的覆盖率数据。
对于这些工具中的任何一个,资格证书都将提供更多的信心,并减少确认工具结果的额外工作的需要。
将 DO-178C 的原则应用到您的软件生命周期过程中可能无法将您从邪恶的“马拉松人”牙医中解救出来,但是当与系统级安全原则结合使用时,它将帮助您自信地回答“是”问:“安全吗?”
评论
查看更多