RFC-0099:推出「zx_socket_set_disposition」

RFC-0099:引入 `zx_socket_set_disposition`
狀態已接受
區域
  • 核心
說明

引入 `zx_socket_set_disposition`,以可逆轉的作業取代 `zx_socket_shutdown`。

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

摘要

引入 zx_socket_set_disposition 取代 zx_socket_shutdown。新的系統呼叫可透過允許關機作業反轉,擴充舊的系統呼叫。

引入 ZX_RIGHT_MANAGE_SOCKET,並在新的系統呼叫中要求使用 ZX_RIGHT_MANAGE_SOCKET。透過 zx_socket_create 新建的句柄就會擁有這項權限。

提振精神

以可逆轉的作業取代關機功能的原因

我們在 fdio 中使用精細的狀態機器,以因應未連線的串流網路通訊埠不應接受寫入作業的事實。狀態機具有本機狀態,這類狀態很難傳播至其他程序中的重複套接字,而遠端狀態 (zircon 套接字上的使用者信號) 則用於驅動本機狀態。這些動作是必要的,因為 Socket 會以「開啟」狀態建立,因此必須透過外部方式防止 I/O 作業,直到 Socket 變成「已連線」狀態 (也是透過外部方式) 為止。

要求新權限的動機

Zircon 套接字關閉功能目前過於寬鬆。由於 Zircon 通訊端句柄可複製 (實際上也是如此),因此具有寫入權限的單一句柄可變更所有句柄的通訊端狀態。允許根據這裡的建議,讓關機動作倒轉,會使這個問題更加嚴重。

將所有內容整合在一起

將 Socket 關閉作業替換為可逆轉的作業,同時禁止未經授權的句柄啟動該作業,可讓網路堆疊實作完全驅動 Socket 狀態。

在將 Socket 販售給用戶端之前,可以先將其關閉,這樣就不必在 fdio 中進行上述狀態追蹤。

網路堆疊可透過用戶端 Fidl 呼叫完全調解 Socket 關閉作業,消除目前存在的競爭條件 (例如 https://fxbug.dev/42140031)。

設計

FIDL 中定義 ZX_RIGHT_MANAGE_SOCKET

延長 bits rights

library zx;

bits rights : uint32 {
  MANAGE_SOCKET = 0x00100000;
};

rights.md 中的文件 ZX_RIGHT_MANAGE_SOCKET

附加到資料表:

授予特權
ZX_RIGHT_MANAGE_SOCKET 允許透過 zx_socket_set_disposition 變更 Socket 配置

FIDL 中定義 zx_socket_set_disposition

新增至 protocol socket

library zx;

protocol socket {
  /// Set disposition of writes.
  socket_set_disposition(handle:<SOCKET, rights.MANAGE_SOCKET> handle, uint32 disposition, uint32 disposition_peer) -> (status status);
}

/reference/syscalls/socket_set_disposition.md 中的文件 zx_socket_set_disposition

說明

zx_socket_set_disposition 會為通訊端程式和其對等端設定 zx_socket_write 呼叫的處置方式。

可用的有效配置旗標:

ZX_SOCKET_DISPOSITION_WRITE_DISABLED:停用指定的 Socket 端點的寫入作業。設定後,寫入指定的通訊端點會失敗,並顯示 ZX_ERR_BAD_STATE。從指定的通訊端點讀取資料會成功,直到指定的通訊端點中緩衝的所有資料都已用盡為止,之後會失敗並顯示 ZX_ERR_BAD_STATE

ZX_SOCKET_DISPOSITION_WRITE_ENABLED:為指定的 Sockets 端點啟用寫入功能。設定完成後,寫入和讀取指定的套接字端點的行為,分別會如 zx_socket_writezx_socket_read 所述。

在具有緩衝資料的 Socket 端點上指定 ZX_SOCKET_DISPOSITION_WRITE_ENABLED 無效;這樣做會導致 zx_socket_set_disposition 傳回 ZX_ERR_BAD_STATE,且不會採取任何動作。

dispositiondisposition_peer 中同時指定 ZX_SOCKET_DISPOSITION_WRITE_DISABLEDZX_SOCKET_DISPOSITION_WRITE_ENABLED 是無效的做法;這樣做會導致 zx_socket_set_disposition 傳回 ZX_ERR_INVALID_ARGS,且不會採取任何行動。

傳回值

zx_socket_set_disposition() 在成功時會傳回 ZX_OK

錯誤

ZX_ERR_BAD_HANDLE handle 不是有效的句柄。

ZX_ERR_BAD_STATE dispositiondisposition_peer 包含 ZX_SOCKET_DISPOSITION_WRITE_ENABLED,而 handle 則是指在指定的通訊端點上具有緩衝資料的通訊端。

ZX_ERR_WRONG_TYPE handle 不是 Socket handle。

ZX_ERR_ACCESS_DENIED handle 沒有 ZX_RIGHT_MANAGE_SOCKET

ZX_ERR_INVALID_ARGS dispositiondisposition_peer 包含上述以外的標記,或無效的標記組合。

遷移

實作後,zx_socket_shutdown 的現有用法將會替換為對 zx_socket_set_disposition 的等效呼叫。必要的 ABI 轉換完成後,系統就會移除 zx_socket_shutdown 及其相關選項。

實作

實作應完全在 Socket 調度器中執行。

成效

這項變更對效能沒有重大影響。

人體工學

這項變更對人體工學沒有重大影響。

回溯相容性

這項變更具有回溯相容性,因為未使用新 API 途徑的用戶端不會受到影響。

安全性考量

這項變更可讓 fdio 程式碼更簡單,進而提升安全性。這項變更對安全性沒有重大影響。

隱私權注意事項

這項變更對隱私權沒有重大影響。

測試

這項功能將透過以下方式進行測試:使用系統呼叫的單元測試,以及將已測試的 fdio 狀態機器部分替換為新機制。

說明文件

zx_socket_writezx_socket_read 會更新為參照 zx_socket_set_disposition,而非 zx_socket_shutdown

其他說明文件會按照實作部分的說明進行更新。

缺點、替代方案和未知因素

除了新的系統呼叫外,您也可以在 zx_socket_shutdown 中新增標記,讓系統呼叫的行為能夠反轉。這種做法的好處是避免引入與行為不相符的新字詞 (意向)。繼續使用 zx_socket_shutdown 的主要缺點是,它接受的標記不夠直觀;ZX_SOCKET_SHUTDOWN_READ 不會執行說明中的動作 (它會禁止對等寫入,而非禁止讀取)。

如果在套接字的指定方向中存在資料,則會指定「unshutdown」的行為為產生錯誤。另一個選擇是允許該作業成功執行;我們選擇更嚴格的選項,以免發生非預期的後果。

您可以使用現有權利,而不需要建立新的權利。對現有權利的調查顯示,沒有任何現有權利與此使用情形相符。

這項設計本身並無法完全解決串流通訊端的狀態傳播問題。這個提案的替代方案是更全面的方法,可盡力完全淘汰 fdio 串流通訊埠狀態機器。這類提案也必須納入這項提案。

既有技術與參考資料

實際上,流程式通訊端的語意是由其他作業系統中的行為定義,因此需要區分已連線和未連線的通訊端。