[RFCv2 4/7] bpf/kexec: Introduce three bpf kfunc for kexec

Alexei Starovoitov alexei.starovoitov at gmail.com
Tue Apr 29 17:03:59 PDT 2025


On Mon, Apr 28, 2025 at 9:13 PM Pingfan Liu <piliu at redhat.com> wrote:
 +__bpf_kfunc struct mem_range_result *bpf_kexec_decompress(char
*image_gz_payload, int image_gz_sz,
> +                       unsigned int expected_decompressed_sz)
> +{
> +       decompress_fn decompressor;
> +       //todo, use flush to cap the memory size used by decompression
> +       long (*flush)(void*, unsigned long) = NULL;
> +       struct mem_range_result *range;
> +       const char *name;
> +       void *output_buf;
> +       char *input_buf;
> +       int ret;
> +
> +       range = kmalloc(sizeof(struct mem_range_result), GFP_KERNEL);
> +       if (!range) {
> +               pr_err("fail to allocate mem_range_result\n");
> +               return NULL;
> +       }
> +       refcount_set(&range->usage, 1);
> +
> +       input_buf = vmalloc(image_gz_sz);
> +       if (!input_buf) {
> +               pr_err("fail to allocate input buffer\n");
> +               kfree(range);
> +               return NULL;
> +       }
> +
> +       ret = copy_from_kernel_nofault(input_buf, image_gz_payload, image_gz_sz);
> +       if (ret < 0) {
> +               pr_err("Error when copying from 0x%px, size:0x%x\n",
> +                               image_gz_payload, image_gz_sz);
> +               kfree(range);
> +               vfree(input_buf);
> +               return NULL;
> +       }
> +
> +       output_buf = vmalloc(expected_decompressed_sz);
> +       if (!output_buf) {
> +               pr_err("fail to allocate output buffer\n");
> +               kfree(range);
> +               vfree(input_buf);
> +               return NULL;
> +       }
> +
> +       decompressor = decompress_method(input_buf, image_gz_sz, &name);
> +       if (!decompressor) {
> +               pr_err("Can not find decompress method\n");
> +               kfree(range);
> +               vfree(input_buf);
> +               vfree(output_buf);
> +               return NULL;
> +       }
> +       //to do, use flush
> +       ret = decompressor(image_gz_payload, image_gz_sz, NULL, NULL,
> +                               output_buf, NULL, NULL);
> +
> +       /* Update the range map */
> +       if (ret == 0) {
> +               range->buf = output_buf;
> +               range->size = expected_decompressed_sz;
> +               range->status = 0;
> +       } else {
> +               pr_err("Decompress error\n");
> +               vfree(output_buf);
> +               kfree(range);
> +               return NULL;
> +       }
> +       pr_info("%s, return range 0x%lx\n", __func__, range);
> +       return range;
> +}

These kfuncs look like generic decompress routines.
They're not related to kexec and probably should be in kernel/bpf/helpers.c
or kernel/bpf/compression.c instead of kernel/kexec_pe_image.c.

They also must be KF_SLEEPABLE.
Please test your patches with all kernel debugs enabled.
Otherwise you would have seen all these "sleeping while atomic"
issues yourself.



More information about the kexec mailing list