Fix up bpf_jit_limit some more

Started by Lorenz Bauer on Oct 12, 2021 · 10 messages from 3 authors · Last reply Oct 14, 2021

Series

4 patches, 6 files

+47 −4

Subsystems (10)

Show 7 more

Maintainers (21)

Show 17 more
STALE1852d SUPERSEDED

Status: Superseded by v3 (posted 2021-10-14). [go to v3]

Revision v2 (3 revisions archived).

Revisions (3)
  1. v1
  2. v2 current [diff against previous]
  3. v3 [diff against previous]

open the first message on its own page

  1. [PATCH v2 1/4] bpf: define bpf_jit_alloc_exec_limit for riscv JIT
    Revisions and related patches
    Revisions (3)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
  2. [PATCH v2 2/4] bpf: define bpf_jit_alloc_exec_limit for arm64 JIT
    Revisions and related patches
    Revisions (3)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
  3. [PATCH v2 3/4] bpf: prevent increasing bpf_jit_limit above max
    Revisions and related patches
    Revisions (3)
    1. v1
    2. v2 current [diff against previous]
    3. v3 [diff against previous]
  4. [PATCH v2 4/4] bpf: export bpf_jit_current
    Revisions and related patches
    Revisions (2)
    1. v1
    2. v2 current [diff against previous]
Message details and related content
Some more cleanups around bpf_jit_limit to make it readable via sysctl.

Jakub raised the point that a sysctl toggle is UAPI and therefore
can't be easily changed later on. I tried to find another place to stick
the info, but couldn't find a good one. All the current BPF knobs are in
sysctl.

There are examples of read only sysctls:
$ sudo find /proc/sys -perm 0444 | wc -l
90

There are no examples of sysctls with mode 0400 however:
$ sudo find /proc/sys -perm 0400 | wc -l
0

Thoughts?

Changes in v2:
* riscv not sparcv (Luke)
* Expose bpf_jit_current in bytes, not pages (Nicholas)

Lorenz Bauer (4):
  bpf: define bpf_jit_alloc_exec_limit for riscv JIT
  bpf: define bpf_jit_alloc_exec_limit for arm64 JIT
  bpf: prevent increasing bpf_jit_limit above max
  bpf: export bpf_jit_current

 Documentation/admin-guide/sysctl/net.rst |  6 ++++++
 arch/arm64/net/bpf_jit_comp.c            |  5 +++++
 arch/riscv/net/bpf_jit_core.c            |  5 +++++
 include/linux/filter.h                   |  2 ++
 kernel/bpf/core.c                        |  7 ++++---
 net/core/sysctl_net_core.c               | 26 +++++++++++++++++++++++-
 6 files changed, 47 insertions(+), 4 deletions(-)

-- 
2.30.2

[PATCH v2 1/4] bpf: define bpf_jit_alloc_exec_limit for riscv JIT

Message details and related content
Expose the maximum amount of useable memory from the riscv JIT.

Signed-off-by: Lorenz Bauer <redacted>
Acked-by: Luke Nelson <luke.r.nels@gmail.com>
---
 arch/riscv/net/bpf_jit_core.c | 5 +++++
 1 file changed, 5 insertions(+)
diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
index fed86f42dfbe..0fee2cbaaf53 100644
--- a/arch/riscv/net/bpf_jit_core.c
+++ b/arch/riscv/net/bpf_jit_core.c
@@ -166,6 +166,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 	return prog;
 }
 
+u64 bpf_jit_alloc_exec_limit(void)
+{
+	return BPF_JIT_REGION_SIZE;
+}
+
 void *bpf_jit_alloc_exec(unsigned long size)
 {
 	return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
-- 
2.30.2

[PATCH v2 2/4] bpf: define bpf_jit_alloc_exec_limit for arm64 JIT

Message details and related content
Expose the maximum amount of useable memory from the arm64 JIT.

Signed-off-by: Lorenz Bauer <redacted>
---
 arch/arm64/net/bpf_jit_comp.c | 5 +++++
 1 file changed, 5 insertions(+)
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 41c23f474ea6..803e7773fa86 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -1136,6 +1136,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 	return prog;
 }
 
+u64 bpf_jit_alloc_exec_limit(void)
+{
+	return BPF_JIT_REGION_SIZE;
+}
+
 void *bpf_jit_alloc_exec(unsigned long size)
 {
 	return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
-- 
2.30.2

[PATCH v2 3/4] bpf: prevent increasing bpf_jit_limit above max

Message details and related content
Restrict bpf_jit_limit to the maximum supported by the arch's JIT.

Signed-off-by: Lorenz Bauer <redacted>
---
 include/linux/filter.h     | 1 +
 kernel/bpf/core.c          | 4 +++-
 net/core/sysctl_net_core.c | 2 +-
 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 47f80adbe744..8231a6a257f6 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1050,6 +1050,7 @@ extern int bpf_jit_enable;
 extern int bpf_jit_harden;
 extern int bpf_jit_kallsyms;
 extern long bpf_jit_limit;
+extern long bpf_jit_limit_max;
 
 typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
 
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b6c72af64d5d..ab84b3816339 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -525,6 +525,7 @@ int bpf_jit_enable   __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
 int bpf_jit_kallsyms __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
 int bpf_jit_harden   __read_mostly;
 long bpf_jit_limit   __read_mostly;
+long bpf_jit_limit_max __read_mostly;
 
 static void
 bpf_prog_ksym_set_addr(struct bpf_prog *prog)
@@ -818,7 +819,8 @@ u64 __weak bpf_jit_alloc_exec_limit(void)
 static int __init bpf_jit_charge_init(void)
 {
 	/* Only used as heuristic here to derive limit. */
-	bpf_jit_limit = min_t(u64, round_up(bpf_jit_alloc_exec_limit() >> 2,
+	bpf_jit_limit_max = bpf_jit_alloc_exec_limit();
+	bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2,
 					    PAGE_SIZE), LONG_MAX);
 	return 0;
 }
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index c8496c1142c9..5f88526ad61c 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -419,7 +419,7 @@ static struct ctl_table net_core_table[] = {
 		.mode		= 0600,
 		.proc_handler	= proc_dolongvec_minmax_bpf_restricted,
 		.extra1		= &long_one,
-		.extra2		= &long_max,
+		.extra2		= &bpf_jit_limit_max,
 	},
 #endif
 	{
-- 
2.30.2

[PATCH v2 4/4] bpf: export bpf_jit_current

Message details and related content
Expose bpf_jit_current as a read only value via sysctl.

Signed-off-by: Lorenz Bauer <redacted>
---
 Documentation/admin-guide/sysctl/net.rst |  6 ++++++
 include/linux/filter.h                   |  1 +
 kernel/bpf/core.c                        |  3 +--
 net/core/sysctl_net_core.c               | 24 ++++++++++++++++++++++++
 4 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
index 4150f74c521a..524e7db8d53f 100644
--- a/Documentation/admin-guide/sysctl/net.rst
+++ b/Documentation/admin-guide/sysctl/net.rst
@@ -123,6 +123,12 @@ compiler in order to reject unprivileged JIT requests once it has
 been surpassed. bpf_jit_limit contains the value of the global limit
 in bytes.
 
+bpf_jit_current
+---------------
+
+The amount of JIT memory currently allocated, in bytes. JITing of
+unprivileged BPF is rejected if this value is above bpf_jit_limit.
+
 dev_weight
 ----------
 
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 8231a6a257f6..42c543a21cd8 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1051,6 +1051,7 @@ extern int bpf_jit_harden;
 extern int bpf_jit_kallsyms;
 extern long bpf_jit_limit;
 extern long bpf_jit_limit_max;
+extern atomic_long_t bpf_jit_current;
 
 typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
 
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index ab84b3816339..12aedab09222 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -526,6 +526,7 @@ int bpf_jit_kallsyms __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_DEFAULT_ON);
 int bpf_jit_harden   __read_mostly;
 long bpf_jit_limit   __read_mostly;
 long bpf_jit_limit_max __read_mostly;
+atomic_long_t bpf_jit_current __read_mostly;
 
 static void
 bpf_prog_ksym_set_addr(struct bpf_prog *prog)
@@ -801,8 +802,6 @@ int bpf_jit_add_poke_descriptor(struct bpf_prog *prog,
 	return slot;
 }
 
-static atomic_long_t bpf_jit_current;
-
 /* Can be overridden by an arch's JIT compiler if it has a custom,
  * dedicated BPF backend memory area, or if neither of the two
  * below apply.
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 5f88526ad61c..78603f561482 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -15,6 +15,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/atomic.h>
 
 #include <net/ip.h>
 #include <net/sock.h>
@@ -307,6 +308,22 @@ proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write,
 
 	return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
+
+static int proc_bpf_jit_current(struct ctl_table *table, int write,
+				void *buffer, size_t *lenp, loff_t *ppos)
+{
+	long curr = atomic_long_read(&bpf_jit_current) << PAGE_SHIFT;
+	struct ctl_table ctl_entry = {
+		.data		= &curr,
+		.maxlen		= sizeof(long),
+	};
+
+
+	if (!capable(CAP_SYS_ADMIN) || write)
+		return -EPERM;
+
+	return proc_doulongvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
+}
 #endif
 
 static struct ctl_table net_core_table[] = {
@@ -421,6 +438,13 @@ static struct ctl_table net_core_table[] = {
 		.extra1		= &long_one,
 		.extra2		= &bpf_jit_limit_max,
 	},
+	{
+		.procname	= "bpf_jit_current",
+		.data		= &bpf_jit_current,
+		.maxlen		= sizeof(long),
+		.mode		= 0400,
+		.proc_handler	= proc_bpf_jit_current,
+	},
 #endif
 	{
 		.procname	= "netdev_tstamp_prequeue",
-- 
2.30.2

Re: [PATCH v2 4/4] bpf: export bpf_jit_current

Message details and related content
On Tue, 12 Oct 2021 at 17:29, Nicolas Dichtel [off-list ref] wrote:
Le 12/10/2021 à 15:59, Lorenz Bauer a écrit :
quoted
Expose bpf_jit_current as a read only value via sysctl.

Signed-off-by: Lorenz Bauer <redacted>
---
[snip]
quoted
+     {
+             .procname       = "bpf_jit_current",
+             .data           = &bpf_jit_current,
+             .maxlen         = sizeof(long),
+             .mode           = 0400,
Why not 0444 ?
This mirrors what the other BPF related sysctls do, which only allow
access from root with CAP_SYS_ADMIN. I'd prefer 0444 as well, but
Daniel explicitly locked down these sysctls in
2e4a30983b0f9b19b59e38bbf7427d7fdd480d98.

Lorenz

--
Lorenz Bauer  |  Systems Engineer
6th Floor, County Hall/The Riverside Building, SE1 7PB, UK

www.cloudflare.com

Re: [PATCH v2 4/4] bpf: export bpf_jit_current

Message details and related content
Le 13/10/2021 à 10:35, Lorenz Bauer a écrit :
On Tue, 12 Oct 2021 at 17:29, Nicolas Dichtel [off-list ref] wrote:
quoted
Le 12/10/2021 à 15:59, Lorenz Bauer a écrit :
quoted
Expose bpf_jit_current as a read only value via sysctl.

Signed-off-by: Lorenz Bauer <redacted>
---
[snip]
quoted
+     {
+             .procname       = "bpf_jit_current",
+             .data           = &bpf_jit_current,
+             .maxlen         = sizeof(long),
+             .mode           = 0400,
Why not 0444 ?
This mirrors what the other BPF related sysctls do, which only allow
access from root with CAP_SYS_ADMIN. I'd prefer 0444 as well, but
Daniel explicitly locked down these sysctls in
2e4a30983b0f9b19b59e38bbf7427d7fdd480d98.
Even after this patch, bpf_jit_enable is 0644.

In fact, if you have CAP_BPF or CAP_SYS_ADMIN, this value has no impact for your
programs. But I you don't have one of these capabilities, it may be rejected,
but you cannot read these values, which help to understand why.


Regards,
Nicolas
Message details and related content
On Tue, Oct 12, 2021 at 03:59 PM CEST, Lorenz Bauer wrote:
Some more cleanups around bpf_jit_limit to make it readable via sysctl.

Jakub raised the point that a sysctl toggle is UAPI and therefore
can't be easily changed later on. I tried to find another place to stick
the info, but couldn't find a good one. All the current BPF knobs are in
sysctl.

There are examples of read only sysctls:
$ sudo find /proc/sys -perm 0444 | wc -l
90

There are no examples of sysctls with mode 0400 however:
$ sudo find /proc/sys -perm 0400 | wc -l
0

Thoughts?
I threw this idea out there during LPC already, that it would be cool to
use BPF iterators for that. Pinned/preloaded iterators were made for
dumping kernel data on demand after all.

What is missing is a BPF iterator type that would run the program just
once (there is just one thing to print), and a BPF helper to lookup
symbol's address.

I thought this would require a bit of work, but actually getting a PoC
(see below) to work was rather pleasntly straightforward.

Perhaps a bit of a hack but I'd consider it as an alternative.

-- >8 --

From bef52bec926ea08ccd32a3421d195210ae7d3b38 Mon Sep 17 00:00:00 2001
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: Wed, 13 Oct 2021 18:54:12 +0200
Subject: [PATCH] RFC: BPF iterator that always runs the program just once

The test iterator loads the value of bpf_jit_current kernel global:

 # bpftool iter pin tools/testing/selftests/bpf/bpf_iter_once.o /sys/fs/bpf/bpf_jit_current
 libbpf: elf: skipping unrecognized data section(6) .rodata.str1.1
 # cat /sys/fs/bpf/bpf_jit_current
 2
 # for ((i=0; i<10; i++)); do iptables -A OUTPUT -m bpf --bytecode '1,6 0 0 0' -j ACCEPT; done
 # cat /sys/fs/bpf/bpf_jit_current
 12
 # iptables -F OUTPUT
 # cat /sys/fs/bpf/bpf_jit_current
 2

Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
 include/uapi/linux/bpf.h                      |  7 ++
 kernel/bpf/Makefile                           |  2 +-
 kernel/bpf/helpers.c                          | 22 ++++++
 kernel/bpf/once_iter.c                        | 76 +++++++++++++++++++

6 more lines

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 6fc59d61937a..ec117ebd3d58 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -4909,6 +4909,12 @@ union bpf_attr {
  *	Return
  *		The number of bytes written to the buffer, or a negative error
  *		in case of failure.
+ *
+ * long bpf_kallsyms_lookup_name(const char *name, u32 name_size)
+ *	Description
+ *		Lookup the address for a symbol.
+ *	Return
+ *		Returns 0 if not found.
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -5089,6 +5095,7 @@ union bpf_attr {
 	FN(task_pt_regs),		\
 	FN(get_branch_snapshot),	\
 	FN(trace_vprintk),		\
+	FN(kallsyms_lookup_name),	\
 	/* */

 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 7f33098ca63f..f2dc86ea0f2d 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -6,7 +6,7 @@ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse
 endif
 CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)

-obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o
+obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o once_iter.o
 obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o
 obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o
 obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 1ffd469c217f..d2524df54ab5 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -15,6 +15,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/proc_ns.h>
 #include <linux/security.h>
+#include <linux/kallsyms.h>

 #include "../../lib/kstrtox.h"
@@ -1328,6 +1329,25 @@ void bpf_timer_cancel_and_free(void *val)
 	kfree(t);
 }

+BPF_CALL_2(bpf_kallsyms_lookup_name, const char *, name, u32, name_size)
+{
+	const char *name_end;
+
+	name_end = strnchr(name, name_size, 0);
+	if (!name_end)
+		return -EINVAL;
+
+	return kallsyms_lookup_name(name);
+}
+
+static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = {
+	.func		= bpf_kallsyms_lookup_name,
+	.gpl_only	= true,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_MEM,
+	.arg2_type	= ARG_CONST_SIZE,
+};
+
 const struct bpf_func_proto bpf_get_current_task_proto __weak;
 const struct bpf_func_proto bpf_get_current_task_btf_proto __weak;
 const struct bpf_func_proto bpf_probe_read_user_proto __weak;
@@ -1404,6 +1424,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
 		return &bpf_timer_start_proto;
 	case BPF_FUNC_timer_cancel:
 		return &bpf_timer_cancel_proto;
+	case BPF_FUNC_kallsyms_lookup_name:
+		return &bpf_kallsyms_lookup_name_proto;
 	default:
 		break;
 	}
diff --git a/kernel/bpf/once_iter.c b/kernel/bpf/once_iter.c
new file mode 100644
index 000000000000..f2635f1b0043
--- /dev/null
+++ b/kernel/bpf/once_iter.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2021 Cloudflare, Inc. */
+
+#include <linux/bpf.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+
+static struct {} empty;
+
+static void *once_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos == 0)
+		++*pos;
+	return &empty;
+}
+
+static void *once_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+struct bpf_iter__once {
+	__bpf_md_ptr(struct bpf_iter_meta *, meta);
+};
+
+DEFINE_BPF_ITER_FUNC(once, struct bpf_iter_meta *meta)
+
+static int once_seq_show(struct seq_file *seq, void *v)
+{
+	return 0;
+}
+
+static void once_seq_stop(struct seq_file *seq, void *v)
+{
+	struct bpf_iter_meta meta;
+	struct bpf_iter__once ctx;
+	struct bpf_prog *prog;
+
+	meta.seq = seq;
+	prog = bpf_iter_get_info(&meta, true);
+	if (!prog)
+		return;
+
+	meta.seq = seq;
+	ctx.meta = &meta;
+	bpf_iter_run_prog(prog, &ctx);
+}
+
+static const struct seq_operations once_seq_ops = {
+	.start	= once_seq_start,
+	.next	= once_seq_next,
+	.stop	= once_seq_stop,
+	.show	= once_seq_show,
+};
+
+static const struct bpf_iter_seq_info once_seq_info = {
+	.seq_ops		= &once_seq_ops,
+	.init_seq_private	= NULL,
+	.fini_seq_private	= NULL,
+	.seq_priv_size		= 0,
+};
+
+static struct bpf_iter_reg once_reg_info = {
+	.target			= "once",
+	.feature		= 0,
+	.ctx_arg_info_size	= 0,
+	.ctx_arg_info		= {},
+	.seq_info		= &once_seq_info,
+};
+
+static int __init once_iter_init(void)
+{
+	return bpf_iter_reg_target(&once_reg_info);
+}
+late_initcall(once_iter_init);
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 6fc59d61937a..ec117ebd3d58 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -4909,6 +4909,12 @@ union bpf_attr {
  *	Return
  *		The number of bytes written to the buffer, or a negative error
  *		in case of failure.
+ *
+ * long bpf_kallsyms_lookup_name(const char *name, u32 name_size)
+ *	Description
+ *		Lookup the address for a symbol.
+ *	Return
+ *		Returns 0 if not found.
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -5089,6 +5095,7 @@ union bpf_attr {
 	FN(task_pt_regs),		\
 	FN(get_branch_snapshot),	\
 	FN(trace_vprintk),		\
+	FN(kallsyms_lookup_name),	\
 	/* */

 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_once.c b/tools/testing/selftests/bpf/progs/bpf_iter_once.c
new file mode 100644
index 000000000000..e5e6d779eb51
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_once.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2021 Cloudflare, Inc. */
+
+#include "bpf_iter.h"
+#include <bpf/bpf_helpers.h>
+
+char _license[] SEC("license") = "GPL";
+
+SEC("iter/once")
+int dump_once(struct bpf_iter__once *ctx)
+{
+	const char sym_name[] = "bpf_jit_current";
+	struct seq_file *seq = ctx->meta->seq;
+	unsigned long sym_addr;
+	s64 value = 0;
+	int err;
+
+	sym_addr = bpf_kallsyms_lookup_name(sym_name, sizeof(sym_name));
+	if (!sym_addr) {
+		BPF_SEQ_PRINTF(seq, "failed to find %s address\n", sym_name);
+		return 0;
+	}
+
+	err = bpf_probe_read_kernel(&value, sizeof(value), (void *)sym_addr);
+	if (err) {
+		BPF_SEQ_PRINTF(seq, "failed to read from %s address\n", sym_name);
+		return 0;
+	}
+
+	BPF_SEQ_PRINTF(seq, "%ld\n", value);
+
+	return 0;
+}
--
2.31.1
Message details and related content
On Wed, 13 Oct 2021 at 20:56, Jakub Sitnicki [off-list ref] wrote:
On Tue, Oct 12, 2021 at 03:59 PM CEST, Lorenz Bauer wrote:
quoted
Some more cleanups around bpf_jit_limit to make it readable via sysctl.

Jakub raised the point that a sysctl toggle is UAPI and therefore
can't be easily changed later on. I tried to find another place to stick
the info, but couldn't find a good one. All the current BPF knobs are in
sysctl.

There are examples of read only sysctls:
$ sudo find /proc/sys -perm 0444 | wc -l
90

There are no examples of sysctls with mode 0400 however:
$ sudo find /proc/sys -perm 0400 | wc -l
0

Thoughts?
I threw this idea out there during LPC already, that it would be cool to
use BPF iterators for that. Pinned/preloaded iterators were made for
dumping kernel data on demand after all.

What is missing is a BPF iterator type that would run the program just
once (there is just one thing to print), and a BPF helper to lookup
symbol's address.

I thought this would require a bit of work, but actually getting a PoC
(see below) to work was rather pleasntly straightforward.

Perhaps a bit of a hack but I'd consider it as an alternative.
I spoke to Jakub, I won't have time to work on this myself. So I'll
drop this patch from the series and send a v3 with just the fixes to
bpf_jit_limit.

-- 
Lorenz Bauer  |  Systems Engineer
6th Floor, County Hall/The Riverside Building, SE1 7PB, UK

www.cloudflare.com
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help