Skip to content

Commit 8b250a1

Browse files
Pingfan LiuKernel Patches Daemon
authored andcommitted
kexec: Integrate with the introduced bpf kfuncs
This patch does two things: First, register as a listener on bpf_copy_to_kernel() Second, in order that the hooked bpf-prog can call the sleepable kfuncs, bpf_handle_pefile and bpf_post_handle_pefile are marked as KF_SLEEPABLE. Signed-off-by: Pingfan Liu <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Philipp Rudo <[email protected]> Cc: Baoquan He <[email protected]> Cc: Dave Young <[email protected]> Cc: Andrew Morton <[email protected]> Cc: [email protected] To: [email protected]
1 parent 3578d8b commit 8b250a1

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

kernel/kexec_pe_image.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,51 @@ static struct kexec_res parsed_resource[3] = {
3838
{ KEXEC_RES_CMDLINE_NAME, },
3939
};
4040

41+
/*
42+
* @name should be one of : kernel, initrd, cmdline
43+
*/
44+
static int bpf_kexec_carrier(const char *name, struct mem_range_result *r)
45+
{
46+
struct kexec_res *res;
47+
int i;
48+
49+
if (!r || !name)
50+
return -EINVAL;
51+
52+
for (i = 0; i < 3; i++) {
53+
if (!strcmp(parsed_resource[i].name, name))
54+
break;
55+
}
56+
if (i >= 3)
57+
return -EINVAL;
58+
59+
res = &parsed_resource[i];
60+
/*
61+
* Replace the intermediate resource generated by the previous step.
62+
*/
63+
if (!!res->r)
64+
mem_range_result_put(res->r);
65+
mem_range_result_get(r);
66+
res->r = r;
67+
return 0;
68+
}
69+
70+
static struct carrier_listener kexec_res_listener[3] = {
71+
{ .name = KEXEC_RES_KERNEL_NAME,
72+
.alloc_type = 1,
73+
.handler = bpf_kexec_carrier,
74+
},
75+
{ .name = KEXEC_RES_INITRD_NAME,
76+
.alloc_type = 1,
77+
.handler = bpf_kexec_carrier,
78+
},
79+
{ .name = KEXEC_RES_CMDLINE_NAME,
80+
/* kmalloc-ed */
81+
.alloc_type = 0,
82+
.handler = bpf_kexec_carrier,
83+
},
84+
};
85+
4186
static bool pe_has_bpf_section(const char *file_buf, unsigned long pe_sz);
4287

4388
static bool is_valid_pe(const char *kernel_buf, unsigned long kernel_len)
@@ -159,6 +204,22 @@ __attribute__((used, optimize("O0"))) void bpf_post_handle_pefile(struct kexec_c
159204
dummy += 2;
160205
}
161206

207+
BTF_KFUNCS_START(kexec_modify_return_ids)
208+
BTF_ID_FLAGS(func, bpf_handle_pefile, KF_SLEEPABLE)
209+
BTF_ID_FLAGS(func, bpf_post_handle_pefile, KF_SLEEPABLE)
210+
BTF_KFUNCS_END(kexec_modify_return_ids)
211+
212+
static const struct btf_kfunc_id_set kexec_modify_return_set = {
213+
.owner = THIS_MODULE,
214+
.set = &kexec_modify_return_ids,
215+
};
216+
217+
static int __init kexec_bpf_prog_run_init(void)
218+
{
219+
return register_btf_fmodret_id_set(&kexec_modify_return_set);
220+
}
221+
late_initcall(kexec_bpf_prog_run_init);
222+
162223
/*
163224
* PE file may be nested and should be unfold one by one.
164225
* Query 'kernel', 'initrd', 'cmdline' in cur_phase, as they are inputs for the
@@ -213,6 +274,9 @@ static void *pe_image_load(struct kimage *image,
213274
cmdline_start = cmdline;
214275
cmdline_sz = cmdline_len;
215276

277+
for (int i = 0; i < ARRAY_SIZE(kexec_res_listener); i++)
278+
register_carrier_listener(&kexec_res_listener[i]);
279+
216280
while (is_valid_format(linux_start, linux_sz) &&
217281
pe_has_bpf_section(linux_start, linux_sz)) {
218282
struct kexec_context context;
@@ -250,6 +314,9 @@ static void *pe_image_load(struct kimage *image,
250314
disarm_bpf_prog();
251315
}
252316

317+
for (int i = 0; i < ARRAY_SIZE(kexec_res_listener); i++)
318+
unregister_carrier_listener(kexec_res_listener[i].name);
319+
253320
/*
254321
* image's kernel_buf, initrd_buf, cmdline_buf are set. Now they should
255322
* be updated to the new content.

0 commit comments

Comments
 (0)