From bc2ae5925bc400f1d1b913a14d7b55832770114f Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Wed, 8 Nov 2023 11:03:20 +0000 Subject: [PATCH] asm: refuse marshaling unknown extended opcodes We currently rely on the low byte of OpCode to be a valid BPF opcode. Make this clearer by adding a method to OpCode. This allows us to reject invalid extended opcodes during marshaling. Signed-off-by: Lorenz Bauer --- asm/instruction.go | 7 ++++++- asm/opcode.go | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/asm/instruction.go b/asm/instruction.go index ae96d622f..67cd39d6f 100644 --- a/asm/instruction.go +++ b/asm/instruction.go @@ -159,8 +159,13 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error) ins.Offset = newOffset } + op, err := ins.OpCode.bpfOpCode() + if err != nil { + return 0, err + } + data := make([]byte, InstructionSize) - data[0] = byte(ins.OpCode) + data[0] = op data[1] = byte(regs) bo.PutUint16(data[2:4], uint16(ins.Offset)) bo.PutUint32(data[4:8], uint32(cons)) diff --git a/asm/opcode.go b/asm/opcode.go index bbda2107f..1dfd0b171 100644 --- a/asm/opcode.go +++ b/asm/opcode.go @@ -93,6 +93,17 @@ type OpCode uint16 // InvalidOpCode is returned by setters on OpCode const InvalidOpCode OpCode = 0xffff +// bpfOpCode returns the actual BPF opcode. +func (op OpCode) bpfOpCode() (byte, error) { + const opCodeMask = 0xff + + if !valid(op, opCodeMask) { + return 0, fmt.Errorf("invalid opcode %x", op) + } + + return byte(op & opCodeMask), nil +} + // rawInstructions returns the number of BPF instructions required // to encode this opcode. func (op OpCode) rawInstructions() int {