libbpf: Close map fd if init map slots failed
authorHangbin Liu <liuhangbin@gmail.com>
Tue, 6 Oct 2020 02:13:43 +0000 (10:13 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 6 Oct 2020 18:10:20 +0000 (11:10 -0700)
Previously we forgot to close the map fd if bpf_map_update_elem()
failed during map slot init, which will leak map fd.

Let's move map slot initialization to new function init_map_slots() to
simplify the code. And close the map fd if init slot failed.

Reported-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20201006021345.3817033-2-liuhangbin@gmail.com
tools/lib/bpf/libbpf.c

index 9b36c52b851195c90092fa7b15877bfed9ce7055..7cec237d9d1ff633013ae7bc45af533adad16031 100644 (file)
@@ -4203,6 +4203,36 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map)
        return 0;
 }
 
+static int init_map_slots(struct bpf_map *map)
+{
+       const struct bpf_map *targ_map;
+       unsigned int i;
+       int fd, err;
+
+       for (i = 0; i < map->init_slots_sz; i++) {
+               if (!map->init_slots[i])
+                       continue;
+
+               targ_map = map->init_slots[i];
+               fd = bpf_map__fd(targ_map);
+               err = bpf_map_update_elem(map->fd, &i, &fd, 0);
+               if (err) {
+                       err = -errno;
+                       pr_warn("map '%s': failed to initialize slot [%d] to map '%s' fd=%d: %d\n",
+                               map->name, i, targ_map->name,
+                               fd, err);
+                       return err;
+               }
+               pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n",
+                        map->name, i, targ_map->name, fd);
+       }
+
+       zfree(&map->init_slots);
+       map->init_slots_sz = 0;
+
+       return 0;
+}
+
 static int
 bpf_object__create_maps(struct bpf_object *obj)
 {
@@ -4245,28 +4275,11 @@ bpf_object__create_maps(struct bpf_object *obj)
                }
 
                if (map->init_slots_sz) {
-                       for (j = 0; j < map->init_slots_sz; j++) {
-                               const struct bpf_map *targ_map;
-                               int fd;
-
-                               if (!map->init_slots[j])
-                                       continue;
-
-                               targ_map = map->init_slots[j];
-                               fd = bpf_map__fd(targ_map);
-                               err = bpf_map_update_elem(map->fd, &j, &fd, 0);
-                               if (err) {
-                                       err = -errno;
-                                       pr_warn("map '%s': failed to initialize slot [%d] to map '%s' fd=%d: %d\n",
-                                               map->name, j, targ_map->name,
-                                               fd, err);
-                                       goto err_out;
-                               }
-                               pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n",
-                                        map->name, j, targ_map->name, fd);
+                       err = init_map_slots(map);
+                       if (err < 0) {
+                               zclose(map->fd);
+                               goto err_out;
                        }
-                       zfree(&map->init_slots);
-                       map->init_slots_sz = 0;
                }
 
                if (map->pin_path && !map->pinned) {