On Fri, 2024-08-30 at 00:29 -0700, Tony Ambardar wrote: [...] > @@ -3050,11 +3127,42 @@ static int btf_ext_parse_hdr(__u8 *data, __u32 data_size) > return -ENOTSUP; > } > > - if (data_size == hdr->hdr_len) { > + if (data_size < hdr_len) { > + pr_debug("BTF.ext header not found\n"); > + return -EINVAL; > + } else if (data_size == hdr_len) { > pr_debug("BTF.ext has no data\n"); > return -EINVAL; > } > > + /* Verify mandatory hdr info details present */ > + if (hdr_len < offsetofend(struct btf_ext_header, line_info_len)) { > + pr_warn("BTF.ext header missing func_info, line_info\n"); > + return -EINVAL; > + } > + > + /* Keep hdr native byte-order in memory for introspection */ > + if (btf_ext->swapped_endian) > + btf_ext_bswap_hdr(btf_ext, hdr_len); > + > + /* Basic info section consistency checks*/ > + info_size = btf_ext->data_size - hdr_len; > + if (info_size & 0x03) { > + pr_warn("BTF.ext info size not 4-byte multiple\n"); > + return -EINVAL; > + } > + info_size -= hdr->func_info_len + hdr->line_info_len; > + if (hdr_len >= offsetofend(struct btf_ext_header, core_relo_len)) > + info_size -= hdr->core_relo_len; nit: Since we are checking this, maybe also check that sections do not overlap? Also, why disallowing gaps between sections? > + if (info_size) { > + pr_warn("BTF.ext info size mismatch with header data\n"); > + return -EINVAL; > + } > + > + /* Keep infos native byte-order in memory for introspection */ > + if (btf_ext->swapped_endian) > + btf_ext_bswap_info(btf_ext, !btf_ext->swapped_endian); > + > return 0; > } [...] > @@ -3119,15 +3223,71 @@ struct btf_ext *btf_ext__new(const __u8 *data, __u32 size) > return btf_ext; > } > > +static void *btf_ext_raw_data(const struct btf_ext *btf_ext_ro, __u32 *size, > + bool swap_endian) > +{ > + struct btf_ext *btf_ext = (struct btf_ext *)btf_ext_ro; > + const __u32 data_sz = btf_ext->data_size; > + void *data; > + > + data = swap_endian ? btf_ext->data_swapped : btf_ext->data; > + if (data) { > + *size = data_sz; > + return data; > + } > + > + data = calloc(1, data_sz); > + if (!data) > + return NULL; > + memcpy(data, btf_ext->data, data_sz); > + > + if (swap_endian) { > + btf_ext_bswap_info(btf_ext, true); > + btf_ext_bswap_hdr(btf_ext, btf_ext->hdr->hdr_len); > + btf_ext->data_swapped = data; > + } Nit: I don't like how this function is organized: - if btf_ext->data can't be NULL swap_endian == true at this point; - if btf_ext->data can be NULL and swap_endian == false pointer to `data` would be lost. I assume that btf_ext->data can't be null, basing on the btf_ext__new(), but function body is a bit confusing. > + > + *size = data_sz; > + return data; > +} > + [...]