Merge branch 'bpf-fix-oob-accesses-in-map_delete_elem-callbacks'

Maciej Fijalkowski says:

====================
bpf: fix OOB accesses in map_delete_elem callbacks

v1->v2:
- CC stable and collect tags from Toke & John

Hi,

Jordy reported that for big enough XSKMAPs and DEVMAPs, when deleting
elements, OOB writes occur.

Reproducer below:

// compile with gcc -o map_poc map_poc.c -lbpf
#include <errno.h>
#include <linux/bpf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>

int main() {
  // Create a large enough BPF XSK map
  int map_fd;
  union bpf_attr create_attr = {
      .map_type = BPF_MAP_TYPE_XSKMAP,
      .key_size = sizeof(int),
      .value_size = sizeof(int),
      .max_entries = 0x80000000 + 2,
  };

  map_fd = syscall(SYS_bpf, BPF_MAP_CREATE, &create_attr, sizeof(create_attr));
  if (map_fd < 0) {
    fprintf(stderr, "Failed to create BPF map: %s\n", strerror(errno));
    return 1;
  }

  // Delete an element from the map using syscall
  unsigned int key = 0x80000000 + 1;
  if (syscall(SYS_bpf, BPF_MAP_DELETE_ELEM,
              &(union bpf_attr){
                  .map_fd = map_fd,
                  .key = &key,
              },
              sizeof(union bpf_attr)) < 0) {
    fprintf(stderr, "Failed to delete element from BPF map: %s\n",
            strerror(errno));
    return 1;
  }

  close(map_fd);
  return 0;
}

This tiny series changes data types from int to u32 of keys being used
for map accesses.

Thanks,
Maciej
====================

Link: https://patch.msgid.link/20241122121030.716788-1-maciej.fijalkowski@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov 2024-11-25 14:25:49 -08:00
commit 7ca0884200
2 changed files with 4 additions and 4 deletions

View File

@ -184,7 +184,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
static void dev_map_free(struct bpf_map *map)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
int i;
u32 i;
/* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
* so the programs (can be more than one that used this map) were
@ -821,7 +821,7 @@ static long dev_map_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;
@ -838,7 +838,7 @@ static long dev_map_hash_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
unsigned long flags;
int ret = -ENOENT;

View File

@ -224,7 +224,7 @@ static long xsk_map_delete_elem(struct bpf_map *map, void *key)
struct xsk_map *m = container_of(map, struct xsk_map, map);
struct xdp_sock __rcu **map_entry;
struct xdp_sock *old_xs;
int k = *(u32 *)key;
u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;