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_write
和 zx_socket_read
所述。
在具有緩衝資料的 Socket 端點上指定 ZX_SOCKET_DISPOSITION_WRITE_ENABLED 無效;這樣做會導致 zx_socket_set_disposition
傳回 ZX_ERR_BAD_STATE,且不會採取任何動作。
在 disposition 或 disposition_peer 中同時指定 ZX_SOCKET_DISPOSITION_WRITE_DISABLED 和 ZX_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 disposition 或 disposition_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 disposition 或 disposition_peer 包含上述以外的標記,或無效的標記組合。
遷移
實作後,zx_socket_shutdown
的現有用法將會替換為對 zx_socket_set_disposition
的等效呼叫。必要的 ABI 轉換完成後,系統就會移除 zx_socket_shutdown
及其相關選項。
實作
實作應完全在 Socket 調度器中執行。
成效
這項變更對效能沒有重大影響。
人體工學
這項變更對人體工學沒有重大影響。
回溯相容性
這項變更具有回溯相容性,因為未使用新 API 途徑的用戶端不會受到影響。
安全性考量
這項變更可讓 fdio 程式碼更簡單,進而提升安全性。這項變更對安全性沒有重大影響。
隱私權注意事項
這項變更對隱私權沒有重大影響。
測試
這項功能將透過以下方式進行測試:使用系統呼叫的單元測試,以及將已測試的 fdio 狀態機器部分替換為新機制。
說明文件
zx_socket_write
和 zx_socket_read
會更新為參照 zx_socket_set_disposition
,而非 zx_socket_shutdown
。
其他說明文件會按照實作部分的說明進行更新。
缺點、替代方案和未知因素
除了新的系統呼叫外,您也可以在 zx_socket_shutdown
中新增標記,讓系統呼叫的行為能夠反轉。這種做法的好處是避免引入與行為不相符的新字詞 (意向)。繼續使用 zx_socket_shutdown
的主要缺點是,它接受的標記不夠直觀;ZX_SOCKET_SHUTDOWN_READ
不會執行說明中的動作 (它會禁止對等寫入,而非禁止讀取)。
如果在套接字的指定方向中存在資料,則會指定「unshutdown」的行為為產生錯誤。另一個選擇是允許該作業成功執行;我們選擇更嚴格的選項,以免發生非預期的後果。
您可以使用現有權利,而不需要建立新的權利。對現有權利的調查顯示,沒有任何現有權利與此使用情形相符。
這項設計本身並無法完全解決串流通訊端的狀態傳播問題。這個提案的替代方案是更全面的方法,可盡力完全淘汰 fdio 串流通訊埠狀態機器。這類提案也必須納入這項提案。
既有技術與參考資料
實際上,流程式通訊端的語意是由其他作業系統中的行為定義,因此需要區分已連線和未連線的通訊端。