[PATCH v2 bpf-next 0/2] error checking where helpers call bpf_map_ops

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Within bpf programs, the bpf helper functions can make inline calls to
kernel functions. In this scenario there can be a disconnect between the
register the kernel function writes a return value to and the register the
bpf program uses to evaluate that return value.

As an example, this bpf code:

long err = bpf_map_update_elem(...);
if (err && err != -EEXIST)
	// got some error other than -EEXIST

...can result in the bpf assembly:

; err = bpf_map_update_elem(&mymap, &key, &val, BPF_NOEXIST);
  37:	movabs $0xffff976a10730400,%rdi
  41:	mov    $0x1,%ecx
  46:	call   0xffffffffe103291c	; htab_map_update_elem
; if (err && err != -EEXIST) {
  4b:	cmp    $0xffffffffffffffef,%rax ; cmp -EEXIST,%rax
  4f:	je     0x000000000000008e
  51:	test   %rax,%rax
  54:	je     0x000000000000008e

The compare operation here evaluates %rax, while in the preceding call to 
htab_map_update_elem the corresponding assembly returns -EEXIST via %eax
(the lower 32 bits of %rax):

movl $0xffffffef, %r9d
...
movl %r9d, %eax

...since it's returning int (32-bit). So the resulting comparison becomes:

cmp $0xffffffffffffffef, $0x00000000ffffffef

...making it not possible to check for negative errors or specific errors,
since the sign value is left at the 32nd bit. It means in the original
example, the conditional branch will be entered even when the error is
-EEXIST, which was not intended.

The selftests added cover these cases for the different bpf_map_ops
functions. When the second patch is applied, changing the return type of
those functions to long, the comparison works as intended and the tests
pass.

JP Kobryn (2):
  bpf/selftests: coverage for bpf_map_ops errors
  bpf: return long from bpf_map_ops funcs

 include/linux/bpf.h                           |  14 +-
 include/linux/filter.h                        |   6 +-
 kernel/bpf/arraymap.c                         |  12 +-
 kernel/bpf/bloom_filter.c                     |  12 +-
 kernel/bpf/bpf_cgrp_storage.c                 |   6 +-
 kernel/bpf/bpf_inode_storage.c                |   6 +-
 kernel/bpf/bpf_struct_ops.c                   |   6 +-
 kernel/bpf/bpf_task_storage.c                 |   6 +-
 kernel/bpf/cpumap.c                           |   8 +-
 kernel/bpf/devmap.c                           |  24 +--
 kernel/bpf/hashtab.c                          |  36 ++--
 kernel/bpf/local_storage.c                    |   6 +-
 kernel/bpf/lpm_trie.c                         |   6 +-
 kernel/bpf/queue_stack_maps.c                 |  22 +--
 kernel/bpf/reuseport_array.c                  |   2 +-
 kernel/bpf/ringbuf.c                          |   6 +-
 kernel/bpf/stackmap.c                         |   6 +-
 kernel/bpf/verifier.c                         |  14 +-
 net/core/bpf_sk_storage.c                     |   6 +-
 net/core/sock_map.c                           |   8 +-
 net/xdp/xskmap.c                              |   8 +-
 .../selftests/bpf/prog_tests/map_ops.c        | 162 ++++++++++++++++++
 .../selftests/bpf/progs/test_map_ops.c        | 138 +++++++++++++++
 23 files changed, 410 insertions(+), 110 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/map_ops.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_map_ops.c

-- 
2.39.2




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux