* [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures
@ 2025-07-23 2:20 chenyuan_fl
2025-07-23 10:24 ` Quentin Monnet
2025-07-23 13:08 ` Jiri Olsa
0 siblings, 2 replies; 16+ messages in thread
From: chenyuan_fl @ 2025-07-23 2:20 UTC (permalink / raw)
To: qmo, ast, daniel, andrii, yonghong.song; +Cc: bpf, linux-kernel, Yuan Chen
From: Yuan Chen <chenyuan@kylinos.cn>
Adjust symbol matching logic to account for Control-flow Enforcement
Technology (CET) on x86_64 systems. CET prefixes functions with
a 4-byte 'endbr' instruction, shifting the actual hook entry point to
symbol + 4.
Changed in PATCH v4:
* Refactor repeated code into a function.
* Add detection for the x86 architecture.
Changed int PATH v5:
* Remove detection for the x86 architecture.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/bpf/bpftool/link.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
index a773e05d5ade..288bf9a032a5 100644
--- a/tools/bpf/bpftool/link.c
+++ b/tools/bpf/bpftool/link.c
@@ -282,6 +282,28 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
return data;
}
+static bool
+symbol_matches_target(__u64 sym_addr, __u64 target_addr)
+{
+ if (sym_addr == target_addr)
+ return true;
+
+#if defined(__x86_64__)
+ /*
+ * On x86_64 architectures with CET (Control-flow Enforcement Technology),
+ * function entry points have a 4-byte 'endbr' instruction prefix.
+ * This causes kprobe hooks to target the address *after* 'endbr'
+ * (symbol address + 4), preserving the CET instruction.
+ * Here we check if the symbol address matches the hook target address
+ * minus 4, indicating a CET-enabled function entry point.
+ */
+ if (sym_addr == target_addr - 4)
+ return true;
+#endif
+
+ return false;
+}
+
static void
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
{
@@ -307,7 +329,7 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
goto error;
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
continue;
jsonw_start_object(json_wtr);
jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
@@ -744,7 +766,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
continue;
printf("\n\t%016lx %-16llx %s",
dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
--
2.25.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-07-23 2:20 [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
@ 2025-07-23 10:24 ` Quentin Monnet
2025-07-23 13:08 ` Jiri Olsa
1 sibling, 0 replies; 16+ messages in thread
From: Quentin Monnet @ 2025-07-23 10:24 UTC (permalink / raw)
To: chenyuan, ast, daniel, andrii, yonghong.song; +Cc: bpf, linux-kernel, Yuan Chen
Your message had a
"Reply-To: <aef2617b-ce03-4830-96a7-39df0c93aaad@kernel.org>" header, I
ignored it. I believe you meant to have In-Reply-To: instead.
2025-07-23 10:20 UTC+0800 ~ chenyuan_fl@163.com
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> Adjust symbol matching logic to account for Control-flow Enforcement
> Technology (CET) on x86_64 systems. CET prefixes functions with
> a 4-byte 'endbr' instruction, shifting the actual hook entry point to
> symbol + 4.
>
> Changed in PATCH v4:
> * Refactor repeated code into a function.
> * Add detection for the x86 architecture.
>
> Changed int PATH v5:
> * Remove detection for the x86 architecture.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
Looks good from my side, thank you!
Reviewed-by: Quentin Monnet <qmo@kernel.org>
Probably worth waiting for Yonghong's ack as well before merging this patch.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-07-23 2:20 [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
2025-07-23 10:24 ` Quentin Monnet
@ 2025-07-23 13:08 ` Jiri Olsa
2025-07-23 15:52 ` Yonghong Song
1 sibling, 1 reply; 16+ messages in thread
From: Jiri Olsa @ 2025-07-23 13:08 UTC (permalink / raw)
To: aef2617b-ce03-4830-96a7-39df0c93aaad
Cc: qmo, ast, daniel, andrii, yonghong.song, bpf, linux-kernel,
Yuan Chen
On Wed, Jul 23, 2025 at 10:20:43AM +0800, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> Adjust symbol matching logic to account for Control-flow Enforcement
> Technology (CET) on x86_64 systems. CET prefixes functions with
> a 4-byte 'endbr' instruction, shifting the actual hook entry point to
> symbol + 4.
>
> Changed in PATCH v4:
> * Refactor repeated code into a function.
> * Add detection for the x86 architecture.
>
> Changed int PATH v5:
> * Remove detection for the x86 architecture.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
> tools/bpf/bpftool/link.c | 26 ++++++++++++++++++++++++--
> 1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
> index a773e05d5ade..288bf9a032a5 100644
> --- a/tools/bpf/bpftool/link.c
> +++ b/tools/bpf/bpftool/link.c
> @@ -282,6 +282,28 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
> return data;
> }
>
> +static bool
> +symbol_matches_target(__u64 sym_addr, __u64 target_addr)
> +{
> + if (sym_addr == target_addr)
> + return true;
> +
> +#if defined(__x86_64__)
> + /*
> + * On x86_64 architectures with CET (Control-flow Enforcement Technology),
> + * function entry points have a 4-byte 'endbr' instruction prefix.
> + * This causes kprobe hooks to target the address *after* 'endbr'
> + * (symbol address + 4), preserving the CET instruction.
> + * Here we check if the symbol address matches the hook target address
> + * minus 4, indicating a CET-enabled function entry point.
> + */
> + if (sym_addr == target_addr - 4)
> + return true;
> +#endif
looks good.. perhaps it might be too much, but should we try to read
CONFIG_X86_KERNEL_IBT value and do the check based on that? there's
already some code reading options in probe_kernel_image_config
jirka
> +
> + return false;
> +}
> +
> static void
> show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> {
> @@ -307,7 +329,7 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> goto error;
>
> for (i = 0; i < dd.sym_count; i++) {
> - if (dd.sym_mapping[i].address != data[j].addr)
> + if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
> continue;
> jsonw_start_object(json_wtr);
> jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
> @@ -744,7 +766,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
>
> printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
> for (i = 0; i < dd.sym_count; i++) {
> - if (dd.sym_mapping[i].address != data[j].addr)
> + if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
> continue;
> printf("\n\t%016lx %-16llx %s",
> dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
> --
> 2.25.1
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-07-23 13:08 ` Jiri Olsa
@ 2025-07-23 15:52 ` Yonghong Song
2025-08-15 2:52 ` [PATCH 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
0 siblings, 1 reply; 16+ messages in thread
From: Yonghong Song @ 2025-07-23 15:52 UTC (permalink / raw)
To: Jiri Olsa, aef2617b-ce03-4830-96a7-39df0c93aaad
Cc: qmo, ast, daniel, andrii, bpf, linux-kernel, Yuan Chen
On 7/23/25 6:08 AM, Jiri Olsa wrote:
> On Wed, Jul 23, 2025 at 10:20:43AM +0800, chenyuan_fl@163.com wrote:
>> From: Yuan Chen <chenyuan@kylinos.cn>
>>
>> Adjust symbol matching logic to account for Control-flow Enforcement
>> Technology (CET) on x86_64 systems. CET prefixes functions with
>> a 4-byte 'endbr' instruction, shifting the actual hook entry point to
>> symbol + 4.
>>
>> Changed in PATCH v4:
>> * Refactor repeated code into a function.
>> * Add detection for the x86 architecture.
>>
>> Changed int PATH v5:
>> * Remove detection for the x86 architecture.
>>
>> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
>> ---
>> tools/bpf/bpftool/link.c | 26 ++++++++++++++++++++++++--
>> 1 file changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
>> index a773e05d5ade..288bf9a032a5 100644
>> --- a/tools/bpf/bpftool/link.c
>> +++ b/tools/bpf/bpftool/link.c
>> @@ -282,6 +282,28 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
>> return data;
>> }
>>
>> +static bool
>> +symbol_matches_target(__u64 sym_addr, __u64 target_addr)
>> +{
>> + if (sym_addr == target_addr)
>> + return true;
>> +
>> +#if defined(__x86_64__)
>> + /*
>> + * On x86_64 architectures with CET (Control-flow Enforcement Technology),
>> + * function entry points have a 4-byte 'endbr' instruction prefix.
>> + * This causes kprobe hooks to target the address *after* 'endbr'
>> + * (symbol address + 4), preserving the CET instruction.
>> + * Here we check if the symbol address matches the hook target address
>> + * minus 4, indicating a CET-enabled function entry point.
>> + */
>> + if (sym_addr == target_addr - 4)
>> + return true;
>> +#endif
> looks good.. perhaps it might be too much, but should we try to read
> CONFIG_X86_KERNEL_IBT value and do the check based on that? there's
> already some code reading options in probe_kernel_image_config
Sounds a good idea. Maybe we can abstract out a helper function
based on probe_kernel_image_config() so it can be used in
both probe_kernel_image_config() and for this symbol_matches_target
case. We can have a variable like 'ibt_supported = ...' outside
the loop. In the above we can do
if (ibt_supported && sym_addr == target_addr - 4)
return true;
>
> jirka
>
>> +
>> + return false;
>> +}
>> +
>> static void
>> show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
>> {
>> @@ -307,7 +329,7 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
>> goto error;
>>
>> for (i = 0; i < dd.sym_count; i++) {
>> - if (dd.sym_mapping[i].address != data[j].addr)
>> + if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
>> continue;
>> jsonw_start_object(json_wtr);
>> jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
>> @@ -744,7 +766,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
>>
>> printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
>> for (i = 0; i < dd.sym_count; i++) {
>> - if (dd.sym_mapping[i].address != data[j].addr)
>> + if (!symbol_matches_target(dd.sym_mapping[i].address, data[j].addr))
>> continue;
>> printf("\n\t%016lx %-16llx %s",
>> dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
>> --
>> 2.25.1
>>
>>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 0/2] bpftool: Refactor config parsing and add CET symbol matching
2025-07-23 15:52 ` Yonghong Song
@ 2025-08-15 2:52 ` chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
0 siblings, 2 replies; 16+ messages in thread
From: chenyuan_fl @ 2025-08-15 2:52 UTC (permalink / raw)
To: yonghong.song, olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
daniel, linux-kernel, qmo
From: Yuan CHen <chenyuan@kylinos.cn>
1. **Refactor kernel config parsing**
- Moves duplicate config file handling from feature.c to common.c
- Keeps all existing functionality while enabling code reuse
2. **Add CET-aware symbol matching**
- Adjusts kprobe hook detection for x86_64 CET (endbr32/64 prefixes)
- Matches symbols at both original and CET-adjusted addresses
Changed in PATCH v4:
* Refactor repeated code into a function.
* Add detection for the x86 architecture.
Changed int PATH v5:
* Remove detection for the x86 architecture.
Changed in PATCH v6:
* Add new helper patch (1/2) to refactor kernel config reading
* Use the new read_kernel_config() in CET symbol matching (2/2) to check CONFIG_X86_KERNEL_IBT
Yuan Chen (2):
bpftool: Refactor kernel config reading into common helper
bpftool: Add CET-aware symbol matching for x86_64 architectures
tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/feature.c | 86 ++--------------------------------
tools/bpf/bpftool/link.c | 38 ++++++++++++++-
tools/bpf/bpftool/main.h | 9 ++++
4 files changed, 142 insertions(+), 84 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v6 1/2] bpftool: Refactor kernel config reading into common helper
2025-08-15 2:52 ` [PATCH 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
@ 2025-08-15 2:52 ` chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
1 sibling, 0 replies; 16+ messages in thread
From: chenyuan_fl @ 2025-08-15 2:52 UTC (permalink / raw)
To: yonghong.song, olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
daniel, linux-kernel, qmo
From: Yuan Chen <chenyuan@kylinos.cn>
Extract the kernel configuration file parsing logic from feature.c into
a new read_kernel_config() function in common.c. This includes:
1. Moving the config file handling and option parsing code
2. Adding required headers and struct definition
3. Keeping all existing functionality
The refactoring enables sharing this logic with other components while
maintaining current behavior. This will be used by subsequent patches
that need to check kernel config options.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/feature.c | 86 ++--------------------------------
tools/bpf/bpftool/main.h | 9 ++++
3 files changed, 106 insertions(+), 82 deletions(-)
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index b07317d2842f..e8daf963ecef 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -21,6 +21,7 @@
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/vfs.h>
+#include <sys/utsname.h>
#include <linux/filter.h>
#include <linux/limits.h>
@@ -31,6 +32,7 @@
#include <bpf/hashmap.h>
#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
#include <bpf/btf.h>
+#include <zlib.h>
#include "main.h"
@@ -1208,3 +1210,94 @@ int pathname_concat(char *buf, int buf_sz, const char *path,
return 0;
}
+
+static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
+ char **value)
+{
+ char *sep;
+
+ while (gzgets(file, buf, n)) {
+ if (strncmp(buf, "CONFIG_", 7))
+ continue;
+
+ sep = strchr(buf, '=');
+ if (!sep)
+ continue;
+
+ /* Trim ending '\n' */
+ buf[strlen(buf) - 1] = '\0';
+
+ /* Split on '=' and ensure that a value is present. */
+ *sep = '\0';
+ if (!sep[1])
+ continue;
+
+ *value = sep + 1;
+ return true;
+ }
+
+ return false;
+}
+
+int read_kernel_config(const struct kernel_config_option *requested_options,
+ size_t num_options, char **out_values,
+ const char *define_prefix)
+{
+ struct utsname utsn;
+ char path[PATH_MAX];
+ gzFile file = NULL;
+ char buf[4096];
+ char *value;
+ size_t i;
+ int ret = 0;
+
+ if (!requested_options || !out_values || num_options == 0)
+ return -1;
+
+ if (!uname(&utsn)) {
+ snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
+
+ /* gzopen also accepts uncompressed files. */
+ file = gzopen(path, "r");
+ }
+
+ if (!file) {
+ /* Some distributions build with CONFIG_IKCONFIG=y and put the
+ * config file at /proc/config.gz.
+ */
+ file = gzopen("/proc/config.gz", "r");
+ }
+
+ if (!file) {
+ p_info("skipping kernel config, can't open file: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!gzgets(file, buf, sizeof(buf)) || !gzgets(file, buf, sizeof(buf))) {
+ p_info("skipping kernel config, can't read from file: %s",
+ strerror(errno));
+ ret = -1;
+ goto end_parse;
+ }
+
+ if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
+ p_info("skipping kernel config, can't find correct file");
+ ret = -1;
+ goto end_parse;
+ }
+
+ while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
+ for (i = 0; i < num_options; i++) {
+ if ((define_prefix && !requested_options[i].macro_dump) ||
+ out_values[i] || strcmp(buf, requested_options[i].name))
+ continue;
+
+ out_values[i] = strdup(value);
+ }
+ }
+
+end_parse:
+ gzclose(file);
+ return ret;
+}
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 24fecdf8e430..0f6070a0c8e7 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -10,7 +10,6 @@
#ifdef USE_LIBCAP
#include <sys/capability.h>
#endif
-#include <sys/utsname.h>
#include <sys/vfs.h>
#include <linux/filter.h>
@@ -18,7 +17,6 @@
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
-#include <zlib.h>
#include "main.h"
@@ -327,40 +325,9 @@ static void probe_jit_limit(void)
}
}
-static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
- char **value)
-{
- char *sep;
-
- while (gzgets(file, buf, n)) {
- if (strncmp(buf, "CONFIG_", 7))
- continue;
-
- sep = strchr(buf, '=');
- if (!sep)
- continue;
-
- /* Trim ending '\n' */
- buf[strlen(buf) - 1] = '\0';
-
- /* Split on '=' and ensure that a value is present. */
- *sep = '\0';
- if (!sep[1])
- continue;
-
- *value = sep + 1;
- return true;
- }
-
- return false;
-}
-
static void probe_kernel_image_config(const char *define_prefix)
{
- static const struct {
- const char * const name;
- bool macro_dump;
- } options[] = {
+ struct kernel_config_option options[] = {
/* Enable BPF */
{ "CONFIG_BPF", },
/* Enable bpf() syscall */
@@ -435,52 +402,11 @@ static void probe_kernel_image_config(const char *define_prefix)
{ "CONFIG_HZ", true, }
};
char *values[ARRAY_SIZE(options)] = { };
- struct utsname utsn;
- char path[PATH_MAX];
- gzFile file = NULL;
- char buf[4096];
- char *value;
size_t i;
- if (!uname(&utsn)) {
- snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
-
- /* gzopen also accepts uncompressed files. */
- file = gzopen(path, "r");
- }
-
- if (!file) {
- /* Some distributions build with CONFIG_IKCONFIG=y and put the
- * config file at /proc/config.gz.
- */
- file = gzopen("/proc/config.gz", "r");
- }
- if (!file) {
- p_info("skipping kernel config, can't open file: %s",
- strerror(errno));
- goto end_parse;
- }
- /* Sanity checks */
- if (!gzgets(file, buf, sizeof(buf)) ||
- !gzgets(file, buf, sizeof(buf))) {
- p_info("skipping kernel config, can't read from file: %s",
- strerror(errno));
- goto end_parse;
- }
- if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
- p_info("skipping kernel config, can't find correct file");
- goto end_parse;
- }
-
- while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
- for (i = 0; i < ARRAY_SIZE(options); i++) {
- if ((define_prefix && !options[i].macro_dump) ||
- values[i] || strcmp(buf, options[i].name))
- continue;
-
- values[i] = strdup(value);
- }
- }
+ if (read_kernel_config(options, ARRAY_SIZE(options), values,
+ define_prefix))
+ return;
for (i = 0; i < ARRAY_SIZE(options); i++) {
if (define_prefix && !options[i].macro_dump)
@@ -488,10 +414,6 @@ static void probe_kernel_image_config(const char *define_prefix)
print_kernel_option(options[i].name, values[i], define_prefix);
free(values[i]);
}
-
-end_parse:
- if (file)
- gzclose(file);
}
static bool probe_bpf_syscall(const char *define_prefix)
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index a2bb0714b3d6..374cac2a8c66 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -275,4 +275,13 @@ int pathname_concat(char *buf, int buf_sz, const char *path,
/* print netfilter bpf_link info */
void netfilter_dump_plain(const struct bpf_link_info *info);
void netfilter_dump_json(const struct bpf_link_info *info, json_writer_t *wtr);
+
+struct kernel_config_option {
+ const char *name;
+ bool macro_dump;
+};
+
+int read_kernel_config(const struct kernel_config_option *requested_options,
+ size_t num_options, char **out_values,
+ const char *define_prefix);
#endif
--
2.39.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-08-15 2:52 ` [PATCH 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
@ 2025-08-15 2:52 ` chenyuan_fl
2025-08-18 9:55 ` Jiri Olsa
1 sibling, 1 reply; 16+ messages in thread
From: chenyuan_fl @ 2025-08-15 2:52 UTC (permalink / raw)
To: yonghong.song, olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
daniel, linux-kernel, qmo
From: Yuan Chen <chenyuan@kylinos.cn>
Adjust symbol matching logic to account for Control-flow Enforcement
Technology (CET) on x86_64 systems. CET prefixes functions with
a 4-byte 'endbr' instruction, shifting the actual hook entry point to
symbol + 4.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/bpf/bpftool/link.c | 50 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
index a773e05d5ade..6787971d3167 100644
--- a/tools/bpf/bpftool/link.c
+++ b/tools/bpf/bpftool/link.c
@@ -282,11 +282,52 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
return data;
}
+static bool is_x86_ibt_enabled(void)
+{
+#if defined(__x86_64__)
+ struct kernel_config_option options[] = {
+ { "CONFIG_X86_KERNEL_IBT", },
+ };
+ char *values[ARRAY_SIZE(options)] = { };
+ bool ret;
+
+ if (read_kernel_config(options, ARRAY_SIZE(options), values, NULL))
+ return false;
+
+ ret = !!values[0];
+ free(values[0]);
+ return ret;
+#else
+ return false;
+#endif
+}
+
+static bool
+symbol_matches_target(__u64 sym_addr, __u64 target_addr, bool is_ibt_enabled)
+{
+ if (sym_addr == target_addr)
+ return true;
+
+ /*
+ * On x86_64 architectures with CET (Control-flow Enforcement Technology),
+ * function entry points have a 4-byte 'endbr' instruction prefix.
+ * This causes kprobe hooks to target the address *after* 'endbr'
+ * (symbol address + 4), preserving the CET instruction.
+ * Here we check if the symbol address matches the hook target address
+ * minus 4, indicating a CET-enabled function entry point.
+ */
+ if (is_ibt_enabled && sym_addr == target_addr - 4)
+ return true;
+
+ return false;
+}
+
static void
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
{
struct addr_cookie *data;
__u32 i, j = 0;
+ bool is_ibt_enabled;
jsonw_bool_field(json_wtr, "retprobe",
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
@@ -306,8 +347,10 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
if (!dd.sym_count)
goto error;
+ is_ibt_enabled = is_x86_ibt_enabled();
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address,
+ data[j].addr, is_ibt_enabled))
continue;
jsonw_start_object(json_wtr);
jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
@@ -719,6 +762,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
{
struct addr_cookie *data;
__u32 i, j = 0;
+ bool is_ibt_enabled;
if (!info->kprobe_multi.count)
return;
@@ -742,9 +786,11 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
if (!dd.sym_count)
goto error;
+ is_ibt_enabled = is_x86_ibt_enabled();
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address,
+ data[j].addr, is_ibt_enabled))
continue;
printf("\n\t%016lx %-16llx %s",
dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
--
2.39.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-08-15 2:52 ` [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
@ 2025-08-18 9:55 ` Jiri Olsa
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
0 siblings, 1 reply; 16+ messages in thread
From: Jiri Olsa @ 2025-08-18 9:55 UTC (permalink / raw)
To: chenyuan_fl
Cc: yonghong.song, olsajiri, aef2617b-ce03-4830-96a7-39df0c93aaad,
andrii, ast, bpf, chenyuan, daniel, linux-kernel, qmo
On Fri, Aug 15, 2025 at 03:52:27AM +0100, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> Adjust symbol matching logic to account for Control-flow Enforcement
> Technology (CET) on x86_64 systems. CET prefixes functions with
> a 4-byte 'endbr' instruction, shifting the actual hook entry point to
> symbol + 4.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
> tools/bpf/bpftool/link.c | 50 ++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 48 insertions(+), 2 deletions(-)
>
> diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
> index a773e05d5ade..6787971d3167 100644
> --- a/tools/bpf/bpftool/link.c
> +++ b/tools/bpf/bpftool/link.c
> @@ -282,11 +282,52 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
> return data;
> }
>
> +static bool is_x86_ibt_enabled(void)
> +{
> +#if defined(__x86_64__)
> + struct kernel_config_option options[] = {
> + { "CONFIG_X86_KERNEL_IBT", },
> + };
> + char *values[ARRAY_SIZE(options)] = { };
> + bool ret;
> +
> + if (read_kernel_config(options, ARRAY_SIZE(options), values, NULL))
> + return false;
> +
> + ret = !!values[0];
> + free(values[0]);
> + return ret;
> +#else
> + return false;
> +#endif
nit, we could store the result to 'static bool enabled' in this function,
so we would not need to pass is_ibt_enabled arg below, and just call
is_x86_ibt_enabled directly, but up to you
> +}
> +
> +static bool
> +symbol_matches_target(__u64 sym_addr, __u64 target_addr, bool is_ibt_enabled)
> +{
> + if (sym_addr == target_addr)
> + return true;
> +
> + /*
> + * On x86_64 architectures with CET (Control-flow Enforcement Technology),
> + * function entry points have a 4-byte 'endbr' instruction prefix.
> + * This causes kprobe hooks to target the address *after* 'endbr'
> + * (symbol address + 4), preserving the CET instruction.
> + * Here we check if the symbol address matches the hook target address
> + * minus 4, indicating a CET-enabled function entry point.
> + */
> + if (is_ibt_enabled && sym_addr == target_addr - 4)
> + return true;
> +
> + return false;
> +}
> +
> static void
> show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> {
> struct addr_cookie *data;
> __u32 i, j = 0;
> + bool is_ibt_enabled;
>
> jsonw_bool_field(json_wtr, "retprobe",
> info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
> @@ -306,8 +347,10 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> if (!dd.sym_count)
> goto error;
>
> + is_ibt_enabled = is_x86_ibt_enabled();
> for (i = 0; i < dd.sym_count; i++) {
> - if (dd.sym_mapping[i].address != data[j].addr)
> + if (!symbol_matches_target(dd.sym_mapping[i].address,
> + data[j].addr, is_ibt_enabled))
> continue;
> jsonw_start_object(json_wtr);
> jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
> @@ -719,6 +762,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
> {
> struct addr_cookie *data;
> __u32 i, j = 0;
> + bool is_ibt_enabled;
>
> if (!info->kprobe_multi.count)
> return;
> @@ -742,9 +786,11 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
> if (!dd.sym_count)
> goto error;
>
> + is_ibt_enabled = is_x86_ibt_enabled();
> printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
> for (i = 0; i < dd.sym_count; i++) {
> - if (dd.sym_mapping[i].address != data[j].addr)
> + if (!symbol_matches_target(dd.sym_mapping[i].address,
> + data[j].addr, is_ibt_enabled))
> continue;
> printf("\n\t%016lx %-16llx %s",
> dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
I wonder should we display the kprobe attached address instead of symbol
address in here
otherwise the patchset lgtm
thanks,
jirka
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching
2025-08-18 9:55 ` Jiri Olsa
@ 2025-08-25 2:20 ` chenyuan_fl
2025-08-25 2:20 ` [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
` (3 more replies)
0 siblings, 4 replies; 16+ messages in thread
From: chenyuan_fl @ 2025-08-25 2:20 UTC (permalink / raw)
To: olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
chenyuan_fl, daniel, linux-kernel, qmo, yonghong.song
From: Yuan CHen <chenyuan@kylinos.cn>
1. **Refactor kernel config parsing**
- Moves duplicate config file handling from feature.c to common.c
- Keeps all existing functionality while enabling code reuse
2. **Add CET-aware symbol matching**
- Adjusts kprobe hook detection for x86_64 CET (endbr32/64 prefixes)
- Matches symbols at both original and CET-adjusted addresses
Changed in PATCH v4:
* Refactor repeated code into a function.
* Add detection for the x86 architecture.
Changed int PATH v5:
* Remove detection for the x86 architecture.
Changed in PATCH v6:
* Add new helper patch (1/2) to refactor kernel config reading
* Use the new read_kernel_config() in CET symbol matching (2/2) to check CONFIG_X86_KERNEL_IBT
Changed in PATCH v7:
* Display actual kprobe attachment addresses instead of symbol addresses
Yuan Chen (2):
bpftool: Refactor kernel config reading into common helper
bpftool: Add CET-aware symbol matching for x86_64 architectures
tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/feature.c | 86 ++--------------------------------
tools/bpf/bpftool/link.c | 38 ++++++++++++++-
tools/bpf/bpftool/main.h | 9 ++++
4 files changed, 142 insertions(+), 84 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
@ 2025-08-25 2:20 ` chenyuan_fl
2025-08-25 20:29 ` Yonghong Song
2025-08-25 2:20 ` [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
` (2 subsequent siblings)
3 siblings, 1 reply; 16+ messages in thread
From: chenyuan_fl @ 2025-08-25 2:20 UTC (permalink / raw)
To: olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
chenyuan_fl, daniel, linux-kernel, qmo, yonghong.song
From: Yuan Chen <chenyuan@kylinos.cn>
Extract the kernel configuration file parsing logic from feature.c into
a new read_kernel_config() function in common.c. This includes:
1. Moving the config file handling and option parsing code
2. Adding required headers and struct definition
3. Keeping all existing functionality
The refactoring enables sharing this logic with other components while
maintaining current behavior. This will be used by subsequent patches
that need to check kernel config options.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
tools/bpf/bpftool/feature.c | 86 ++--------------------------------
tools/bpf/bpftool/main.h | 9 ++++
3 files changed, 106 insertions(+), 82 deletions(-)
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index b07317d2842f..e8daf963ecef 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -21,6 +21,7 @@
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/vfs.h>
+#include <sys/utsname.h>
#include <linux/filter.h>
#include <linux/limits.h>
@@ -31,6 +32,7 @@
#include <bpf/hashmap.h>
#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
#include <bpf/btf.h>
+#include <zlib.h>
#include "main.h"
@@ -1208,3 +1210,94 @@ int pathname_concat(char *buf, int buf_sz, const char *path,
return 0;
}
+
+static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
+ char **value)
+{
+ char *sep;
+
+ while (gzgets(file, buf, n)) {
+ if (strncmp(buf, "CONFIG_", 7))
+ continue;
+
+ sep = strchr(buf, '=');
+ if (!sep)
+ continue;
+
+ /* Trim ending '\n' */
+ buf[strlen(buf) - 1] = '\0';
+
+ /* Split on '=' and ensure that a value is present. */
+ *sep = '\0';
+ if (!sep[1])
+ continue;
+
+ *value = sep + 1;
+ return true;
+ }
+
+ return false;
+}
+
+int read_kernel_config(const struct kernel_config_option *requested_options,
+ size_t num_options, char **out_values,
+ const char *define_prefix)
+{
+ struct utsname utsn;
+ char path[PATH_MAX];
+ gzFile file = NULL;
+ char buf[4096];
+ char *value;
+ size_t i;
+ int ret = 0;
+
+ if (!requested_options || !out_values || num_options == 0)
+ return -1;
+
+ if (!uname(&utsn)) {
+ snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
+
+ /* gzopen also accepts uncompressed files. */
+ file = gzopen(path, "r");
+ }
+
+ if (!file) {
+ /* Some distributions build with CONFIG_IKCONFIG=y and put the
+ * config file at /proc/config.gz.
+ */
+ file = gzopen("/proc/config.gz", "r");
+ }
+
+ if (!file) {
+ p_info("skipping kernel config, can't open file: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!gzgets(file, buf, sizeof(buf)) || !gzgets(file, buf, sizeof(buf))) {
+ p_info("skipping kernel config, can't read from file: %s",
+ strerror(errno));
+ ret = -1;
+ goto end_parse;
+ }
+
+ if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
+ p_info("skipping kernel config, can't find correct file");
+ ret = -1;
+ goto end_parse;
+ }
+
+ while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
+ for (i = 0; i < num_options; i++) {
+ if ((define_prefix && !requested_options[i].macro_dump) ||
+ out_values[i] || strcmp(buf, requested_options[i].name))
+ continue;
+
+ out_values[i] = strdup(value);
+ }
+ }
+
+end_parse:
+ gzclose(file);
+ return ret;
+}
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 24fecdf8e430..0f6070a0c8e7 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -10,7 +10,6 @@
#ifdef USE_LIBCAP
#include <sys/capability.h>
#endif
-#include <sys/utsname.h>
#include <sys/vfs.h>
#include <linux/filter.h>
@@ -18,7 +17,6 @@
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
-#include <zlib.h>
#include "main.h"
@@ -327,40 +325,9 @@ static void probe_jit_limit(void)
}
}
-static bool read_next_kernel_config_option(gzFile file, char *buf, size_t n,
- char **value)
-{
- char *sep;
-
- while (gzgets(file, buf, n)) {
- if (strncmp(buf, "CONFIG_", 7))
- continue;
-
- sep = strchr(buf, '=');
- if (!sep)
- continue;
-
- /* Trim ending '\n' */
- buf[strlen(buf) - 1] = '\0';
-
- /* Split on '=' and ensure that a value is present. */
- *sep = '\0';
- if (!sep[1])
- continue;
-
- *value = sep + 1;
- return true;
- }
-
- return false;
-}
-
static void probe_kernel_image_config(const char *define_prefix)
{
- static const struct {
- const char * const name;
- bool macro_dump;
- } options[] = {
+ struct kernel_config_option options[] = {
/* Enable BPF */
{ "CONFIG_BPF", },
/* Enable bpf() syscall */
@@ -435,52 +402,11 @@ static void probe_kernel_image_config(const char *define_prefix)
{ "CONFIG_HZ", true, }
};
char *values[ARRAY_SIZE(options)] = { };
- struct utsname utsn;
- char path[PATH_MAX];
- gzFile file = NULL;
- char buf[4096];
- char *value;
size_t i;
- if (!uname(&utsn)) {
- snprintf(path, sizeof(path), "/boot/config-%s", utsn.release);
-
- /* gzopen also accepts uncompressed files. */
- file = gzopen(path, "r");
- }
-
- if (!file) {
- /* Some distributions build with CONFIG_IKCONFIG=y and put the
- * config file at /proc/config.gz.
- */
- file = gzopen("/proc/config.gz", "r");
- }
- if (!file) {
- p_info("skipping kernel config, can't open file: %s",
- strerror(errno));
- goto end_parse;
- }
- /* Sanity checks */
- if (!gzgets(file, buf, sizeof(buf)) ||
- !gzgets(file, buf, sizeof(buf))) {
- p_info("skipping kernel config, can't read from file: %s",
- strerror(errno));
- goto end_parse;
- }
- if (strcmp(buf, "# Automatically generated file; DO NOT EDIT.\n")) {
- p_info("skipping kernel config, can't find correct file");
- goto end_parse;
- }
-
- while (read_next_kernel_config_option(file, buf, sizeof(buf), &value)) {
- for (i = 0; i < ARRAY_SIZE(options); i++) {
- if ((define_prefix && !options[i].macro_dump) ||
- values[i] || strcmp(buf, options[i].name))
- continue;
-
- values[i] = strdup(value);
- }
- }
+ if (read_kernel_config(options, ARRAY_SIZE(options), values,
+ define_prefix))
+ return;
for (i = 0; i < ARRAY_SIZE(options); i++) {
if (define_prefix && !options[i].macro_dump)
@@ -488,10 +414,6 @@ static void probe_kernel_image_config(const char *define_prefix)
print_kernel_option(options[i].name, values[i], define_prefix);
free(values[i]);
}
-
-end_parse:
- if (file)
- gzclose(file);
}
static bool probe_bpf_syscall(const char *define_prefix)
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
index a2bb0714b3d6..374cac2a8c66 100644
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -275,4 +275,13 @@ int pathname_concat(char *buf, int buf_sz, const char *path,
/* print netfilter bpf_link info */
void netfilter_dump_plain(const struct bpf_link_info *info);
void netfilter_dump_json(const struct bpf_link_info *info, json_writer_t *wtr);
+
+struct kernel_config_option {
+ const char *name;
+ bool macro_dump;
+};
+
+int read_kernel_config(const struct kernel_config_option *requested_options,
+ size_t num_options, char **out_values,
+ const char *define_prefix);
#endif
--
2.39.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
2025-08-25 2:20 ` [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
@ 2025-08-25 2:20 ` chenyuan_fl
2025-08-25 20:39 ` Yonghong Song
2025-08-25 22:44 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching Jiri Olsa
2025-08-27 21:53 ` Andrii Nakryiko
3 siblings, 1 reply; 16+ messages in thread
From: chenyuan_fl @ 2025-08-25 2:20 UTC (permalink / raw)
To: olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
chenyuan_fl, daniel, linux-kernel, qmo, yonghong.song
From: Yuan Chen <chenyuan@kylinos.cn>
Adjust symbol matching logic to account for Control-flow Enforcement
Technology (CET) on x86_64 systems. CET prefixes functions with
a 4-byte 'endbr' instruction, shifting the actual hook entry point to
symbol + 4.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/bpf/bpftool/link.c | 54 +++++++++++++++++++++++++++++++++++++---
1 file changed, 50 insertions(+), 4 deletions(-)
diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
index a773e05d5ade..bdcd717b0348 100644
--- a/tools/bpf/bpftool/link.c
+++ b/tools/bpf/bpftool/link.c
@@ -282,11 +282,52 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
return data;
}
+static bool is_x86_ibt_enabled(void)
+{
+#if defined(__x86_64__)
+ struct kernel_config_option options[] = {
+ { "CONFIG_X86_KERNEL_IBT", },
+ };
+ char *values[ARRAY_SIZE(options)] = { };
+ bool ret;
+
+ if (read_kernel_config(options, ARRAY_SIZE(options), values, NULL))
+ return false;
+
+ ret = !!values[0];
+ free(values[0]);
+ return ret;
+#else
+ return false;
+#endif
+}
+
+static bool
+symbol_matches_target(__u64 sym_addr, __u64 target_addr, bool is_ibt_enabled)
+{
+ if (sym_addr == target_addr)
+ return true;
+
+ /*
+ * On x86_64 architectures with CET (Control-flow Enforcement Technology),
+ * function entry points have a 4-byte 'endbr' instruction prefix.
+ * This causes kprobe hooks to target the address *after* 'endbr'
+ * (symbol address + 4), preserving the CET instruction.
+ * Here we check if the symbol address matches the hook target address
+ * minus 4, indicating a CET-enabled function entry point.
+ */
+ if (is_ibt_enabled && sym_addr == target_addr - 4)
+ return true;
+
+ return false;
+}
+
static void
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
{
struct addr_cookie *data;
__u32 i, j = 0;
+ bool is_ibt_enabled;
jsonw_bool_field(json_wtr, "retprobe",
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
@@ -306,11 +347,13 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
if (!dd.sym_count)
goto error;
+ is_ibt_enabled = is_x86_ibt_enabled();
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address,
+ data[j].addr, is_ibt_enabled))
continue;
jsonw_start_object(json_wtr);
- jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
+ jsonw_uint_field(json_wtr, "addr", (unsigned long)data[j].addr);
jsonw_string_field(json_wtr, "func", dd.sym_mapping[i].name);
/* Print null if it is vmlinux */
if (dd.sym_mapping[i].module[0] == '\0') {
@@ -719,6 +762,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
{
struct addr_cookie *data;
__u32 i, j = 0;
+ bool is_ibt_enabled;
if (!info->kprobe_multi.count)
return;
@@ -742,12 +786,14 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
if (!dd.sym_count)
goto error;
+ is_ibt_enabled = is_x86_ibt_enabled();
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
for (i = 0; i < dd.sym_count; i++) {
- if (dd.sym_mapping[i].address != data[j].addr)
+ if (!symbol_matches_target(dd.sym_mapping[i].address,
+ data[j].addr, is_ibt_enabled))
continue;
printf("\n\t%016lx %-16llx %s",
- dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
+ (unsigned long)data[j].addr, data[j].cookie, dd.sym_mapping[i].name);
if (dd.sym_mapping[i].module[0] != '\0')
printf(" [%s] ", dd.sym_mapping[i].module);
else
--
2.39.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper
2025-08-25 2:20 ` [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
@ 2025-08-25 20:29 ` Yonghong Song
0 siblings, 0 replies; 16+ messages in thread
From: Yonghong Song @ 2025-08-25 20:29 UTC (permalink / raw)
To: chenyuan_fl, olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
daniel, linux-kernel, qmo
On 8/24/25 7:20 PM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> Extract the kernel configuration file parsing logic from feature.c into
> a new read_kernel_config() function in common.c. This includes:
>
> 1. Moving the config file handling and option parsing code
> 2. Adding required headers and struct definition
> 3. Keeping all existing functionality
>
> The refactoring enables sharing this logic with other components while
> maintaining current behavior. This will be used by subsequent patches
> that need to check kernel config options.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures
2025-08-25 2:20 ` [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
@ 2025-08-25 20:39 ` Yonghong Song
0 siblings, 0 replies; 16+ messages in thread
From: Yonghong Song @ 2025-08-25 20:39 UTC (permalink / raw)
To: chenyuan_fl, olsajiri
Cc: aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf, chenyuan,
daniel, linux-kernel, qmo
On 8/24/25 7:20 PM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> Adjust symbol matching logic to account for Control-flow Enforcement
> Technology (CET) on x86_64 systems. CET prefixes functions with
> a 4-byte 'endbr' instruction, shifting the actual hook entry point to
> symbol + 4.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
2025-08-25 2:20 ` [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
2025-08-25 2:20 ` [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
@ 2025-08-25 22:44 ` Jiri Olsa
2025-08-27 21:53 ` Andrii Nakryiko
3 siblings, 0 replies; 16+ messages in thread
From: Jiri Olsa @ 2025-08-25 22:44 UTC (permalink / raw)
To: chenyuan_fl
Cc: olsajiri, aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf,
chenyuan, daniel, linux-kernel, qmo, yonghong.song
On Mon, Aug 25, 2025 at 03:20:00AM +0100, chenyuan_fl@163.com wrote:
> From: Yuan CHen <chenyuan@kylinos.cn>
>
> 1. **Refactor kernel config parsing**
> - Moves duplicate config file handling from feature.c to common.c
> - Keeps all existing functionality while enabling code reuse
>
> 2. **Add CET-aware symbol matching**
> - Adjusts kprobe hook detection for x86_64 CET (endbr32/64 prefixes)
> - Matches symbols at both original and CET-adjusted addresses
>
> Changed in PATCH v4:
> * Refactor repeated code into a function.
> * Add detection for the x86 architecture.
>
> Changed int PATH v5:
> * Remove detection for the x86 architecture.
>
> Changed in PATCH v6:
> * Add new helper patch (1/2) to refactor kernel config reading
> * Use the new read_kernel_config() in CET symbol matching (2/2) to check CONFIG_X86_KERNEL_IBT
>
> Changed in PATCH v7:
> * Display actual kprobe attachment addresses instead of symbol addresses
Acked-by: Jiri Olsa <jolsa@kernel.org>
thanks,
jirka
>
> Yuan Chen (2):
> bpftool: Refactor kernel config reading into common helper
> bpftool: Add CET-aware symbol matching for x86_64 architectures
>
> tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
> tools/bpf/bpftool/feature.c | 86 ++--------------------------------
> tools/bpf/bpftool/link.c | 38 ++++++++++++++-
> tools/bpf/bpftool/main.h | 9 ++++
> 4 files changed, 142 insertions(+), 84 deletions(-)
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
` (2 preceding siblings ...)
2025-08-25 22:44 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching Jiri Olsa
@ 2025-08-27 21:53 ` Andrii Nakryiko
2025-08-28 21:50 ` Quentin Monnet
3 siblings, 1 reply; 16+ messages in thread
From: Andrii Nakryiko @ 2025-08-27 21:53 UTC (permalink / raw)
To: chenyuan_fl, Quentin Monnet
Cc: olsajiri, aef2617b-ce03-4830-96a7-39df0c93aaad, andrii, ast, bpf,
chenyuan, daniel, linux-kernel, yonghong.song
On Sun, Aug 24, 2025 at 7:20 PM <chenyuan_fl@163.com> wrote:
>
> From: Yuan CHen <chenyuan@kylinos.cn>
>
> 1. **Refactor kernel config parsing**
> - Moves duplicate config file handling from feature.c to common.c
> - Keeps all existing functionality while enabling code reuse
>
> 2. **Add CET-aware symbol matching**
> - Adjusts kprobe hook detection for x86_64 CET (endbr32/64 prefixes)
> - Matches symbols at both original and CET-adjusted addresses
>
Quentin, can you please take a quick look at this patch set, when you
get a chance? Thanks!
> Changed in PATCH v4:
> * Refactor repeated code into a function.
> * Add detection for the x86 architecture.
>
> Changed int PATH v5:
> * Remove detection for the x86 architecture.
>
> Changed in PATCH v6:
> * Add new helper patch (1/2) to refactor kernel config reading
> * Use the new read_kernel_config() in CET symbol matching (2/2) to check CONFIG_X86_KERNEL_IBT
>
> Changed in PATCH v7:
> * Display actual kprobe attachment addresses instead of symbol addresses
>
> Yuan Chen (2):
> bpftool: Refactor kernel config reading into common helper
> bpftool: Add CET-aware symbol matching for x86_64 architectures
>
> tools/bpf/bpftool/common.c | 93 +++++++++++++++++++++++++++++++++++++
> tools/bpf/bpftool/feature.c | 86 ++--------------------------------
> tools/bpf/bpftool/link.c | 38 ++++++++++++++-
> tools/bpf/bpftool/main.h | 9 ++++
> 4 files changed, 142 insertions(+), 84 deletions(-)
>
> --
> 2.39.5
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching
2025-08-27 21:53 ` Andrii Nakryiko
@ 2025-08-28 21:50 ` Quentin Monnet
0 siblings, 0 replies; 16+ messages in thread
From: Quentin Monnet @ 2025-08-28 21:50 UTC (permalink / raw)
To: Andrii Nakryiko, chenyuan_fl
Cc: olsajiri, andrii, ast, bpf, chenyuan, daniel, linux-kernel,
yonghong.song
2025-08-27 14:53 UTC-0700 ~ Andrii Nakryiko <andrii.nakryiko@gmail.com>
> On Sun, Aug 24, 2025 at 7:20 PM <chenyuan_fl@163.com> wrote:
>>
>> From: Yuan CHen <chenyuan@kylinos.cn>
>>
>> 1. **Refactor kernel config parsing**
>> - Moves duplicate config file handling from feature.c to common.c
>> - Keeps all existing functionality while enabling code reuse
>>
>> 2. **Add CET-aware symbol matching**
>> - Adjusts kprobe hook detection for x86_64 CET (endbr32/64 prefixes)
>> - Matches symbols at both original and CET-adjusted addresses
>>
>
> Quentin, can you please take a quick look at this patch set, when you
> get a chance? Thanks!
Yes! Both patches look good to me. For the series:
Acked-by: Quentin Monnet <qmo@kernel.org>
Thanks for this work
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-08-28 21:50 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-23 2:20 [PATCH v5] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
2025-07-23 10:24 ` Quentin Monnet
2025-07-23 13:08 ` Jiri Olsa
2025-07-23 15:52 ` Yonghong Song
2025-08-15 2:52 ` [PATCH 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
2025-08-15 2:52 ` [PATCH v6 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
2025-08-18 9:55 ` Jiri Olsa
2025-08-25 2:20 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching chenyuan_fl
2025-08-25 2:20 ` [PATCH v7 1/2] bpftool: Refactor kernel config reading into common helper chenyuan_fl
2025-08-25 20:29 ` Yonghong Song
2025-08-25 2:20 ` [PATCH v7 2/2] bpftool: Add CET-aware symbol matching for x86_64 architectures chenyuan_fl
2025-08-25 20:39 ` Yonghong Song
2025-08-25 22:44 ` [PATCH v7 0/2] bpftool: Refactor config parsing and add CET symbol matching Jiri Olsa
2025-08-27 21:53 ` Andrii Nakryiko
2025-08-28 21:50 ` Quentin Monnet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).