RFC-0170:從更新套件中移除二進位映像檔

RFC-0170:從更新套件中移除二進位圖片
狀態已接受
區域
  • 軟體推送
說明

在 OTA 期間重新排序圖像寫入作業,以節省空間。

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-05-12
審查日期 (年-月-日)2022-06-22

摘要

為釋出系統空間,我們必須分割更新套件。在至少一個空間受限的產品上,我們可節省約 14 MiB。這項變更相當複雜,需要透過中繼版本才能完成。根據 RFC 103 的規定,所有踏板版本都需要有專屬的 RFC。本 RFC 將詳細說明新的更新套件格式。

提振精神

無線更新 (OTA) 是升級執行中裝置上的 Fuchsia 版本的機制。如果有可用的更新,系統更新器會擷取更新套件。擷取套件代表套件內容會寫入 BlobFS,並受到保護,不會遭到垃圾收集。更新套件包含在 Zircon 分區中保留空間的映像檔 (例如復原映像檔和 Zircon 開機映像檔),以及要下載的其他套件清單,以便完成更新。

目前,Fuchsia 裝置必須為每張圖片儲存兩個副本:

  1. 在目的地分區 (例如 ZIRCON_A) 中,裝置在執行階段使用的一個副本。
  2. blobfs 中的一個副本,因為圖片會以更新套件中的 blob 形式提供給裝置。

透過保護圖片免於遭到垃圾收集,更新作業可確保在中斷時仍能繼續進行。前進進度是保證更新系統的極為重要屬性。不過,在空間受限的產品上,將映像檔寫入磁碟區隔和 BlobFS 並非最佳預算。

映像檔寫入作業是 OTA 程序中的倒數第二個步驟,之後會切換哪個分割區為有效分割區,並重新啟動至新的系統映像檔。在下次更新之前,核心、韌體和復原映像檔都會受到保護,不會遭到垃圾收集和刪除。透過在 OTA 期間重新排序圖片寫入作業,我們可以在下載 OTA 中的大部分套件之前,從 BlobFS 收集圖片,並回收空間預算,供其他套件使用。變更 SWD 設計以移除圖片的重複副本,可能可節省大量空間,這對某些 Fuchsia 裝置來說是相當寶貴的資源。

為了在 OTA 期間進行二進位映像檔垃圾收集,同時確保向前進展,我們需要變更更新套件的格式。

相關人員

導師:hjfreyer@google.com

審查者:

  • 軟體推送:wittrock@google.com、jsankey@google.com
  • MOS:gtsai@google.com
  • 安全性:ampearce@google.com
  • 產品組裝:awolter@google.com
  • 發布者:billstevenson@google.com

設計

目前,更新套件是套件,也包含擷取的圖片,並在擷取更新套件時將圖片寫入 blobfs。

我們建議您將圖片從更新套件中提取,並將每張圖片放入各自的套件中。

這與我們目前的 OTA 程序和套件格式完全相符,但需要變更更新套件格式。

為了參照這些新套件,我們會在更新套件中加入名為 images.json 的檔案,其中包含描述圖片套件的中繼資料。該檔案的範例如下:


{
  "version": "1",
  "contents": {
    "partitions": [
      {
        "type": "zbi",
        "slot": "fuchsia",
        "size": 1,
        "hash": "0a",
        "url": "fuchsia-pkg://fuchsia.com/fuchsia-zbi/0?hash={merkle_hash}#path/to/fuchsia.zbi"
      },
      {
        "type": "vbmeta",
        "slot": "fuchsia",
        "size": 2,
        "hash": "0b",
        "url": "fuchsia-pkg://fuchsia.com/fuchsia-vbmeta/0?hash={merkle_hash}#path/to/fuchsia.vbmeta"
      },
      {
        "type": "zbi",
        "slot": "recovery",
        "size": 3,
        "hash": "0c",
        "url": "fuchsia-pkg://fuchsia.com/recovery-zbi/0?hash={merkle_hash}#path/to/recovery.zbi"
      },
      {
        "type": "vbmeta",
        "slot": "recovery",
        "size": 4,
        "hash": "0d",
        "url": "fuchsia-pkg://fuchsia.com/recovery-vbmeta/0?hash={merkle_hash}#path/to/recovery.vbmeta"
      }
    ],
    "firmware": [
      {
        "type": "",
        "size": 5,
        "hash": "0e",
        "url": "fuchsia-pkg://fuchsia.com/update-images-firmware/0?hash={merkle_hash}#path/to/firmware"
      },
      {
        "type": "bl2",
        "size": 6,
        "hash": "0e",
        "url": "fuchsia-pkg://fuchsia.com/update-images-firmware/0?hash={merkle_hash}#path/to/firmware"
      }
    ]
  }
}

版本屬性會定義如何解讀內容屬性。使用此 RFC 定義的格式時,版本一律必須是「1」,但現在引入版本屬性,可簡化日後可能需要的其他變更。這個模式已用於 SWD 堆疊的資訊清單中的其他位置,且能與 serde 完美整合。

系統更新程式會剖析資訊清單,判斷是否需要擷取圖片 (取決於是否已在適當的插槽中找到具有對應雜湊值的檔案)。系統會擷取每個已變更的映像檔,並將其寫入相應的分區,然後從 BlobFS 收集垃圾。如果 images.json 中沒有圖像,我們就不會覆寫 Zircon 分區中的內容。

系統會納入圖片的大小和雜湊值,用於驗證檢查。雜湊值是圖片檔案的 SHA256 雜湊值,以十六進位表示。由於分割區在不同裝置上會有所不同,我們也需要知道圖片的大小以利比較。網址包含梅克爾雜湊。Merkle 雜湊的運算方式較為複雜,因此我們選擇使用 SHA256 雜湊來加快比較速度。

我們建議的 OTA 程序如下:

  1. 下載更新套件
  2. 剖析含有更新圖片套件參照資料的新中繼資料檔案
  3. 針對該檔案中列出的每個映像檔,如果該映像檔與非活動分區中指定 Zircon 分區中的映像檔相同,請繼續。中繼資料檔案包含圖片的雜湊和大小 (因為圖片大小不等於分割區大小),我們可以快速比較非活動分割區的圖片雜湊。否則:
    1. 擷取含有圖片的套件,該套件會將圖片寫入 BlobFS,並處理完整性檢查。將套件新增至保留索引。
    2. 寫入分區。
    3. 從 BlobFS 進行垃圾收集 (從保留索引中移除套件),以便回收空間。
  4. 繼續下載更新套件中指定的其餘套件,並完成 OTA 更新。

變更更新套件的結構,可解決空間限制問題。將資料寫入 BlobFS 後,再進行垃圾收集,我們就能利用現有儲存空間架構提供的全面安全保證。

實作

如要對更新套件進行這項變更,我們必須進行三階段發布:第一階段處理目前更新套件的格式和新更新套件的格式超集合,第二階段只產生新格式,最後階段則停止處理舊版更新套件的處理邏輯。

在第一階段,系統會修改 system_updater,以便成功剖析原始更新套件格式,以及本 RFC 中提出的修改後格式。MOS 仍會使用原始格式產生更新套件。這項包含這項工作的版本會標示為墊腳石,確保所有 Fuchsia 裝置都能在收到使用新格式的更新套件前,收到可剖析新格式的 system_updater。

在第二階段,MOS 將開始使用本 RFC 提出的新格式產生更新套件。

在第三階段,一旦我們確信沒有任何裝置需要回溯至使用原始更新套件格式的版本,就會修改 system_updater,移除對原始更新套件格式的支援。

如果我們不分階段發布,則只能解讀目前版本更新套件的裝置,在收到更新的更新套件後會變成磚塊。我們需要將第一階段版本標示為「墊腳石」版本,確保所有裝置都會通過該版本。

更新套件的使用者必須瞭解分階段發布作業。已知使用者包括安全性、審查、MOS、產品組合和軟體提交。

成效

預計不會有重大變化。

我們需要對圖片進行雜湊運算並進行比較。在最佳情況下,雜湊會相符,我們就不需要花時間擷取或寫入雜湊。在所有圖片都變更的極端情況下,我們仍需要下載及寫入相同位元組數。

安全性考量

Scrutiny (我們的建構時安全分析工具) 會分析更新套件,從中擷取 ZBI。我們需要更新 Scrutiny 測試,以反映更新套件中 ZBI 的新位置。

圖片的完整性檢查不會改變。我們會繼續使用相同的方法擷取更新套件,而更新套件包含映像檔套件的雜湊,且當裝置重新啟動至新系統時,所有其他安全性屬性都會透過驗證啟動機制強制執行。

隱私權注意事項

這項 RFC 不會對圖片的建立或內容造成任何變更,只會影響圖片的傳送順序,因此不會影響隱私權。

測試

我們已經為更新套件和系統更新程式進行單元和端對端整合測試。我們需要擴充這些測試,涵蓋從目前的更新套件版本到中繼版本,以便進行第一個踏腳石版本。針對第二個版本,我們需要進行測試,以便同時處理更新套件中的中繼版本和新版更新套件。完成這項工作後,我們會移除中間測試,並測試使用舊版更新套件進行的降級無線更新作業一律會失敗。

說明文件

如果這項變更獲得核准,我們需要更新更新套件的說明文件OTA 說明文件

缺點、替代方案、未知

替代方案是完全不將圖片寫入 BlobFS 的設計。

最簡單的方法是直接將映像檔鋪到各個區段,從 blobfs 進行更新套件的垃圾收集,最後下載保留索引中的新套件 blob。這個替代方案實作簡單、可避免重複寫入,且不需要透過墊腳石版本。不過,我們無法保證後續進展。如果更新中斷,裝置可能會完全無法更新。

我們有另一個做法,就是將圖片保留在更新套件中,但將更新套件視為比現有更特殊的套件:我們可以完全避免將圖片儲存到 blobfs。這項設計可免除更新套件的格式變更需求,但需要大幅變更系統更新器邏輯,並將更新套件的處理方式與「一般」套件的處理方式分開。我們認為建議的設計只是重構更新套件,而非引入特殊處理邏輯。

既有技術

更新套件的設計先前已在 fuchsia.dev 上記錄