tools/bpf/bpftool/link.c

Source file repositories/reference/linux-study-clean/tools/bpf/bpftool/link.c

File Facts

System
Linux kernel
Corpus path
tools/bpf/bpftool/link.c
Extension
.c
Size
34102 bytes
Lines
1299
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct addr_cookie {
	__u64 addr;
	__u64 cookie;
};

static int cmp_addr_cookie(const void *A, const void *B)
{
	const struct addr_cookie *a = A, *b = B;

	if (a->addr == b->addr)
		return 0;
	return a->addr < b->addr ? -1 : 1;
}

static struct addr_cookie *
get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
{
	struct addr_cookie *data;
	__u32 i;

	data = calloc(count, sizeof(data[0]));
	if (!data) {
		p_err("mem alloc failed");
		return NULL;
	}
	for (i = 0; i < count; i++) {
		data[i].addr = addrs[i];
		data[i].cookie = cookies[i];
	}
	qsort(data, count, sizeof(data[0]), cmp_addr_cookie);
	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);
	jsonw_uint_field(json_wtr, "func_cnt", info->kprobe_multi.count);
	jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed);
	jsonw_name(json_wtr, "funcs");
	jsonw_start_array(json_wtr);
	data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
				     u64_to_ptr(info->kprobe_multi.cookies),
				     info->kprobe_multi.count);
	if (!data)

Annotation

Implementation Notes