Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Daniel Borkmann says:

====================
pull-request: bpf 2021-11-05

We've added 15 non-merge commits during the last 3 day(s) which contain
a total of 14 files changed, 199 insertions(+), 90 deletions(-).

The main changes are:

1) Fix regression from stack spill/fill of <8 byte scalars, from Martin KaFai Lau.

2) Fix perf's build of bpftool's bootstrap version due to missing libbpf
   headers, from Quentin Monnet.

3) Fix riscv{32,64} BPF exception tables build errors and warnings, from Björn Töpel.

4) Fix bpf fs to allow RENAME_EXCHANGE support for atomic upgrades on sk_lookup
   control planes, from Lorenz Bauer.

5) Fix libbpf's error reporting in bpf_map_lookup_and_delete_elem_flags() due to
   missing libbpf_err_errno(), from Mehrdad Arshad Rad.

6) Various fixes to make xdp_redirect_multi selftest more reliable, from Hangbin Liu.

7) Fix netcnt selftest to make it run serial and thus avoid conflicts with other
   cgroup/skb selftests run in parallel that could cause flakes, from Andrii Nakryiko.

8) Fix reuseport_bpf_numa networking selftest to skip unavailable NUMA nodes,
   from Kleber Sacilotto de Souza.

* https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  riscv, bpf: Fix RV32 broken build, and silence RV64 warning
  selftests/bpf/xdp_redirect_multi: Limit the tests in netns
  selftests/bpf/xdp_redirect_multi: Give tcpdump a chance to terminate cleanly
  selftests/bpf/xdp_redirect_multi: Use arping to accurate the arp number
  selftests/bpf/xdp_redirect_multi: Put the logs to tmp folder
  libbpf: Fix lookup_and_delete_elem_flags error reporting
  bpftool: Install libbpf headers for the bootstrap version, too
  selftests/net: Fix reuseport_bpf_numa by skipping unavailable nodes
  selftests/bpf: Verifier test on refill from a smaller spill
  bpf: Do not reject when the stack read size is different from the tracked scalar size
  selftests/bpf: Make netcnt selftests serial to avoid spurious failures
  selftests/bpf: Test RENAME_EXCHANGE and RENAME_NOREPLACE on bpffs
  selftests/bpf: Convert test_bpffs to ASSERT macros
  libfs: Support RENAME_EXCHANGE in simple_rename()
  libfs: Move shmem_exchange to simple_rename_exchange
====================

Link: https://lore.kernel.org/r/20211105165803.29372-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Nov 5, 2021
2 parents a46a503 + f47d4ff commit 9bea6aa
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 90 deletions.
4 changes: 2 additions & 2 deletions arch/riscv/mm/extable.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/uaccess.h>

#ifdef CONFIG_BPF_JIT
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I)
int rv_bpf_fixup_exception(const struct exception_table_entry *ex, struct pt_regs *regs);
#endif

Expand All @@ -23,7 +23,7 @@ int fixup_exception(struct pt_regs *regs)
if (!fixup)
return 0;

#ifdef CONFIG_BPF_JIT
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_ARCH_RV64I)
if (regs->epc >= BPF_JIT_REGION_START && regs->epc < BPF_JIT_REGION_END)
return rv_bpf_fixup_exception(fixup, regs);
#endif
Expand Down
2 changes: 2 additions & 0 deletions arch/riscv/net/bpf_jit_comp64.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
#define BPF_FIXUP_OFFSET_MASK GENMASK(26, 0)
#define BPF_FIXUP_REG_MASK GENMASK(31, 27)

int rv_bpf_fixup_exception(const struct exception_table_entry *ex,
struct pt_regs *regs);
int rv_bpf_fixup_exception(const struct exception_table_entry *ex,
struct pt_regs *regs)
{
Expand Down
29 changes: 28 additions & 1 deletion fs/libfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,16 +448,43 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
}
EXPORT_SYMBOL(simple_rmdir);

int simple_rename_exchange(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
bool old_is_dir = d_is_dir(old_dentry);
bool new_is_dir = d_is_dir(new_dentry);

if (old_dir != new_dir && old_is_dir != new_is_dir) {
if (old_is_dir) {
drop_nlink(old_dir);
inc_nlink(new_dir);
} else {
drop_nlink(new_dir);
inc_nlink(old_dir);
}
}
old_dir->i_ctime = old_dir->i_mtime =
new_dir->i_ctime = new_dir->i_mtime =
d_inode(old_dentry)->i_ctime =
d_inode(new_dentry)->i_ctime = current_time(old_dir);

return 0;
}
EXPORT_SYMBOL_GPL(simple_rename_exchange);

int simple_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry, unsigned int flags)
{
struct inode *inode = d_inode(old_dentry);
int they_are_dirs = d_is_dir(old_dentry);

if (flags & ~RENAME_NOREPLACE)
if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
return -EINVAL;

if (flags & RENAME_EXCHANGE)
return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);

if (!simple_empty(new_dentry))
return -ENOTEMPTY;

Expand Down
2 changes: 2 additions & 0 deletions include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -3383,6 +3383,8 @@ extern int simple_open(struct inode *inode, struct file *file);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
extern int simple_rmdir(struct inode *, struct dentry *);
extern int simple_rename_exchange(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry);
extern int simple_rename(struct user_namespace *, struct inode *,
struct dentry *, struct inode *, struct dentry *,
unsigned int);
Expand Down
18 changes: 6 additions & 12 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -3088,9 +3088,12 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
reg = &reg_state->stack[spi].spilled_ptr;

if (is_spilled_reg(&reg_state->stack[spi])) {
if (size != BPF_REG_SIZE) {
u8 scalar_size = 0;
u8 spill_size = 1;

for (i = BPF_REG_SIZE - 1; i > 0 && stype[i - 1] == STACK_SPILL; i--)
spill_size++;

if (size != BPF_REG_SIZE || spill_size != BPF_REG_SIZE) {
if (reg->type != SCALAR_VALUE) {
verbose_linfo(env, env->insn_idx, "; ");
verbose(env, "invalid size of register fill\n");
Expand All @@ -3101,10 +3104,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
if (dst_regno < 0)
return 0;

for (i = BPF_REG_SIZE; i > 0 && stype[i - 1] == STACK_SPILL; i--)
scalar_size++;

if (!(off % BPF_REG_SIZE) && size == scalar_size) {
if (!(off % BPF_REG_SIZE) && size == spill_size) {
/* The earlier check_reg_arg() has decided the
* subreg_def for this insn. Save it first.
*/
Expand All @@ -3128,12 +3128,6 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
state->regs[dst_regno].live |= REG_LIVE_WRITTEN;
return 0;
}
for (i = 1; i < BPF_REG_SIZE; i++) {
if (stype[(slot - i) % BPF_REG_SIZE] != STACK_SPILL) {
verbose(env, "corrupted spill memory\n");
return -EACCES;
}
}

if (dst_regno >= 0) {
/* restore register state from stack */
Expand Down
24 changes: 1 addition & 23 deletions mm/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2947,28 +2947,6 @@ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
return shmem_unlink(dir, dentry);
}

static int shmem_exchange(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
{
bool old_is_dir = d_is_dir(old_dentry);
bool new_is_dir = d_is_dir(new_dentry);

if (old_dir != new_dir && old_is_dir != new_is_dir) {
if (old_is_dir) {
drop_nlink(old_dir);
inc_nlink(new_dir);
} else {
drop_nlink(new_dir);
inc_nlink(old_dir);
}
}
old_dir->i_ctime = old_dir->i_mtime =
new_dir->i_ctime = new_dir->i_mtime =
d_inode(old_dentry)->i_ctime =
d_inode(new_dentry)->i_ctime = current_time(old_dir);

return 0;
}

static int shmem_whiteout(struct user_namespace *mnt_userns,
struct inode *old_dir, struct dentry *old_dentry)
{
Expand Down Expand Up @@ -3014,7 +2992,7 @@ static int shmem_rename2(struct user_namespace *mnt_userns,
return -EINVAL;

if (flags & RENAME_EXCHANGE)
return shmem_exchange(old_dir, old_dentry, new_dir, new_dentry);
return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);

if (!simple_empty(new_dentry))
return -ENOTEMPTY;
Expand Down
32 changes: 22 additions & 10 deletions tools/bpf/bpftool/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,29 @@ else
_OUTPUT := $(CURDIR)
endif
BOOTSTRAP_OUTPUT := $(_OUTPUT)/bootstrap/

LIBBPF_OUTPUT := $(_OUTPUT)/libbpf/
LIBBPF_DESTDIR := $(LIBBPF_OUTPUT)
LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include
LIBBPF_HDRS_DIR := $(LIBBPF_INCLUDE)/bpf
LIBBPF := $(LIBBPF_OUTPUT)libbpf.a

LIBBPF = $(LIBBPF_OUTPUT)libbpf.a
LIBBPF_BOOTSTRAP_OUTPUT = $(BOOTSTRAP_OUTPUT)libbpf/
LIBBPF_BOOTSTRAP = $(LIBBPF_BOOTSTRAP_OUTPUT)libbpf.a
LIBBPF_BOOTSTRAP_OUTPUT := $(BOOTSTRAP_OUTPUT)libbpf/
LIBBPF_BOOTSTRAP_DESTDIR := $(LIBBPF_BOOTSTRAP_OUTPUT)
LIBBPF_BOOTSTRAP_INCLUDE := $(LIBBPF_BOOTSTRAP_DESTDIR)/include
LIBBPF_BOOTSTRAP_HDRS_DIR := $(LIBBPF_BOOTSTRAP_INCLUDE)/bpf
LIBBPF_BOOTSTRAP := $(LIBBPF_BOOTSTRAP_OUTPUT)libbpf.a

# We need to copy hashmap.h and nlattr.h which is not otherwise exported by
# libbpf, but still required by bpftool.
LIBBPF_INTERNAL_HDRS := $(addprefix $(LIBBPF_HDRS_DIR)/,hashmap.h nlattr.h)
LIBBPF_BOOTSTRAP_INTERNAL_HDRS := $(addprefix $(LIBBPF_BOOTSTRAP_HDRS_DIR)/,hashmap.h)

ifeq ($(BPFTOOL_VERSION),)
BPFTOOL_VERSION := $(shell make -rR --no-print-directory -sC ../../.. kernelversion)
endif

$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DIR):
$(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DIR) $(LIBBPF_BOOTSTRAP_HDRS_DIR):
$(QUIET_MKDIR)mkdir -p $@

$(LIBBPF): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_OUTPUT)
Expand All @@ -52,7 +57,12 @@ $(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_

$(LIBBPF_BOOTSTRAP): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_BOOTSTRAP_OUTPUT)
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_BOOTSTRAP_OUTPUT) \
ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@
DESTDIR=$(LIBBPF_BOOTSTRAP_DESTDIR) prefix= \
ARCH= CC=$(HOSTCC) LD=$(HOSTLD) $@ install_headers

$(LIBBPF_BOOTSTRAP_INTERNAL_HDRS): $(LIBBPF_BOOTSTRAP_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_BOOTSTRAP_HDRS_DIR)
$(call QUIET_INSTALL, $@)
$(Q)install -m 644 -t $(LIBBPF_BOOTSTRAP_HDRS_DIR) $<

$(LIBBPF)-clean: FORCE | $(LIBBPF_OUTPUT)
$(call QUIET_CLEAN, libbpf)
Expand Down Expand Up @@ -172,11 +182,11 @@ else
$(Q)cp "$(VMLINUX_H)" $@
endif

$(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF)
$(OUTPUT)%.bpf.o: skeleton/%.bpf.c $(OUTPUT)vmlinux.h $(LIBBPF_BOOTSTRAP)
$(QUIET_CLANG)$(CLANG) \
-I$(if $(OUTPUT),$(OUTPUT),.) \
-I$(srctree)/tools/include/uapi/ \
-I$(LIBBPF_INCLUDE) \
-I$(LIBBPF_BOOTSTRAP_INCLUDE) \
-g -O2 -Wall -target bpf -c $< -o $@ && $(LLVM_STRIP) -g $@

$(OUTPUT)%.skel.h: $(OUTPUT)%.bpf.o $(BPFTOOL_BOOTSTRAP)
Expand Down Expand Up @@ -209,8 +219,10 @@ $(BPFTOOL_BOOTSTRAP): $(BOOTSTRAP_OBJS) $(LIBBPF_BOOTSTRAP)
$(OUTPUT)bpftool: $(OBJS) $(LIBBPF)
$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
$(QUIET_CC)$(HOSTCC) $(CFLAGS) -c -MMD -o $@ $<
$(BOOTSTRAP_OUTPUT)%.o: %.c $(LIBBPF_BOOTSTRAP_INTERNAL_HDRS) | $(BOOTSTRAP_OUTPUT)
$(QUIET_CC)$(HOSTCC) \
$(subst -I$(LIBBPF_INCLUDE),-I$(LIBBPF_BOOTSTRAP_INCLUDE),$(CFLAGS)) \
-c -MMD -o $@ $<

$(OUTPUT)%.o: %.c
$(QUIET_CC)$(CC) $(CFLAGS) -c -MMD -o $@ $<
Expand Down Expand Up @@ -257,6 +269,6 @@ doc-uninstall:
FORCE:

.SECONDARY:
.PHONY: all FORCE clean install-bin install uninstall
.PHONY: all FORCE bootstrap clean install-bin install uninstall
.PHONY: doc doc-clean doc-install doc-uninstall
.DEFAULT_GOAL := all
4 changes: 3 additions & 1 deletion tools/lib/bpf/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,14 +515,16 @@ int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
{
union bpf_attr attr;
int ret;

memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = ptr_to_u64(key);
attr.value = ptr_to_u64(value);
attr.flags = flags;

return sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
return libbpf_err_errno(ret);
}

int bpf_map_delete_elem(int fd, const void *key)
Expand Down
2 changes: 1 addition & 1 deletion tools/testing/selftests/bpf/prog_tests/netcnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#define CG_NAME "/netcnt"

void test_netcnt(void)
void serial_test_netcnt(void)
{
union percpu_net_cnt *percpu_netcnt = NULL;
struct bpf_cgroup_storage_key key;
Expand Down
85 changes: 74 additions & 11 deletions tools/testing/selftests/bpf/prog_tests/test_bpffs.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Facebook */
#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <sys/mount.h>
#include <sys/stat.h>
Expand Down Expand Up @@ -29,44 +30,106 @@ static int read_iter(char *file)

static int fn(void)
{
int err, duration = 0;
struct stat a, b, c;
int err, map;

err = unshare(CLONE_NEWNS);
if (CHECK(err, "unshare", "failed: %d\n", errno))
if (!ASSERT_OK(err, "unshare"))
goto out;

err = mount("", "/", "", MS_REC | MS_PRIVATE, NULL);
if (CHECK(err, "mount /", "failed: %d\n", errno))
if (!ASSERT_OK(err, "mount /"))
goto out;

err = umount(TDIR);
if (CHECK(err, "umount " TDIR, "failed: %d\n", errno))
if (!ASSERT_OK(err, "umount " TDIR))
goto out;

err = mount("none", TDIR, "tmpfs", 0, NULL);
if (CHECK(err, "mount", "mount root failed: %d\n", errno))
if (!ASSERT_OK(err, "mount tmpfs"))
goto out;

err = mkdir(TDIR "/fs1", 0777);
if (CHECK(err, "mkdir "TDIR"/fs1", "failed: %d\n", errno))
if (!ASSERT_OK(err, "mkdir " TDIR "/fs1"))
goto out;
err = mkdir(TDIR "/fs2", 0777);
if (CHECK(err, "mkdir "TDIR"/fs2", "failed: %d\n", errno))
if (!ASSERT_OK(err, "mkdir " TDIR "/fs2"))
goto out;

err = mount("bpf", TDIR "/fs1", "bpf", 0, NULL);
if (CHECK(err, "mount bpffs "TDIR"/fs1", "failed: %d\n", errno))
if (!ASSERT_OK(err, "mount bpffs " TDIR "/fs1"))
goto out;
err = mount("bpf", TDIR "/fs2", "bpf", 0, NULL);
if (CHECK(err, "mount bpffs " TDIR "/fs2", "failed: %d\n", errno))
if (!ASSERT_OK(err, "mount bpffs " TDIR "/fs2"))
goto out;

err = read_iter(TDIR "/fs1/maps.debug");
if (CHECK(err, "reading " TDIR "/fs1/maps.debug", "failed\n"))
if (!ASSERT_OK(err, "reading " TDIR "/fs1/maps.debug"))
goto out;
err = read_iter(TDIR "/fs2/progs.debug");
if (CHECK(err, "reading " TDIR "/fs2/progs.debug", "failed\n"))
if (!ASSERT_OK(err, "reading " TDIR "/fs2/progs.debug"))
goto out;

err = mkdir(TDIR "/fs1/a", 0777);
if (!ASSERT_OK(err, "creating " TDIR "/fs1/a"))
goto out;
err = mkdir(TDIR "/fs1/a/1", 0777);
if (!ASSERT_OK(err, "creating " TDIR "/fs1/a/1"))
goto out;
err = mkdir(TDIR "/fs1/b", 0777);
if (!ASSERT_OK(err, "creating " TDIR "/fs1/b"))
goto out;

map = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 4, 1, 0);
if (!ASSERT_GT(map, 0, "create_map(ARRAY)"))
goto out;
err = bpf_obj_pin(map, TDIR "/fs1/c");
if (!ASSERT_OK(err, "pin map"))
goto out;
close(map);

/* Check that RENAME_EXCHANGE works for directories. */
err = stat(TDIR "/fs1/a", &a);
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/a)"))
goto out;
err = renameat2(0, TDIR "/fs1/a", 0, TDIR "/fs1/b", RENAME_EXCHANGE);
if (!ASSERT_OK(err, "renameat2(/fs1/a, /fs1/b, RENAME_EXCHANGE)"))
goto out;
err = stat(TDIR "/fs1/b", &b);
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/b)"))
goto out;
if (!ASSERT_EQ(a.st_ino, b.st_ino, "b should have a's inode"))
goto out;
err = access(TDIR "/fs1/b/1", F_OK);
if (!ASSERT_OK(err, "access(" TDIR "/fs1/b/1)"))
goto out;

/* Check that RENAME_EXCHANGE works for mixed file types. */
err = stat(TDIR "/fs1/c", &c);
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/map)"))
goto out;
err = renameat2(0, TDIR "/fs1/c", 0, TDIR "/fs1/b", RENAME_EXCHANGE);
if (!ASSERT_OK(err, "renameat2(/fs1/c, /fs1/b, RENAME_EXCHANGE)"))
goto out;
err = stat(TDIR "/fs1/b", &b);
if (!ASSERT_OK(err, "stat(" TDIR "/fs1/b)"))
goto out;
if (!ASSERT_EQ(c.st_ino, b.st_ino, "b should have c's inode"))
goto out;
err = access(TDIR "/fs1/c/1", F_OK);
if (!ASSERT_OK(err, "access(" TDIR "/fs1/c/1)"))
goto out;

/* Check that RENAME_NOREPLACE works. */
err = renameat2(0, TDIR "/fs1/b", 0, TDIR "/fs1/a", RENAME_NOREPLACE);
if (!ASSERT_ERR(err, "renameat2(RENAME_NOREPLACE)")) {
err = -EINVAL;
goto out;
}
err = access(TDIR "/fs1/b", F_OK);
if (!ASSERT_OK(err, "access(" TDIR "/fs1/b)"))
goto out;

out:
umount(TDIR "/fs1");
umount(TDIR "/fs2");
Expand Down
Loading

0 comments on commit 9bea6aa

Please sign in to comment.