Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add BPF_PROG_BIND_MAP syscall

This syscall binds a map to a program. Returns success if the map is
already bound to the program.

Signed-off-by: YiFei Zhu <zhuyifei@google.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Cc: YiFei Zhu <zhuyifei1999@gmail.com>
Link: https://lore.kernel.org/bpf/20200915234543.3220146-3-sdf@google.com

authored by

YiFei Zhu and committed by
Alexei Starovoitov
ef15314a 984fe94f

+77
+7
include/uapi/linux/bpf.h
··· 124 124 BPF_ENABLE_STATS, 125 125 BPF_ITER_CREATE, 126 126 BPF_LINK_DETACH, 127 + BPF_PROG_BIND_MAP, 127 128 }; 128 129 129 130 enum bpf_map_type { ··· 658 657 __u32 link_fd; 659 658 __u32 flags; 660 659 } iter_create; 660 + 661 + struct { /* struct used by BPF_PROG_BIND_MAP command */ 662 + __u32 prog_fd; 663 + __u32 map_fd; 664 + __u32 flags; /* extra flags */ 665 + } prog_bind_map; 661 666 662 667 } __attribute__((aligned(8))); 663 668
+63
kernel/bpf/syscall.c
··· 4161 4161 return err; 4162 4162 } 4163 4163 4164 + #define BPF_PROG_BIND_MAP_LAST_FIELD prog_bind_map.flags 4165 + 4166 + static int bpf_prog_bind_map(union bpf_attr *attr) 4167 + { 4168 + struct bpf_prog *prog; 4169 + struct bpf_map *map; 4170 + struct bpf_map **used_maps_old, **used_maps_new; 4171 + int i, ret = 0; 4172 + 4173 + if (CHECK_ATTR(BPF_PROG_BIND_MAP)) 4174 + return -EINVAL; 4175 + 4176 + if (attr->prog_bind_map.flags) 4177 + return -EINVAL; 4178 + 4179 + prog = bpf_prog_get(attr->prog_bind_map.prog_fd); 4180 + if (IS_ERR(prog)) 4181 + return PTR_ERR(prog); 4182 + 4183 + map = bpf_map_get(attr->prog_bind_map.map_fd); 4184 + if (IS_ERR(map)) { 4185 + ret = PTR_ERR(map); 4186 + goto out_prog_put; 4187 + } 4188 + 4189 + mutex_lock(&prog->aux->used_maps_mutex); 4190 + 4191 + used_maps_old = prog->aux->used_maps; 4192 + 4193 + for (i = 0; i < prog->aux->used_map_cnt; i++) 4194 + if (used_maps_old[i] == map) 4195 + goto out_unlock; 4196 + 4197 + used_maps_new = kmalloc_array(prog->aux->used_map_cnt + 1, 4198 + sizeof(used_maps_new[0]), 4199 + GFP_KERNEL); 4200 + if (!used_maps_new) { 4201 + ret = -ENOMEM; 4202 + goto out_unlock; 4203 + } 4204 + 4205 + memcpy(used_maps_new, used_maps_old, 4206 + sizeof(used_maps_old[0]) * prog->aux->used_map_cnt); 4207 + used_maps_new[prog->aux->used_map_cnt] = map; 4208 + 4209 + prog->aux->used_map_cnt++; 4210 + prog->aux->used_maps = used_maps_new; 4211 + 4212 + kfree(used_maps_old); 4213 + 4214 + out_unlock: 4215 + mutex_unlock(&prog->aux->used_maps_mutex); 4216 + 4217 + if (ret) 4218 + bpf_map_put(map); 4219 + out_prog_put: 4220 + bpf_prog_put(prog); 4221 + return ret; 4222 + } 4223 + 4164 4224 SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) 4165 4225 { 4166 4226 union bpf_attr attr; ··· 4353 4293 break; 4354 4294 case BPF_LINK_DETACH: 4355 4295 err = link_detach(&attr); 4296 + break; 4297 + case BPF_PROG_BIND_MAP: 4298 + err = bpf_prog_bind_map(&attr); 4356 4299 break; 4357 4300 default: 4358 4301 err = -EINVAL;
+7
tools/include/uapi/linux/bpf.h
··· 124 124 BPF_ENABLE_STATS, 125 125 BPF_ITER_CREATE, 126 126 BPF_LINK_DETACH, 127 + BPF_PROG_BIND_MAP, 127 128 }; 128 129 129 130 enum bpf_map_type { ··· 658 657 __u32 link_fd; 659 658 __u32 flags; 660 659 } iter_create; 660 + 661 + struct { /* struct used by BPF_PROG_BIND_MAP command */ 662 + __u32 prog_fd; 663 + __u32 map_fd; 664 + __u32 flags; /* extra flags */ 665 + } prog_bind_map; 661 666 662 667 } __attribute__((aligned(8))); 663 668