From ae5ed0b14052adc4be0d98e5e8a46a0b0ab2c565 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 20 Dec 2019 13:57:42 +0100 Subject: pkg/compiler: fix bitfield layout bug Fixes #1542 Found thanks to syz-check. Update #590 --- tools/syz-check/check.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/syz-check/check.go b/tools/syz-check/check.go index 0582d892c..5bd556516 100644 --- a/tools/syz-check/check.go +++ b/tools/syz-check/check.go @@ -171,6 +171,9 @@ func checkStruct(typ *prog.StructDesc, astStruct *ast.Struct, str *dwarf.StructT warn(astStruct.Pos, "struct %v: bad size: syz=%v kernel=%v", typ.Name(), typ.Size(), str.ByteSize) } // TODO: handle unions, currently we should report some false errors. + if str.Kind == "union" { + return warnings, nil + } // TODO: we could also check enums (elements match corresponding flags in syzkaller). // TODO: we could also check values of literal constants (dwarf should have that, right?). ai := 0 @@ -191,24 +194,25 @@ func checkStruct(typ *prog.StructDesc, astStruct *ast.Struct, str *dwarf.StructT warn(pos, "%v: bad size: syz=%v kernel=%v", desc, field.UnitSize(), fld.Type.Size()) } - if offset != uint64(fld.ByteOffset) { + byteOffset := offset - field.UnitOffset() + if byteOffset != uint64(fld.ByteOffset) { warn(pos, "%v: bad offset: syz=%v kernel=%v", - desc, offset, fld.ByteOffset) + desc, byteOffset, fld.ByteOffset) } // How would you define bitfield offset? // Offset of the beginning of the field from the beginning of the memory location, right? // No, DWARF defines it as offset of the end of the field from the end of the memory location. - offset := fld.Type.Size()*8 - fld.BitOffset - fld.BitSize + bitOffset := fld.Type.Size()*8 - fld.BitOffset - fld.BitSize if fld.BitSize == 0 { // And to make things even more interesting this calculation // does not work for normal variables. - offset = 0 + bitOffset = 0 } if field.BitfieldLength() != uint64(fld.BitSize) || - field.BitfieldOffset() != uint64(offset) { + field.BitfieldOffset() != uint64(bitOffset) { warn(pos, "%v: bad bit size/offset: syz=%v/%v kernel=%v/%v", desc, field.BitfieldLength(), field.BitfieldOffset(), - fld.BitSize, offset) + fld.BitSize, bitOffset) } } ai++ -- cgit mrf-deployment