Skip to content

Commit

Permalink
pkg/compiler: fix incorrect alignment calculation for padding
Browse files Browse the repository at this point in the history
We assumed that for ConstType alignment is equal to size,
which is perfectly reasonable for normal int8/16/32/64/ptr.
However, padding is also represented by ConstType of arbitrary size,
so if we added 157 bytes of padding that becomes alignment of
the padding field and as the result of the whole struct.
This affects very few structs, but quite radically and quite
important structs.

Discovered thanks to syz-check.

Update #590
  • Loading branch information
dvyukov committed Dec 18, 2019
1 parent 42dc692 commit 73c3845
Show file tree
Hide file tree
Showing 16 changed files with 275 additions and 546 deletions.
12 changes: 6 additions & 6 deletions executor/defs.h

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

12 changes: 7 additions & 5 deletions pkg/compiler/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,15 +349,17 @@ func (comp *compiler) addAlignment(fields []prog.Type, varlen, packed bool, alig
}

func (comp *compiler) typeAlign(t0 prog.Type) uint64 {
switch t0.(type) {
case *prog.IntType, *prog.ConstType, *prog.LenType, *prog.FlagsType, *prog.ProcType,
switch t := t0.(type) {
case *prog.IntType, *prog.LenType, *prog.FlagsType, *prog.ProcType,
*prog.CsumType, *prog.PtrType, *prog.VmaType, *prog.ResourceType:
return t0.Size()
case *prog.ConstType:
if t.IsPad {
return 1
}
return t.Size()
case *prog.BufferType:
return 1
}

switch t := t0.(type) {
case *prog.ArrayType:
return comp.typeAlign(t.Type)
case *prog.StructType:
Expand Down
11 changes: 10 additions & 1 deletion pkg/compiler/testdata/all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,16 @@ s1 {
f1 int8
} [size[C2]]

foo$s0(a ptr[in, s0], b ptr[in, s1])
s2 {
f1 int8
f2 s3
} [size[101]]

s3 {
f1 int8
} [size[100]]

foo$s0(a ptr[in, s0], b ptr[in, s1], c ptr[in, s2])

# Unions.

Expand Down
3 changes: 0 additions & 3 deletions sys/linux/dev_kvm.txt.warn
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,5 @@ field kvm_fpu.pad1: bad offset: syz=132 kernel=133
struct kvm_irq_chip: no corresponding struct in kernel
struct kvm_ioapic_redir: no corresponding struct in kernel
struct kvm_mce_cap: no corresponding struct in kernel
struct kvm_nested_state: bad size: syz=288 kernel=128
field kvm_nested_state.hdr: bad offset: syz=96 kernel=8
field kvm_nested_state.data: bad offset: syz=216 kernel=128
struct kvm_nested_state_arg: no corresponding struct in kernel
struct kvm_vmx_nested_state: no corresponding struct in kernel
131 changes: 42 additions & 89 deletions sys/linux/gen/386.go

Large diffs are not rendered by default.

130 changes: 42 additions & 88 deletions sys/linux/gen/amd64.go

Large diffs are not rendered by default.

117 changes: 38 additions & 79 deletions sys/linux/gen/arm.go

Large diffs are not rendered by default.

116 changes: 38 additions & 78 deletions sys/linux/gen/arm64.go

Large diffs are not rendered by default.

116 changes: 38 additions & 78 deletions sys/linux/gen/mips64le.go

Large diffs are not rendered by default.

116 changes: 38 additions & 78 deletions sys/linux/gen/ppc64le.go

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions sys/linux/netfilter.txt.warn
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,6 @@ field xt_policy_elem.spi/mode: bad size: syz=4 kernel=1
field xt_policy_elem.reqid/match: bad offset: syz=68 kernel=74
field xt_policy_elem.reqid/match: bad size: syz=4 kernel=1
field xt_policy_elem.proto/invert: bad offset: syz=72 kernel=75
struct xt_physdev_info: bad size: syz=105 kernel=66
field xt_physdev_info.in_mask: bad offset: syz=30 kernel=16
field xt_physdev_info.physoutdev: bad offset: syz=46 kernel=32
field xt_physdev_info.out_mask: bad offset: syz=75 kernel=48
field xt_physdev_info.invert: bad offset: syz=91 kernel=64
field xt_physdev_info.bitmask: bad offset: syz=92 kernel=65
struct xt_esp: bad number of fields: syz=3 kernel=2
field xt_esp.spis_min/spis: bad size: syz=4 kernel=8
field xt_esp.spis_max/invflags: bad offset: syz=4 kernel=8
Expand Down
32 changes: 16 additions & 16 deletions sys/linux/netfilter_arp.txt.warn
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ struct arpt_entry_matches: no corresponding struct in kernel
struct arpt_entry_underflow: no corresponding struct in kernel
struct arpt_entry_underflow_matches: no corresponding struct in kernel
struct arpt_arp_or_uncond: no corresponding struct in kernel
struct arpt_arp: bad size: syz=210 kernel=164
struct arpt_arp: bad size: syz=160 kernel=164
field arpt_arp.src_devaddr/arhln: bad size: syz=16 kernel=1
field arpt_arp.src_devmask/arhln_mask: bad offset: syz=40 kernel=17
field arpt_arp.src_devmask/arhln_mask: bad offset: syz=32 kernel=17
field arpt_arp.src_devmask/arhln_mask: bad size: syz=16 kernel=1
field arpt_arp.tgt_devaddr/src_devaddr: bad offset: syz=56 kernel=18
field arpt_arp.tgt_devaddr/src_devaddr: bad offset: syz=48 kernel=18
field arpt_arp.tgt_devaddr/src_devaddr: bad size: syz=16 kernel=32
field arpt_arp.tgt_devmask/tgt_devaddr: bad offset: syz=80 kernel=50
field arpt_arp.tgt_devmask/tgt_devaddr: bad offset: syz=64 kernel=50
field arpt_arp.tgt_devmask/tgt_devaddr: bad size: syz=16 kernel=32
field arpt_arp.arpop: bad offset: syz=96 kernel=82
field arpt_arp.arpop_mask: bad offset: syz=98 kernel=84
field arpt_arp.arhrd: bad offset: syz=100 kernel=86
field arpt_arp.arhrd_mask: bad offset: syz=102 kernel=88
field arpt_arp.arpro: bad offset: syz=104 kernel=90
field arpt_arp.arpro_mask: bad offset: syz=106 kernel=92
field arpt_arp.iniface: bad offset: syz=108 kernel=94
field arpt_arp.outiface: bad offset: syz=124 kernel=110
field arpt_arp.iniface_mask: bad offset: syz=150 kernel=126
field arpt_arp.outiface_mask: bad offset: syz=180 kernel=142
field arpt_arp.flags: bad offset: syz=196 kernel=158
field arpt_arp.invflags: bad offset: syz=198 kernel=160
field arpt_arp.arpop: bad offset: syz=80 kernel=82
field arpt_arp.arpop_mask: bad offset: syz=82 kernel=84
field arpt_arp.arhrd: bad offset: syz=84 kernel=86
field arpt_arp.arhrd_mask: bad offset: syz=86 kernel=88
field arpt_arp.arpro: bad offset: syz=88 kernel=90
field arpt_arp.arpro_mask: bad offset: syz=90 kernel=92
field arpt_arp.iniface: bad offset: syz=92 kernel=94
field arpt_arp.outiface: bad offset: syz=108 kernel=110
field arpt_arp.iniface_mask: bad offset: syz=124 kernel=126
field arpt_arp.outiface_mask: bad offset: syz=140 kernel=142
field arpt_arp.flags: bad offset: syz=156 kernel=158
field arpt_arp.invflags: bad offset: syz=158 kernel=160
struct arpt_devaddr: no corresponding struct in kernel
struct arpt_devmask: no corresponding struct in kernel
struct arpt_counters_info: no corresponding struct in kernel
6 changes: 0 additions & 6 deletions sys/linux/netfilter_ipv4.txt.warn
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
struct ipt_entry_underflow: no corresponding struct in kernel
struct ipt_entry_underflow_matches: no corresponding struct in kernel
struct ipt_ip_or_uncond: no corresponding struct in kernel
struct ipt_ip: bad size: syz=120 kernel=84
field ipt_ip.iniface_mask: bad offset: syz=60 kernel=48
field ipt_ip.outiface_mask: bad offset: syz=90 kernel=64
field ipt_ip.proto: bad offset: syz=106 kernel=80
field ipt_ip.flags: bad offset: syz=108 kernel=82
field ipt_ip.invflags: bad offset: syz=109 kernel=83
struct ipt_icmp: bad number of fields: syz=4 kernel=3
field ipt_icmp.code_min/code: bad size: syz=1 kernel=2
field ipt_icmp.code_max/invflags: bad offset: syz=2 kernel=3
Expand Down
7 changes: 0 additions & 7 deletions sys/linux/netfilter_ipv6.txt.warn
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
struct ip6t_entry_underflow: no corresponding struct in kernel
struct ip6t_entry_underflow_matches: no corresponding struct in kernel
struct ip6t_ip6_or_uncond: no corresponding struct in kernel
struct ip6t_ip6: bad size: syz=165 kernel=136
field ip6t_ip6.iniface_mask: bad offset: syz=105 kernel=96
field ip6t_ip6.outiface_mask: bad offset: syz=135 kernel=112
field ip6t_ip6.proto: bad offset: syz=152 kernel=128
field ip6t_ip6.tos: bad offset: syz=154 kernel=130
field ip6t_ip6.flags: bad offset: syz=155 kernel=131
field ip6t_ip6.invflags: bad offset: syz=156 kernel=132
struct ip6t_icmp: bad number of fields: syz=4 kernel=3
field ip6t_icmp.code_min/code: bad size: syz=1 kernel=2
field ip6t_icmp.code_max/invflags: bad offset: syz=2 kernel=3
Expand Down
2 changes: 0 additions & 2 deletions sys/linux/socket_netrom.txt.warn
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
struct address_netrom_dev: no corresponding struct in kernel
struct nr_route_struct: bad size: syz=120 kernel=112
field nr_route_struct.device: bad offset: syz=12 kernel=11
4 changes: 0 additions & 4 deletions sys/linux/socket_rose.txt.warn
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
struct rose_address: bad number of fields: syz=2 kernel=1
struct rose_address_remote: no corresponding struct in kernel
struct rose_address_dev: no corresponding struct in kernel
struct rose_route_struct: bad size: syz=108 kernel=88
field rose_route_struct.device: bad offset: syz=24 kernel=15
field rose_route_struct.ndigis: bad offset: syz=40 kernel=31
field rose_route_struct.digipeaters: bad offset: syz=41 kernel=32

0 comments on commit 73c3845

Please sign in to comment.