Commit a0f2b7ac authored by Hangbin Liu's avatar Hangbin Liu Committed by Alexei Starovoitov
Browse files

libbpf: Close map fd if init map slots failed



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: default avatarAndrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20201006021345.3817033-2-liuhangbin@gmail.com
parent dca4121c
Loading
Loading
Loading
Loading
+34 −21
Original line number Diff line number Diff line
@@ -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);
			err = init_map_slots(map);
			if (err < 0) {
				zclose(map->fd);
				goto err_out;
			}
				pr_debug("map '%s': slot [%d] set to map '%s' fd=%d\n",
					 map->name, j, targ_map->name, fd);
			}
			zfree(&map->init_slots);
			map->init_slots_sz = 0;
		}

		if (map->pin_path && !map->pinned) {