bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
To: bpf@vger.kernel.org
Cc: nkapron@google.com, teknoraver@meta.com,
	roberto.sassu@huawei.com, gregkh@linuxfoundation.org,
	paul@paul-moore.com, code@tyhicks.com,
	flaniel@linux.microsoft.com
Subject: [PATCH 08/14] bpf: Add elf parsing support to the BPF_LOAD_FD subcommand
Date: Thu,  9 Jan 2025 13:43:50 -0800	[thread overview]
Message-ID: <20250109214617.485144-9-bboscaccy@linux.microsoft.com> (raw)
In-Reply-To: <20250109214617.485144-1-bboscaccy@linux.microsoft.com>

Using the sysfs entry passed into the subcommand, the previosly loaded
elf object file is parsed.  The objective of this parse is to identify
key elf file sections, specfically the text and btf sections. From
there, indicies are saved to relevant sections. Armed with the initial
parse info, we search for and create program definitions, along with
any respective btf information for them.

Signed-off-by: Blaise Boscaccy <bboscaccy@linux.microsoft.com>
---
 kernel/bpf/syscall.c | 175 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3cfb497e1b236..03ab0bb7bf076 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6074,6 +6074,177 @@ skip_mods_and_typedefs(const struct btf *btf, u32 id, u32 *res_id)
 	return t;
 }
 
+static int init_btf(struct bpf_obj *obj, unsigned int btf_idx, unsigned int btf_ext_idx)
+{
+	Elf_Shdr *shdr =  &obj->sechdrs[btf_idx];
+	void *buffer = (void *)obj->hdr + shdr->sh_offset;
+	struct btf_ext_info *ext_segs[3];
+	int seg_num, sec_num;
+	int idx;
+	struct btf_ext_info *seg;
+	const struct btf_ext_info_sec *sec;
+	const char *sec_name;
+	struct btf *btf = btf_init_mem(buffer, shdr->sh_size, 0, 0, 0);
+
+	obj->btf = btf;
+	shdr = &obj->sechdrs[btf_ext_idx];
+	buffer = (void *)obj->hdr + shdr->sh_offset;
+	obj->btf_ext = btf_ext__new(buffer, shdr->sh_size);
+	obj->index.btf = btf_idx;
+	obj->index.btf_ext = btf_ext_idx;
+
+	/* setup .BTF.ext to ELF section mapping */
+	ext_segs[0] = &obj->btf_ext->func_info;
+	ext_segs[1] = &obj->btf_ext->line_info;
+	ext_segs[2] = &obj->btf_ext->core_relo_info;
+	for (seg_num = 0; seg_num < ARRAY_SIZE(ext_segs); seg_num++) {
+		seg = ext_segs[seg_num];
+
+		if (seg->sec_cnt == 0)
+			continue;
+
+		seg->sec_idxs = kcalloc(seg->sec_cnt, sizeof(*seg->sec_idxs), GFP_KERNEL);
+		if (!seg->sec_idxs)
+			return -ENOMEM;
+
+		sec_num = 0;
+		for_each_btf_ext_sec(seg, sec) {
+			/* preventively increment index to avoid doing
+			 * this before every continue below
+			 */
+			sec_num++;
+
+			sec_name = btf_str_by_offset(obj->btf, sec->sec_name_off);
+			if (str_is_empty(sec_name))
+				continue;
+
+			idx = elf_sec_idx_by_name(obj, sec_name);
+			if (idx < 0)
+				continue;
+			seg->sec_idxs[sec_num - 1] = idx;
+		}
+	}
+	return 0;
+}
+
+static int find_progs(struct bpf_obj *obj, unsigned int sec_idx)
+{
+	unsigned int i;
+	unsigned int prog_sz;
+	unsigned int sec_off;
+	Elf_Shdr *symsec = &obj->sechdrs[obj->index.sym];
+	Elf_Sym *sym = (void *)obj->hdr + symsec->sh_offset;
+	Elf_Shdr *shdr =  &obj->sechdrs[sec_idx];
+	struct bpf_prog_obj *progs;
+	int err;
+	struct bpf_insn *insns = NULL;
+	void *buffer;
+	unsigned int insn_cnt, ndx;
+	char *name;
+
+	for (i = 1; i < symsec->sh_size / sizeof(Elf_Sym); i++) {
+		name = obj->strtab + sym[i].st_name;
+
+		if (sym[i].st_shndx != sec_idx)
+			continue;
+		if (ELF64_ST_TYPE(sym[i].st_info) != STT_FUNC)
+			continue;
+
+		prog_sz = sym[i].st_size;
+		sec_off = sym[i].st_value;
+		buffer = (void *)obj->hdr + shdr->sh_offset + sec_off;
+
+		insns = kmalloc(prog_sz, GFP_KERNEL);
+		if (!insns)
+			return -ENOMEM;
+
+		memcpy(insns, buffer, prog_sz);
+		insn_cnt = prog_sz / sizeof(struct bpf_insn);
+
+		progs = krealloc_array(obj->progs, obj->nr_programs + 1,
+				       sizeof(struct bpf_prog_obj), GFP_KERNEL);
+		if (!progs) {
+			err = -ENOMEM;
+			goto free_insns;
+		}
+
+		obj->progs = progs;
+		ndx = obj->nr_programs;
+		obj->progs[ndx].insn = insns;
+		obj->progs[ndx].insn_cnt = insn_cnt;
+		obj->progs[ndx].sec_idx = sec_idx;
+		obj->progs[ndx].sec_insn_off = sec_off / sizeof(struct bpf_insn);
+		obj->progs[ndx].sec_insn_cnt = insn_cnt;
+		obj->progs[ndx].name = name;
+		obj->progs[ndx].exception_cb_idx = -1;
+		obj->nr_programs++;
+
+	}
+	return 0;
+
+free_insns:
+	kfree(insns);
+	return err;
+}
+
+static int elf_collect(struct bpf_obj *obj)
+{
+	unsigned int i;
+	Elf_Shdr *shdr, *strhdr;
+	unsigned int sym_idx;
+	unsigned int sec_idx = 0;
+	unsigned int btf_idx = 0, btf_ext_idx = 0;
+	int err = 0;
+
+	obj->sechdrs = (void *)obj->hdr + obj->hdr->e_shoff;
+	strhdr = &obj->sechdrs[obj->hdr->e_shstrndx];
+	obj->secstrings = (void *)obj->hdr + strhdr->sh_offset;
+
+	for (i = 1; i < obj->hdr->e_shnum; i++) {
+		shdr = &obj->sechdrs[i];
+		switch (shdr->sh_type) {
+		case SHT_NULL:
+		case SHT_NOBITS:
+			continue;
+		case SHT_SYMTAB:
+			sym_idx = i;
+			fallthrough;
+		default:
+			break;
+		}
+	}
+
+	obj->index.sym = sym_idx;
+	shdr = &obj->sechdrs[sym_idx];
+	obj->index.str = shdr->sh_link;
+	obj->strtab = (char *)obj->hdr + obj->sechdrs[obj->index.str].sh_offset;
+
+	for (i = 1; i < obj->hdr->e_shnum; i++) {
+		shdr = &obj->sechdrs[i];
+		sec_idx = i;
+		if (strcmp(".text", obj->secstrings + shdr->sh_name) == 0)
+			obj->index.text = sec_idx;
+
+		if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0) {
+			err = find_progs(obj, sec_idx);
+			if (err)
+				return err;
+		}
+
+		if (strcmp(".BTF", obj->secstrings + shdr->sh_name) == 0)
+			btf_idx = i;
+
+		if (strcmp(".BTF.ext", obj->secstrings + shdr->sh_name) == 0)
+			btf_ext_idx = i;
+
+		if (strcmp(".addr_space.1", obj->secstrings + shdr->sh_name) == 0)
+			obj->index.arena = sec_idx;
+	}
+
+	err = init_btf(obj, btf_idx, btf_ext_idx);
+	return err;
+}
+
 static void free_bpf_obj(struct bpf_obj *obj)
 {
 	int i;
@@ -6305,6 +6476,10 @@ static int load_fd(union bpf_attr *attr)
 	}
 	kfree(modules);
 
+	err = elf_collect(obj);
+	if (err < 0)
+		goto free;
+
 	return obj_f;
 free:
 	free_bpf_obj(obj);
-- 
2.47.1


  parent reply	other threads:[~2025-01-09 21:47 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-09 21:43 [POC][RFC][PATCH] bpf: in-kernel bpf relocations on raw elf files Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 01/14] bpf: Port prerequiste BTF handling functions from userspace Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 02/14] bpf: Add data structures for managing in-kernel eBPF relocations Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 03/14] bpf: Port .btf.ext parsing functions from userspace Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 04/14] bpf: Port elf and btf utility helper " Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 05/14] fs/kernel_read_file: Add an eBPF specifier to kernel_read_file Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 06/14] bpf: Add BPF_LOAD_FD subcommand Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 07/14] bpf: Implement BPF_LOAD_FD subcommand handler Blaise Boscaccy
2025-01-10  6:05   ` Greg KH
2025-01-10 22:41     ` Blaise Boscaccy
2025-01-11  0:41   ` kernel test robot
2025-01-09 21:43 ` Blaise Boscaccy [this message]
2025-01-09 21:43 ` [PATCH 09/14] bpf: Collect extern relocations Blaise Boscaccy
2025-01-11  1:35   ` kernel test robot
2025-01-09 21:43 ` [PATCH 10/14] bpf: Implement BTF fixup functionality Blaise Boscaccy
2025-01-11  3:19   ` kernel test robot
2025-01-09 21:43 ` [PATCH 11/14] bpf: Implement relocation collection Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 12/14] bpf: Resolve external relocations Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 13/14] bpf: Apply in-kernel bpf instruction relocations Blaise Boscaccy
2025-01-09 21:43 ` [PATCH 14/14] bpf: Augment BPF_PROG_LOAD to use in-kernel relocations Blaise Boscaccy
2025-01-10 18:40 ` [POC][RFC][PATCH] bpf: in-kernel bpf relocations on raw elf files Alexei Starovoitov
2025-01-10 23:27   ` Blaise Boscaccy
2025-01-13 17:54     ` Alexei Starovoitov
2025-01-14 18:24       ` Blaise Boscaccy
2025-01-24  5:08         ` bpf signing. " Alexei Starovoitov
2025-01-24  7:05           ` John Fastabend
2025-01-28 22:32             ` Blaise Boscaccy
2025-01-30  1:13 ` Cong Wang
2025-01-30 19:22   ` Blaise Boscaccy
2025-02-01 22:24     ` Cong Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250109214617.485144-9-bboscaccy@linux.microsoft.com \
    --to=bboscaccy@linux.microsoft.com \
    --cc=bpf@vger.kernel.org \
    --cc=code@tyhicks.com \
    --cc=flaniel@linux.microsoft.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=nkapron@google.com \
    --cc=paul@paul-moore.com \
    --cc=roberto.sassu@huawei.com \
    --cc=teknoraver@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).