aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-04-15 10:45:34 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-04-15 11:53:27 +0000
commitb9af7e61fec27039b365f0ce8ec03fbccd2c6d6a (patch)
tree77c11460683ff0a9798cd47aff7e4de107713f8c /pkg/compiler
parent932a0a0dc74e7f3f5486b27216f3698a74084673 (diff)
prog: fix selection of args eligible for squashing
This fixes 3 issues: 1. We intended to squash only 'in' pointer elems, but we looked at the pointer direction rather than elem direction. Since pointers themselves are always 'in' we squashed a number of types we didn't want to squash. 2. We can squash filenames, which can lead to generation of escaping filenames, e.g. fuzzer managed to create "/" filename for blockdev_filename as: mount(&(0x7f0000000000)=ANY=[@ANYBLOB='/'], ...) Don't squash filenames. 3. We analyzed a concrete arg to see if it contains something we don't want to squash (e.g. pointers). But the whole type can still contain unsupported things in inactive union options, or in 0-sized arrays. E.g. this happened in the mount case above. Analyze the whole type to check for unsupported things. This also moves most of the analysis to the compiler, so mutation will be a bit faster. This removes the following linux types from squashing. 1. These are not 'in': btrfs_ioctl_search_args_v2 btrfs_ioctl_space_args ethtool_cmd_u fscrypt_add_key_arg fscrypt_get_policy_ex_arg fsverity_digest hiddev_ioctl_string_arg hidraw_report_descriptor ifreq_dev_t[devnames, ptr[inout, ethtool_cmd_u]] ifreq_dev_t[ipv4_tunnel_names, ptr[inout, ip_tunnel_parm]] ifreq_dev_t["sit0", ptr[inout, ip_tunnel_prl]] io_uring_probe ip_tunnel_parm ip_tunnel_prl poll_cq_resp query_port_cmd query_qp_resp resize_cq_resp scsi_ioctl_probe_host_out_buffer sctp_assoc_ids sctp_authchunks sctp_getaddrs sctp_getaddrs_old 2. These contain pointers: binder_objects iovec[in, netlink_msg_route_sched] iovec[in, netlink_msg_route_sched_retired] msghdr_netlink[netlink_msg_route_sched] msghdr_netlink[netlink_msg_route_sched_retired] nvme_of_msg 3. These contain filenames: binfmt_script blockdev_filename netlink_msg_route_sched netlink_msg_route_sched_retired selinux_create_req
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/types.go54
1 files changed, 51 insertions, 3 deletions
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index e77f80a3d..70a0bd565 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -210,14 +210,62 @@ var typePtr = &typeDesc{
base.TypeSize = 8
}
base.TypeAlign = getIntAlignment(comp, base)
+ elem := comp.genType(args[1], 0)
+ elemDir := genDir(args[0])
return &prog.PtrType{
- TypeCommon: base.TypeCommon,
- Elem: comp.genType(args[1], 0),
- ElemDir: genDir(args[0]),
+ TypeCommon: base.TypeCommon,
+ Elem: elem,
+ ElemDir: elemDir,
+ SquashableElem: isSquashableElem(elem, elemDir),
}
},
}
+func isSquashableElem(elem prog.Type, dir prog.Dir) bool {
+ if dir != prog.DirIn {
+ return false
+ }
+ // Check if the pointer element contains something that can be complex, and does not contain
+ // anything unsupported we don't want to sqaush. Prog package later checks at runtime
+ // if a concrete arg actually contains something complex. But we look at the whole type
+ // to understand if it contains anything unsupported b/c a union may contain e.g. a complex struct
+ // and a filename we don't want to squash, or an array may contain something unsupported,
+ // but has 0 size in a concrete argument.
+ complex, unsupported := false, false
+ prog.ForeachArgType(elem, func(t prog.Type, ctx *prog.TypeCtx) {
+ switch typ := t.(type) {
+ case *prog.StructType:
+ if typ.Varlen() {
+ complex = true
+ }
+ if typ.OverlayField != 0 {
+ // Squashing of structs with out_overlay is not supported.
+ // If we do it, we need to be careful to either squash out part as well,
+ // or remove any resources in the out part from the prog.
+ unsupported = true
+ }
+ case *prog.UnionType:
+ if typ.Varlen() && len(typ.Fields) > 5 {
+ complex = true
+ }
+ case *prog.PtrType:
+ // Squashing of pointers is not supported b/c if we do it
+ // we will pass random garbage as pointers.
+ unsupported = true
+ case *prog.BufferType:
+ switch typ.Kind {
+ case prog.BufferFilename, prog.BufferGlob, prog.BufferCompressed:
+ // Squashing file names may lead to unwanted escaping paths (e.g. "/"),
+ // squashing compressed buffers is not useful since we uncompress them ourselves
+ // (not the kernel).
+ unsupported = true
+ }
+ }
+ ctx.Stop = unsupported
+ })
+ return complex && !unsupported
+}
+
var typeVoid = &typeDesc{
Names: []string{"void"},
CantBeOpt: true,