Skip to content

Commit bd513cd

Browse files
mauriciovasquezbernalAlexei Starovoitov
authored andcommitted
bpf: add MAP_LOOKUP_AND_DELETE_ELEM syscall
The previous patch implemented a bpf queue/stack maps that provided the peek/pop/push functions. There is not a direct relationship between those functions and the current maps syscalls, hence a new MAP_LOOKUP_AND_DELETE_ELEM syscall is added, this is mapped to the pop operation in the queue/stack maps and it is still to implement in other kind of maps. Signed-off-by: Mauricio Vasquez B <[email protected]> Acked-by: Song Liu <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent f1a2e44 commit bd513cd

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ enum bpf_cmd {
103103
BPF_BTF_LOAD,
104104
BPF_BTF_GET_FD_BY_ID,
105105
BPF_TASK_FD_QUERY,
106+
BPF_MAP_LOOKUP_AND_DELETE_ELEM,
106107
};
107108

108109
enum bpf_map_type {

kernel/bpf/syscall.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,69 @@ static int map_get_next_key(union bpf_attr *attr)
999999
return err;
10001000
}
10011001

1002+
#define BPF_MAP_LOOKUP_AND_DELETE_ELEM_LAST_FIELD value
1003+
1004+
static int map_lookup_and_delete_elem(union bpf_attr *attr)
1005+
{
1006+
void __user *ukey = u64_to_user_ptr(attr->key);
1007+
void __user *uvalue = u64_to_user_ptr(attr->value);
1008+
int ufd = attr->map_fd;
1009+
struct bpf_map *map;
1010+
void *key, *value, *ptr;
1011+
u32 value_size;
1012+
struct fd f;
1013+
int err;
1014+
1015+
if (CHECK_ATTR(BPF_MAP_LOOKUP_AND_DELETE_ELEM))
1016+
return -EINVAL;
1017+
1018+
f = fdget(ufd);
1019+
map = __bpf_map_get(f);
1020+
if (IS_ERR(map))
1021+
return PTR_ERR(map);
1022+
1023+
if (!(f.file->f_mode & FMODE_CAN_WRITE)) {
1024+
err = -EPERM;
1025+
goto err_put;
1026+
}
1027+
1028+
key = __bpf_copy_key(ukey, map->key_size);
1029+
if (IS_ERR(key)) {
1030+
err = PTR_ERR(key);
1031+
goto err_put;
1032+
}
1033+
1034+
value_size = map->value_size;
1035+
1036+
err = -ENOMEM;
1037+
value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
1038+
if (!value)
1039+
goto free_key;
1040+
1041+
if (map->map_type == BPF_MAP_TYPE_QUEUE ||
1042+
map->map_type == BPF_MAP_TYPE_STACK) {
1043+
err = map->ops->map_pop_elem(map, value);
1044+
} else {
1045+
err = -ENOTSUPP;
1046+
}
1047+
1048+
if (err)
1049+
goto free_value;
1050+
1051+
if (copy_to_user(uvalue, value, value_size) != 0)
1052+
goto free_value;
1053+
1054+
err = 0;
1055+
1056+
free_value:
1057+
kfree(value);
1058+
free_key:
1059+
kfree(key);
1060+
err_put:
1061+
fdput(f);
1062+
return err;
1063+
}
1064+
10021065
static const struct bpf_prog_ops * const bpf_prog_types[] = {
10031066
#define BPF_PROG_TYPE(_id, _name) \
10041067
[_id] = & _name ## _prog_ops,
@@ -2472,6 +2535,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
24722535
case BPF_TASK_FD_QUERY:
24732536
err = bpf_task_fd_query(&attr, uattr);
24742537
break;
2538+
case BPF_MAP_LOOKUP_AND_DELETE_ELEM:
2539+
err = map_lookup_and_delete_elem(&attr);
2540+
break;
24752541
default:
24762542
err = -EINVAL;
24772543
break;

0 commit comments

Comments
 (0)