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;
> +}
> +

[...]


Reply via email to