diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2022-01-04 15:29:10 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2022-01-11 16:30:08 +0100 |
| commit | bad18a53de8fa8d3d097e3d701efb72a014661cb (patch) | |
| tree | 2ff6cc1aa917897c643d2e4bc5e6ce2098d55a6d /pkg/compiler | |
| parent | a19c1bce2eee5a1893b4ae9c8292b0f1b2630225 (diff) | |
pkg/compiler: require stricter resource constructors
Don't consider syscalls that return resources in unions/arrays as constructors.
Unions and arrays are problematic because we don't have directed generation
in prog.randGen.createResource() and can fail to generate a syscall that
returns a particular resource (generate a wrong union option that does not
contain the necessary resource). This leads to the following panics:
panic: failed to create a resource ifindex with ioctl$sock_SIOCGIFCONF
Require each resource to have a constructor syscall that returns the resource
outside of unions/arrays.
Diffstat (limited to 'pkg/compiler')
| -rw-r--r-- | pkg/compiler/check.go | 21 | ||||
| -rw-r--r-- | pkg/compiler/gen.go | 3 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors2.txt | 8 | ||||
| -rw-r--r-- | pkg/compiler/types.go | 3 |
4 files changed, 26 insertions, 9 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index fe4ac7c62..ae9724dfc 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -632,10 +632,10 @@ func (comp *compiler) checkConstructors() { switch n := decl.(type) { case *ast.Call: for _, arg := range n.Args { - comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, inputs, checked) + comp.checkTypeCtors(arg.Type, prog.DirIn, true, true, ctors, inputs, checked) } if n.Ret != nil { - comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, inputs, checked) + comp.checkTypeCtors(n.Ret, prog.DirOut, true, true, ctors, inputs, checked) } } } @@ -658,16 +658,19 @@ func (comp *compiler) checkConstructors() { } } -func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, +func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate bool, ctors, inputs map[string]bool, checked map[structDir]bool) { - desc := comp.getTypeDesc(t) + desc, args, base := comp.getArgsBase(t, isArg) + if base.IsOptional { + canCreate = false + } if desc == typeResource { // TODO(dvyukov): consider changing this to "dir == prog.DirOut". // We have few questionable cases where resources can be created // only by inout struct fields. These structs should be split // into two different structs: one is in and second is out. // But that will require attaching dir to individual fields. - if dir != prog.DirIn { + if canCreate && dir != prog.DirIn { r := comp.resources[t.Ident] for r != nil && !ctors[r.Name.Name] { ctors[r.Name.Name] = true @@ -685,6 +688,9 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, } if desc == typeStruct { s := comp.structs[t.Ident] + if s.IsUnion { + canCreate = false + } name := s.Name.Name key := structDir{name, dir} if checked[key] { @@ -696,17 +702,16 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, if !fldHasDir { fldDir = dir } - comp.checkTypeCtors(fld.Type, fldDir, false, ctors, inputs, checked) + comp.checkTypeCtors(fld.Type, fldDir, false, canCreate, ctors, inputs, checked) } return } if desc == typePtr { dir = genDir(t.Args[0]) } - _, args, _ := comp.getArgsBase(t, isArg) for i, arg := range args { if desc.Args[i].Type == typeArgType { - comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, ctors, inputs, checked) + comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, canCreate, ctors, inputs, checked) } } } diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go index 89571c966..3d5517ae8 100644 --- a/pkg/compiler/gen.go +++ b/pkg/compiler/gen.go @@ -379,7 +379,8 @@ func (comp *compiler) layoutStructFields(t *prog.StructType, varlen, packed bool t.Fields = comp.finalizeStructFields(t, newFields, varlen, structAlign, byteOffset, bitOffset) } -func (comp *compiler) finalizeStructFields(t *prog.StructType, fields []prog.Field, varlen bool, structAlign, byteOffset, bitOffset uint64) []prog.Field { +func (comp *compiler) finalizeStructFields(t *prog.StructType, fields []prog.Field, varlen bool, + structAlign, byteOffset, bitOffset uint64) []prog.Field { if bitOffset != 0 { pad := roundup(bitOffset, 8) / 8 byteOffset += pad diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt index 40764777c..482314b4a 100644 --- a/pkg/compiler/testdata/errors2.txt +++ b/pkg/compiler/testdata/errors2.txt @@ -189,12 +189,15 @@ resource r117[int8] ### resource r117 is never used as an input (such resources resource r118[int8] ### resource r118 is never used as an input (such resources are not useful) resource r119[int8] ### resource r119 is never used as an input (such resources are not useful) resource r120[int8] ### resource r120 can't be created (never mentioned as a syscall return value or output argument/field) +resource r121[int8] ### resource r121 can't be created (never mentioned as a syscall return value or output argument/field) foo$300(a0 r100, a1 r101, a2 r102, a3 r103, a4 r104, a5 r105, a6 r106, a7 r107, a8 r108) foo$301(a0 r109, a1 r110, a2 r111, a3 r112, a4 r113, a5 r114, a6 r115, a7 r120) foo$302(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104 foo$303(a ptr[in, s302], b ptr[in, s303], c ptr[in, s304], d ptr[out, s305], e ptr[inout, s306], f ptr[inout, s307], g ptr[in, s308], h ptr[out, s310]) foo$304(a ptr[out, r117], b ptr[in, s312], c ptr[in, s313]) r116 +foo$305(a0 r121) +foo$306(a0 ptr[out, u315]) s300 { f1 ptr[inout, s301] @@ -266,6 +269,11 @@ s314 { f1 r119 (out) } +u315 [ + f1 r121 + f2 int32 +] + # TODO: Two instances of the same resource might exist in the same structure as # both in and out. How common is this and how to handle this? diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 8454a92d5..fc4acfee3 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -1093,6 +1093,9 @@ resource ANYRES64[int64]: -1, 0 syz_builtin0(a ptr[in, ANYPTRS]) (disabled) syz_builtin1(a ptr[out, ANYUNION]) (disabled) +syz_builtin2() ANYRES16 (disabled) +syz_builtin3() ANYRES32 (disabled) +syz_builtin4() ANYRES64 (disabled) ` func init() { |
