From 0808a665bc75ab0845906bfeca0d12fb520ae6eb Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Thu, 20 Feb 2025 12:25:04 +0100 Subject: pkg/rpcserver: pkg/flatrpc: executor: add handshake stage 0 As we figured out in #5805, syz-manager treats random incoming RPC connections as trusted, and will crash if a non-executor client sends an invalid packet to it. To address this issue, we introduce another stage of handshake, which includes a cookie exchange: - upon connection from an executor, the manager sends a ConnectHello RPC message to it, which contains a random 64-bit cookie; - the executor calculates a hash of that cookie and includes it into its ConnectRequest together with the other information; - before checking the validity of ConnectRequest, the manager ensures client sanity (passed ID didn't change, hashed cookie has the expected value) We deliberately pick a random cookie instead of a magic number: if the fuzzer somehow learns to send packets to the manager, we don't want it to crash multiple managers on the same machine. --- executor/executor_runner.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'executor/executor_runner.h') diff --git a/executor/executor_runner.h b/executor/executor_runner.h index a3b668893..88fc785db 100644 --- a/executor/executor_runner.h +++ b/executor/executor_runner.h @@ -629,9 +629,24 @@ private: failmsg("bad restarting", "restarting=%d", restarting_); } + // Implementation must match that in pkg/rpcserver/rpcserver.go. + uint64 HashAuthCookie(uint64 cookie) + { + const uint64_t prime1 = 73856093; + const uint64_t prime2 = 83492791; + + return (cookie * prime1) ^ prime2; + } + int Handshake() { + // Handshake stage 0: get a cookie from the manager. + rpc::ConnectHelloRawT conn_hello; + conn_.Recv(conn_hello); + + // Handshake stage 1: share basic information about the client. rpc::ConnectRequestRawT conn_req; + conn_req.cookie = HashAuthCookie(conn_hello.cookie); conn_req.id = vm_index_; conn_req.arch = GOARCH; conn_req.git_revision = GIT_REVISION; @@ -656,6 +671,7 @@ private: if (conn_reply.cover) max_signal_.emplace(); + // Handshake stage 2: share information requested by the manager. rpc::InfoRequestRawT info_req; info_req.files = ReadFiles(conn_reply.files); -- cgit mrf-deployment