Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion ebpf_ffi/ebpf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,19 @@ struct bpf_result ffi_get_map_elements(int map_fd, uint64_t map_size) {
return serialize_proto(res);
}

struct bpf_result ffi_get_map_elements_fd_array(uint64_t fd_array_addr,
uint32_t idx,
uint64_t map_size) {
MapElements res;
std::vector<uint64_t> elements;
std::string error_message;

int *fd_array = reinterpret_cast<int *>(fd_array_addr);
Comment thread
thatjiaozi marked this conversation as resolved.
int map_fd = fd_array[idx];

return ffi_get_map_elements(map_fd, map_size);
}

bool execute_ebpf_program(int prog_fd, uint8_t *input, int input_length,
std::string &error_message) {
int socks[2] = {};
Expand Down Expand Up @@ -268,7 +281,7 @@ struct bpf_result ffi_execute_ebpf_program(void *serialized_proto,
void ffi_clean_fd_array(unsigned long long int addr, int size) {
int *fd_array = reinterpret_cast<int *>(addr);
for (int i = 0; i < size; i++) {
close(fd_array[size]);
close(fd_array[i]);
}
free(fd_array);
}
5 changes: 5 additions & 0 deletions ebpf_ffi/ebpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ int ffi_create_bpf_map(size_t size);
// MapElements.
struct bpf_result ffi_get_map_elements(int map_fd, uint64_t map_size);

// Retrieves all the map elements out of a map whose fd is stored in a fd array.
struct bpf_result ffi_get_map_elements_fd_array(uint64_t fd_array_addr,
uint32_t idx,
uint64_t map_size);

bool execute_ebpf_program(int prog_fd, uint8_t *input, int input_length,
std::string &error_message);

Expand Down
44 changes: 24 additions & 20 deletions pkg/strategies/coverage_based.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func NewCoverageBasedStrategy() *CoverageBased {
// value as well as all stack locations from -8 to -512.
defaultProg, _ := InstructionSequence(
// Need to patch the fd on every run of prog generation.
LdMapByFd(R1, 0),
LdMapByIdx(R1, 0),
StW(R10, 0, -4),
Mov64(R2, R10),
Add64(R2, -4),
Expand Down Expand Up @@ -61,8 +61,13 @@ func NewCoverageBasedStrategy() *CoverageBased {
fingerprintHashTable: make(map[uint64]bool),
programCount: 0,
validProgramCount: 0,
mapFd: -1,
defaultProg: defaultProg,
bpfMap: &epb.EbpfMap{
Type: epb.BpfMapType_ARRAY,
KeySize: 4,
ValueSize: 8,
MaxEntries: 2,
},
defaultProg: defaultProg,
}
}

Expand All @@ -78,17 +83,17 @@ type CoverageBased struct {
programCount int
validProgramCount int
lastProgram []*epb.Instruction
mapFd int
bpfMap *epb.EbpfMap
defaultProg []*epb.Instruction
}

func mapPtrArithmeticFooter(randomReg epb.Reg, mapFd int) ([]*epb.Instruction, error) {
func mapPtrArithmeticFooter(randomReg epb.Reg) ([]*epb.Instruction, error) {
return InstructionSequence(
// Select a random register and store its value in R8.
Mov64(R8, randomReg),

// Load a fd to the map.
LdMapByFd(R9, mapFd),
// Load a fd to the map. Should be stored in a fd array.
LdMapByIdx(R9, 0),

StW(R10, 0, -4),
Mov64(R2, R10),
Expand Down Expand Up @@ -215,18 +220,7 @@ func (cv *CoverageBased) GenerateProgram(ffi *units.FFI) (*pb.Program, error) {
return nil, err
}

// For the footer, write a control and test value to a map, control will
// not do ptr arithmetic, test will attempt to do some and see if the
// verifier thinks its safe. We will validate this assumption in onExecuteDone.
ffi.CloseFD(cv.mapFd)
cv.mapFd = ffi.CreateMapArray(1)
if cv.mapFd < 0 {
return nil, mapCreationFailed
}

mutatedProgram[0].Immediate = int32(cv.mapFd)

footer, err := mapPtrArithmeticFooter(RandomRegister(), cv.mapFd)
footer, err := mapPtrArithmeticFooter(RandomRegister())
if err != nil {
return nil, err
}
Expand All @@ -236,6 +230,7 @@ func (cv *CoverageBased) GenerateProgram(ffi *units.FFI) (*pb.Program, error) {
Functions: []*epb.Functions{
{Instructions: append(mutatedProgram, footer...)},
},
Maps: []*epb.EbpfMap{cv.bpfMap},
},
},
}
Expand Down Expand Up @@ -302,7 +297,16 @@ func (cv *CoverageBased) OnVerifyDone(ffi *units.FFI, verificationResult *fpb.Va
// OnExecuteDone should validate if the program behaved like the
// verifier expected, if that was not the case it should return false.
func (cv *CoverageBased) OnExecuteDone(ffi *units.FFI, executionResult *fpb.ExecutionResult) bool {
mapEl, _ := ffi.GetMapElements(cv.mapFd, 1)
if executionResult.FdArray == 0 {
fmt.Println("Error: invalid fd array address (null)")
return false
}
mapEl, _ := ffi.GetMapElementsFdArray(executionResult.FdArray, 0, 1)
if len(mapEl.Elements) == 0 {
fmt.Println("error reading map elements: ")
fmt.Println(mapEl.ErrorMessage)
return false
}
valid := mapEl.Elements[0] == 0xCAFE
cv.isFinished = !valid
return valid
Expand Down
6 changes: 5 additions & 1 deletion pkg/units/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ func (cu *Control) runEbpf(prog *epb.Program) error {
}

exRes, err := cu.ffi.RunEbpfProgram(exReq)
cu.ffi.CloseFD(int(validationResult.ProgramFd))
defer func() {
cu.ffi.CloseFD(int(validationResult.ProgramFd))
}()
if err != nil {
fmt.Printf("RunProgram error: %v\n", err)
if !cu.strat.OnError(err) {
Expand All @@ -167,6 +169,8 @@ func (cu *Control) runEbpf(prog *epb.Program) error {
return nil
}

exRes.FdArray = validationResult.FdArrayAddr

ok := cu.strat.OnExecuteDone(cu.ffi, exRes)
if !ok {
fmt.Println("Program produced unexpected results")
Expand Down
7 changes: 7 additions & 0 deletions pkg/units/ffi.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package units
//struct bpf_result ffi_load_ebpf_program(void* serialized_proto, size_t size, int coverage_enabled, unsigned long coverage_size);
//struct bpf_result ffi_execute_ebpf_program(void* serialized_proto, size_t length);
//struct bpf_result ffi_get_map_elements(int map_fd, uint64_t map_size);
//struct bpf_result ffi_get_map_elements_fd_array(uint64_t fd_array_addr, uint32_t idx, uint64_t map_size);
//int ffi_create_bpf_map(size_t size);
//void ffi_close_fd(int fd);
//int ffi_update_map_element(int map_fd, int key, uint64_t value);
Expand Down Expand Up @@ -127,6 +128,12 @@ func (e *FFI) GetMapElements(fd int, mapSize uint64) (*fpb.MapElements, error) {
return mapElementsProtoFromStruct(&res)
}

// GetMapElements fetches the map elements of the given fd_array position.
func (e *FFI) GetMapElementsFdArray(fd_array uint64, idx uint32, mapSize uint32) (*fpb.MapElements, error) {
res := C.ffi_get_map_elements_fd_array(C.ulong(fd_array), C.uint(idx), C.ulong(mapSize))
return mapElementsProtoFromStruct(&res)
}

// SetMapElement sets the elemnt specified by `key` to `value` in the map
// described by `fd`
func (e *FFI) SetMapElement(fd int, key uint32, value uint64) int {
Expand Down
1 change: 1 addition & 0 deletions proto/ffi.proto
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ message ExecutionResult {
bool did_succeed = 1;
string error_message = 2;
bytes output_data = 3;
uint64 fd_array = 4;
}

// Result from get_map_elements call, retrieves all the elements in a bpf map.
Expand Down
Loading