Skip to content

Commit c64ffee

Browse files
shun159lmb
authored andcommitted
struct_ops: skip copy for zeroed nested structs and fail on non-zeroed
resolves #1880 Signed-off-by: shun159 <[email protected]>
1 parent 843f326 commit c64ffee

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

collection.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -751,21 +751,18 @@ func (cl *collectionLoader) populateStructOps(m *Map, mapSpec *MapSpec) error {
751751
if srcOff < 0 || srcOff+mSize > len(userData) {
752752
return fmt.Errorf("member %q: userdata is too small", m.Name)
753753
}
754-
for _, b := range userData[srcOff : srcOff+mSize] {
755-
// let fail if the field in type user type is missing in type kern type
756-
if b != 0 {
757-
return fmt.Errorf("%s doesn't exist in %s, but it has non-zero value", m.Name, kType.Name)
758-
}
754+
755+
// let fail if the field in type user type is missing in type kern type
756+
if !structOpsIsMemZeroed(userData[srcOff : srcOff+mSize]) {
757+
return fmt.Errorf("%s doesn't exist in %s, but it has non-zero value", m.Name, kType.Name)
759758
}
759+
760760
continue
761761
}
762762

763763
km := kType.Members[i]
764764

765765
switch btf.UnderlyingType(m.Type).(type) {
766-
case *btf.Struct, *btf.Union:
767-
return fmt.Errorf("nested struct or union not supported")
768-
769766
case *btf.Pointer:
770767
// If this is a pointer → resolve struct_ops program.
771768
psKey := kType.Name + ":" + m.Name

struct_ops.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,25 @@ func structOpsCopyMember(m, km btf.Member, data []byte, kernVData []byte) error
115115
return fmt.Errorf("unmatched member type %s != %s (kernel)", m.Name, km.Name)
116116
}
117117

118+
switch mType.(type) {
119+
case *btf.Struct, *btf.Union:
120+
if !structOpsIsMemZeroed(data[srcOff : srcOff+mSize]) {
121+
return fmt.Errorf("non-zero nested struct %s: %w", m.Name, ErrNotSupported)
122+
}
123+
// the bytes has zeroed value, we simply skip the copy.
124+
return nil
125+
}
126+
118127
copy(kernVData[dstOff:dstOff+mSize], data[srcOff:srcOff+mSize])
119128
return nil
120129
}
130+
131+
// structOpsIsMemZeroed() checks whether all bytes in data are zero.
132+
func structOpsIsMemZeroed(data []byte) bool {
133+
for _, b := range data {
134+
if b != 0 {
135+
return false
136+
}
137+
}
138+
return true
139+
}

0 commit comments

Comments
 (0)