Skip to content

Commit 97aa71a

Browse files
authored
fix(nbd): parse Request flags and type as separate u16 fields (#2548)
The NBD request wire layout (big-endian, 28 bytes) is `magic(4) | flags(2) | type(2) | handle(8) | from(8) | length(4)`, but `dispatch.go` was reading the four bytes after `magic` as a single `uint32` and assigning it to `Request.Type`. That works only while the kernel chooses `flags=0`; as soon as it sets any `NBD_CMD_FLAG_*` bit (e.g. `NBD_CMD_FLAG_FUA` on a sync write) the high half leaks into `Type` and the dispatch switch falls through to the default error path, killing the NBD connection. This PR splits `Flags` from `Type` into two `uint16` fields, decodes each independently, and extracts the parsing into a small `parseRequest` helper so the byte offsets are unit-testable. All command flags are still intentionally ignored. Production traffic on `main` is unaffected: the orchestrator does not advertise `FlagSendTrim` or `FlagSendWriteZeroes`, so today's kernels never set non-zero flags on the requests we receive. This is purely a correctness fix to the wire parser so the dispatch keeps matching the right command the moment any flag bit is set.
1 parent 1af207c commit 97aa71a

1 file changed

Lines changed: 12 additions & 3 deletions

File tree

packages/orchestrator/pkg/sandbox/nbd/dispatch.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,18 @@ const (
7070
NBDResponseMagic = 0x67446698
7171
)
7272

73-
// NBD Request packet
73+
// NBD Request packet. Wire layout (big-endian, 28 bytes total):
74+
//
75+
// magic(4) | flags(2) | type(2) | handle(8) | from(8) | length(4)
76+
//
77+
// Spec: https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md#request-message
78+
//
79+
// Flags carries the NBD_CMD_FLAG_* bits and is intentionally ignored — split
80+
// from Type so a non-zero flag bit doesn't corrupt the command opcode.
7481
type Request struct {
7582
Magic uint32
76-
Type uint32
83+
Flags uint16
84+
Type uint16
7785
Handle uint64
7886
From uint64
7987
Length uint32
@@ -189,7 +197,8 @@ func (d *Dispatch) Handle(ctx context.Context) error {
189197

190198
header := buffer[rp : rp+28]
191199
request.Magic = binary.BigEndian.Uint32(header)
192-
request.Type = binary.BigEndian.Uint32(header[4:8])
200+
request.Flags = binary.BigEndian.Uint16(header[4:6])
201+
request.Type = binary.BigEndian.Uint16(header[6:8])
193202
request.Handle = binary.BigEndian.Uint64(header[8:16])
194203
request.From = binary.BigEndian.Uint64(header[16:24])
195204
request.Length = binary.BigEndian.Uint32(header[24:28])

0 commit comments

Comments
 (0)