UPSTREAM: bpf: Add kconfig knob for disabling unpriv bpf by default

commit 08389d888287c3823f80b0216766b71e17f0aba5 upstream.

Add a kconfig knob which allows for unprivileged bpf to be disabled by default.
If set, the knob sets /proc/sys/kernel/unprivileged_bpf_disabled to value of 2.

This still allows a transition of 2 -> {0,1} through an admin. Similarly,
this also still keeps 1 -> {1} behavior intact, so that once set to permanently
disabled, it cannot be undone aside from a reboot.

We've also added extra2 with max of 2 for the procfs handler, so that an admin
still has a chance to toggle between 0 <-> 2.

Either way, as an additional alternative, applications can make use of CAP_BPF
that we added a while ago.

Bug: 215557547
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/74ec548079189e4e4dffaeb42b8987bb3c852eee.1620765074.git.daniel@iogearbox.net
[fllinden@amazon.com: backported to 5.4]
Signed-off-by: Frank van der Linden <fllinden@amazon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit c230f6ba10)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I6d80853f0bd2c8618d956d967681c97b931a6137
This commit is contained in:
Daniel Borkmann 2021-05-11 22:35:17 +02:00 committed by Greg Kroah-Hartman
parent 2aea7dc18f
commit 508711cf30
4 changed files with 58 additions and 5 deletions

View File

@ -1125,6 +1125,27 @@ NMI switch that most IA32 servers have fires unknown NMI up, for
example. If a system hangs up, try pressing the NMI switch. example. If a system hangs up, try pressing the NMI switch.
unprivileged_bpf_disabled:
==========================
Writing 1 to this entry will disable unprivileged calls to ``bpf()``;
once disabled, calling ``bpf()`` without ``CAP_SYS_ADMIN`` will return
``-EPERM``. Once set to 1, this can't be cleared from the running kernel
anymore.
Writing 2 to this entry will also disable unprivileged calls to ``bpf()``,
however, an admin can still change this setting later on, if needed, by
writing 0 or 1 to this entry.
If ``BPF_UNPRIV_DEFAULT_OFF`` is enabled in the kernel config, then this
entry will default to 2 instead of 0.
= =============================================================
0 Unprivileged calls to ``bpf()`` are enabled
1 Unprivileged calls to ``bpf()`` are disabled without recovery
2 Unprivileged calls to ``bpf()`` are disabled
= =============================================================
watchdog: watchdog:
========= =========

View File

@ -1626,6 +1626,16 @@ config BPF_JIT_ALWAYS_ON
Enables BPF JIT and removes BPF interpreter to avoid Enables BPF JIT and removes BPF interpreter to avoid
speculative execution of BPF instructions by the interpreter speculative execution of BPF instructions by the interpreter
config BPF_UNPRIV_DEFAULT_OFF
bool "Disable unprivileged BPF by default"
depends on BPF_SYSCALL
help
Disables unprivileged BPF by default by setting the corresponding
/proc/sys/kernel/unprivileged_bpf_disabled knob to 2. An admin can
still reenable it by setting it to 0 later on, or permanently
disable it by setting it to 1 (from which no other transition to
0 is possible anymore).
config USERFAULTFD config USERFAULTFD
bool "Enable userfaultfd() system call" bool "Enable userfaultfd() system call"
depends on MMU depends on MMU

View File

@ -39,7 +39,8 @@ static DEFINE_SPINLOCK(prog_idr_lock);
static DEFINE_IDR(map_idr); static DEFINE_IDR(map_idr);
static DEFINE_SPINLOCK(map_idr_lock); static DEFINE_SPINLOCK(map_idr_lock);
int sysctl_unprivileged_bpf_disabled __read_mostly; int sysctl_unprivileged_bpf_disabled __read_mostly =
IS_BUILTIN(CONFIG_BPF_UNPRIV_DEFAULT_OFF) ? 2 : 0;
static const struct bpf_map_ops * const bpf_map_types[] = { static const struct bpf_map_ops * const bpf_map_types[] = {
#define BPF_PROG_TYPE(_id, _ops) #define BPF_PROG_TYPE(_id, _ops)

View File

@ -251,6 +251,28 @@ static int sysrq_sysctl_handler(struct ctl_table *table, int write,
#endif #endif
#ifdef CONFIG_BPF_SYSCALL
static int bpf_unpriv_handler(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
int ret, unpriv_enable = *(int *)table->data;
bool locked_state = unpriv_enable == 1;
struct ctl_table tmp = *table;
if (write && !capable(CAP_SYS_ADMIN))
return -EPERM;
tmp.data = &unpriv_enable;
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
if (write && !ret) {
if (locked_state && unpriv_enable != 1)
return -EPERM;
*(int *)table->data = unpriv_enable;
}
return ret;
}
#endif
static struct ctl_table kern_table[]; static struct ctl_table kern_table[];
static struct ctl_table vm_table[]; static struct ctl_table vm_table[];
static struct ctl_table fs_table[]; static struct ctl_table fs_table[];
@ -1256,10 +1278,9 @@ static struct ctl_table kern_table[] = {
.data = &sysctl_unprivileged_bpf_disabled, .data = &sysctl_unprivileged_bpf_disabled,
.maxlen = sizeof(sysctl_unprivileged_bpf_disabled), .maxlen = sizeof(sysctl_unprivileged_bpf_disabled),
.mode = 0644, .mode = 0644,
/* only handle a transition from default "0" to "1" */ .proc_handler = bpf_unpriv_handler,
.proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO,
.extra1 = SYSCTL_ONE, .extra2 = &two,
.extra2 = SYSCTL_ONE,
}, },
{ {
.procname = "bpf_stats_enabled", .procname = "bpf_stats_enabled",