LWN:GPSD 中的时间溢出!

关注了就能看到更多这么棒的文章哦~

A GPSD time warp

By Jake Edge
August 4, 2021
DeepL assisted translation
https://lwn.net/Articles/865044/

GPSD project,提供了一个跟 GPS 设备进行通信的 daemon 程序,用来获取这些传感器提供的位置信息。但是 GPS 卫星本身也提供了高精度的时间信息,GPSD 可以同时提取这些信息来供网络时间协议(NTP,Network Timer Protocol)服务使用。不过,GPSD 代码中的一个 bug 会导致 10 月份的时候出现时间倒退,如果受影响的 NTP 服务在那之前没有及时更新的话很可能会面临破坏。

可以说问题的根本原因是 GPS week-number 的滚动实现,因为在最初的 GPS 协议中,只有 10 个比特用于表示 week number。10 个 bit 的话,在数到 1023 后就会溢出,所以只能表示 19.6 年左右。由于 GPS 的时间纪元(epoch)是从 1980 年初开始的,所以已经发生了两次翻转(rollover)事件(分别在 1999 年和 2019 年)。在 2038 年之前不应该再有了,但是 GPSD 的一些合理性检查代码中的一个 bug 将导致在 2021 年 10 月 24 日的时候会从 week number 中减去 1024。这样一来就会变回到 2002 年 3 月了,谁都不希望看到这个结果。

这个问题是由 Stephen Williams 在 7 月 21 日报告出来的。它对 GPSD 的 3.20-3.22 版本都有影响,也就是从 2019 年最后一天开始到现在的所有版本。即将发布的 3.23 版本(最早会在 8 月 4 日发布)将会 fix 这个问题,但人们需要把所有相关的服务器上的 GPSD 都更新到这个版本。有人担心如果 NTP 服务器管理员没有收到这个消息的话,很可能会在十月份的时候碰到这件倒霉事。

bug report 中贴出了相关的代码。在 gpsd_gpstime_resolv() 函数中使用了一个错误的常量值:

/* sanity check week number, GPS epoch, against leap seconds
 * Does not work well with regressions because the leap_sconds
 * could be from the receiver, or from BUILD_LEAPSECONDS. */
if (0 < session->context->leap_seconds &&
    19 > session->context->leap_seconds &&
    2180 < week) {
    /* assume leap second = 19 by 31 Dec 2022
     * so week > 2180 is way in the future, do not allow it */
    week -= 1024;
    GPSD_LOG(LOG_WARN, &session->context->errout,
             "GPS week confusion. Adjusted week %u for leap %d\n",
             week, session->context->leap_seconds);
}

这段代码可能有点难读懂,因为比较的顺序与通常的写法相反。也许这是 Yoda notation 写法,不过这种写法一般也不会用来进行这些大于、小于的比较。其他地方计算出来的 week number 都考虑到了 rollover 问题,跟 2180 进行了比较,不过这并不是 comment 里面所说的 "way in the future" (很久之后),而是实际上对应于 10 月 24 日。这个检查显然是为了避免出现一些虚假的 regression,正如 comment 里第一句所说。

GPSD 的维护者 Gary E. Miller 承认了这个问题,他说他本想使用 2022 年 12 月 31 日的 week number,但在计算时出现了错误,算成了 2180。这部分代码事实上还 "预测 " 在 2022 年底会增加一个闰秒,但是,正如 Williams 指出的,这个预测并不正确。此外,其实不久之后会出现负闰秒(negative leap second),但写代码的时候并没有考虑到这一点。

Miller 说,直到 2020 年为止,"闰秒一直是可以可靠预测的",但最近发现地球旋转速度增加,因此这一点出现了变化,也增加了出现负闰秒的可能性。然而,大家谈论的代码是针对 regression test,而不是实时处理 GPS 数据的代码,这是问题的另一部分。

7 月 24 日,Miller 提交了一个 fix,从 live path 中删除了错误判断条件。但是这个 fix 只出现在 3.23 版本中,不会被 backport 到以前的版本中,至少 GPSD project 的规矩是这样。虽然各大发行版可能会做这件事,但他并不相信这样足以让事情变好:

gpsd 没有足够的志愿者来维护 "多个 branch"。一些发行版试图 cherry-pick 一些 patch,但通常会使事情变得更糟。

这个 bug 已经在 gpsd-dev 和 gpsd-users 的邮件列表中公布过了。所以几个发行版的打包发布人员已经看到了。他们做什么我们就无法控制了。

3.23 版将在一周内发布。

[…] 发行版不接受 gpsd 的 update 版本,也不把他们的改动推送回 upstream 上,这是我感到非常不爽的一个问题。

Williams 在他正在维护的 GPSD 3.19 的 branch 中发现了这个错误。针对 3.20 进行的一些修改被 backport 到该分支中,然后他对代码进行测试的时候发现了这个问题。但 Miller 认为,发行版和其他人都应该运行最新版本,而且当 3.23 一旦可用,他们就应该升级到 3.23,因为每个新版本都修复了一些与安全有关的错误。当然,这与其他项目的立场有些类似,比如 Linux 内核项目,Miller 指出:"我[要]赞同 Greg K_H 的口号:所有用户必须更新。"

会议还讨论了负闰秒的问题。Williams 说,在合入了 Miller 的 fix 后,不再存在之前那种问题了,而且哪怕是之前那些有问题的代码,碰到负闰秒也不会有什么大的影响。他只是碰巧注意到这个有问题的代码没有预计到负闰秒的可能性。目前还没有人发现如果负闰秒时会有什么问题,不过确实可以做更多的测试来确认。

正如 Miller 所说,GPS 协议的设计者比较短视地 "植入" 了一个仅有 20 年的 rollover 周期。Miller 的说法是:"从设计上就决定了 GPS 每隔 1024 个星期就会发生一次 rollover"。最近出现的 CNAV 协议(目前尚未部署到所有 GPS 卫星上)将 week number 升级到了 13 位,这就会给我们一个 157 年的重复周期,看起来更加安全一点,尽管第一次溢出也会在 116 年后的 2137 年发生。到那时,很可能会有其他的导航技术(和时间技术),或者在某个地方再挤进几个 bit。

如果希望在 10 月中旬以后仍然能够依靠 GPSD 获得准确时间的话,就需要运行没有这个 bug 的版本。在电影中,时间倒流很有趣,但对于在互联网上分配时间的系统来说可就不那么有趣了。使用 GPSD 的 NTP 服务的话就必须升级,或者至少避免使用 3.20-3.22 期间的版本。

[感谢 David A. Wheeler 为我们介绍了这个问题。]

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值