All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: davem@davemloft.net
Cc: daniel@iogearbox.net, andrii@kernel.org,
	john.fastabend@gmail.com, bpf@vger.kernel.org,
	kernel-team@fb.com
Subject: [PATCH v6 bpf-next 15/21] libbpf: Cleanup temp FDs when intermediate sys_bpf fails.
Date: Thu, 13 May 2021 17:36:17 -0700	[thread overview]
Message-ID: <20210514003623.28033-16-alexei.starovoitov@gmail.com> (raw)
In-Reply-To: <20210514003623.28033-1-alexei.starovoitov@gmail.com>

From: Alexei Starovoitov <ast@kernel.org>

Fix loader program to close temporary FDs when intermediate
sys_bpf command fails.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
---
 tools/lib/bpf/bpf_gen_internal.h |  1 +
 tools/lib/bpf/gen_loader.c       | 48 +++++++++++++++++++++++++++++---
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/bpf_gen_internal.h b/tools/lib/bpf/bpf_gen_internal.h
index f42a55efd559..615400391e57 100644
--- a/tools/lib/bpf/bpf_gen_internal.h
+++ b/tools/lib/bpf/bpf_gen_internal.h
@@ -15,6 +15,7 @@ struct bpf_gen {
 	void *data_cur;
 	void *insn_start;
 	void *insn_cur;
+	ssize_t cleanup_label;
 	__u32 nr_progs;
 	__u32 nr_maps;
 	int log_level;
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c
index 0fc54b1ca311..8df718a6b142 100644
--- a/tools/lib/bpf/gen_loader.c
+++ b/tools/lib/bpf/gen_loader.c
@@ -101,8 +101,36 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in
 
 void bpf_gen__init(struct bpf_gen *gen, int log_level)
 {
+	size_t stack_sz = sizeof(struct loader_stack);
+	int i;
+
 	gen->log_level = log_level;
+	/* save ctx pointer into R6 */
 	emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
+
+	/* bzero stack */
+	emit(gen, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10));
+	emit(gen, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -stack_sz));
+	emit(gen, BPF_MOV64_IMM(BPF_REG_2, stack_sz));
+	emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
+	emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
+
+	/* jump over cleanup code */
+	emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0,
+			      /* size of cleanup code below */
+			      (stack_sz / 4) * 3 + 2));
+
+	/* remember the label where all error branches will jump to */
+	gen->cleanup_label = gen->insn_cur - gen->insn_start;
+	/* emit cleanup code: close all temp FDs */
+	for (i = 0; i < stack_sz; i += 4) {
+		emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));
+		emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));
+		emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
+	}
+	/* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
+	emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
+	emit(gen, BPF_EXIT_INSN());
 }
 
 static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
@@ -187,12 +215,24 @@ static void emit_sys_bpf(struct bpf_gen *gen, int cmd, int attr, int attr_size)
 	emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
 }
 
+static bool is_simm16(__s64 value)
+{
+	return value == (__s64)(__s16)value;
+}
+
 static void emit_check_err(struct bpf_gen *gen)
 {
-	emit(gen, BPF_JMP_IMM(BPF_JSGE, BPF_REG_7, 0, 2));
-	emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
-	/* TODO: close intermediate FDs in case of error */
-	emit(gen, BPF_EXIT_INSN());
+	__s64 off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
+
+	/* R7 contains result of last sys_bpf command.
+	 * if (R7 < 0) goto cleanup;
+	 */
+	if (is_simm16(off)) {
+		emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, off));
+	} else {
+		gen->error = -ERANGE;
+		emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
+	}
 }
 
 /* reg1 and reg2 should not be R1 - R5. They can be R0, R6 - R10 */
-- 
2.30.2


  parent reply	other threads:[~2021-05-14  0:36 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-14  0:36 [PATCH v6 bpf-next 00/21] bpf: syscall program, FD array, loader program, light skeleton Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 01/21] bpf: Introduce bpf_sys_bpf() helper and program type Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 02/21] bpf: Introduce bpfptr_t user/kernel pointer Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 03/21] bpf: Prepare bpf syscall to be used from kernel and user space Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 04/21] libbpf: Support for syscall program type Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 05/21] selftests/bpf: Test " Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 06/21] bpf: Make btf_load command to be bpfptr_t compatible Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 07/21] selftests/bpf: Test for btf_load command Alexei Starovoitov
2021-05-14 18:12   ` Andrii Nakryiko
2021-05-14  0:36 ` [PATCH v6 bpf-next 08/21] bpf: Introduce fd_idx Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 09/21] bpf: Add bpf_btf_find_by_name_kind() helper Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 10/21] bpf: Add bpf_sys_close() helper Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 11/21] libbpf: Change the order of data and text relocations Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 12/21] libbpf: Add bpf_object pointer to kernel_supports() Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 13/21] libbpf: Preliminary support for fd_idx Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 14/21] libbpf: Generate loader program out of BPF ELF file Alexei Starovoitov
2021-06-11 20:22   ` Andrii Nakryiko
2021-07-20 20:51     ` Alexei Starovoitov
2021-07-20 21:10       ` Andrii Nakryiko
2021-05-14  0:36 ` Alexei Starovoitov [this message]
2021-05-14  0:36 ` [PATCH v6 bpf-next 16/21] libbpf: Introduce bpf_map__initial_value() Alexei Starovoitov
2021-05-14 18:02   ` Andrii Nakryiko
2021-05-14  0:36 ` [PATCH v6 bpf-next 17/21] bpftool: Use syscall/loader program in "prog load" and "gen skeleton" command Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 18/21] selftests/bpf: Convert few tests to light skeleton Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 19/21] selftests/bpf: Convert atomics test " Alexei Starovoitov
2021-05-14  0:36 ` [PATCH v6 bpf-next 20/21] selftests/bpf: Convert test printk to use rodata Alexei Starovoitov
2021-05-14 18:15   ` Andrii Nakryiko
2021-05-14  0:36 ` [PATCH v6 bpf-next 21/21] selftests/bpf: Convert test trace_printk to lskel Alexei Starovoitov
2021-05-14 18:16 ` [PATCH v6 bpf-next 00/21] bpf: syscall program, FD array, loader program, light skeleton Andrii Nakryiko
2021-05-18 19:54 ` Daniel Borkmann
2021-05-18 21:17   ` Alexei Starovoitov
2021-05-18 23:04     ` Daniel Borkmann

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=20210514003623.28033-16-alexei.starovoitov@gmail.com \
    --to=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=john.fastabend@gmail.com \
    --cc=kernel-team@fb.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.