// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2020 Facebook */
#include <linux/bpf.h>
#include <linux/fs.h>
#include <linux/filter.h>
#include <linux/kernel.h>
#include <linux/btf_ids.h>

struct bpf_iter_seq_map_info {
	u32 map_id;
};

static void *bpf_map_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct bpf_iter_seq_map_info *info = seq->private;
	struct bpf_map *map;

	map = bpf_map_get_curr_or_next(&info->map_id);
	if (!map)
		return NULL;

	if (*pos == 0)
		++*pos;
	return map;
}

static void *bpf_map_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct bpf_iter_seq_map_info *info = seq->private;

	++*pos;
	++info->map_id;
	bpf_map_put((struct bpf_map *)v);
	return bpf_map_get_curr_or_next(&info->map_id);
}

struct bpf_iter__bpf_map {
	__bpf_md_ptr(struct bpf_iter_meta *, meta);
	__bpf_md_ptr(struct bpf_map *, map);
};

DEFINE_BPF_ITER_FUNC(bpf_map, struct bpf_iter_meta *meta, struct bpf_map *map)

static int __bpf_map_seq_show(struct seq_file *seq, void *v, bool in_stop)
{
	struct bpf_iter__bpf_map ctx;
	struct bpf_iter_meta meta;
	struct bpf_prog *prog;
	int ret = 0;

	ctx.meta = &meta;
	ctx.map = v;
	meta.seq = seq;
	prog = bpf_iter_get_info(&meta, in_stop);
	if (prog)
		ret = bpf_iter_run_prog(prog, &ctx);

	return ret;
}

static int bpf_map_seq_show(struct seq_file *seq, void *v)
{
	return __bpf_map_seq_show(seq, v, false);
}

static void bpf_map_seq_stop(struct seq_file *seq, void *v)
{
	if (!v)
		(void)__bpf_map_seq_show(seq, v, true);
	else
		bpf_map_put((struct bpf_map *)v);
}

static const struct seq_operations bpf_map_seq_ops = {
	.start	= bpf_map_seq_start,
	.next	= bpf_map_seq_next,
	.stop	= bpf_map_seq_stop,
	.show	= bpf_map_seq_show,
};

BTF_ID_LIST(btf_bpf_map_id)
BTF_ID(struct, bpf_map)

static const struct bpf_iter_seq_info bpf_map_seq_info = {
	.seq_ops		= &bpf_map_seq_ops,
	.init_seq_private	= NULL,
	.fini_seq_private	= NULL,
	.seq_priv_size		= sizeof(struct bpf_iter_seq_map_info),
};

static struct bpf_iter_reg bpf_map_reg_info = {
	.target			= "bpf_map",
	.ctx_arg_info_size	= 1,
	.ctx_arg_info		= {
		{ offsetof(struct bpf_iter__bpf_map, map),
		  PTR_TO_BTF_ID_OR_NULL },
	},
	.seq_info		= &bpf_map_seq_info,
};

static int bpf_iter_attach_map(struct bpf_prog *prog,
			       union bpf_iter_link_info *linfo,
			       struct bpf_iter_aux_info *aux)
{
	u32 key_acc_size, value_acc_size, key_size, value_size;
	struct bpf_map *map;
	bool is_percpu = false;
	int err = -EINVAL;

	if (!linfo->map.map_fd)
		return -EBADF;

	map = bpf_map_get_with_uref(linfo->map.map_fd);
	if (IS_ERR(map))
		return PTR_ERR(map);

	if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
	    map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
	    map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
		is_percpu = true;
	else if (map->map_type != BPF_MAP_TYPE_HASH &&
		 map->map_type != BPF_MAP_TYPE_LRU_HASH &&
		 map->map_type != BPF_MAP_TYPE_ARRAY)
		goto put_map;

	key_acc_size = prog->aux->max_rdonly_access;
	value_acc_size = prog->aux->max_rdwr_access;
	key_size = map->key_size;
	if (!is_percpu)
		value_size = map->value_size;
	else
		value_size = round_up(map->value_size, 8) * num_possible_cpus();

	if (key_acc_size > key_size || value_acc_size > value_size) {
		err = -EACCES;
		goto put_map;
	}

	aux->map = map;
	return 0;

put_map:
	bpf_map_put_with_uref(map);
	return err;
}

static void bpf_iter_detach_map(struct bpf_iter_aux_info *aux)
{
	bpf_map_put_with_uref(aux->map);
}

void bpf_iter_map_show_fdinfo(const struct bpf_iter_aux_info *aux,
			      struct seq_file *seq)
{
	seq_printf(seq, "map_id:\t%u\n", aux->map->id);
}

int bpf_iter_map_fill_link_info(const struct bpf_iter_aux_info *aux,
				struct bpf_link_info *info)
{
	info->iter.map.map_id = aux->map->id;
	return 0;
}

DEFINE_BPF_ITER_FUNC(bpf_map_elem, struct bpf_iter_meta *meta,
		     struct bpf_map *map, void *key, void *value)

static const struct bpf_iter_reg bpf_map_elem_reg_info = {
	.target			= "bpf_map_elem",
	.attach_target		= bpf_iter_attach_map,
	.detach_target		= bpf_iter_detach_map,
	.show_fdinfo		= bpf_iter_map_show_fdinfo,
	.fill_link_info		= bpf_iter_map_fill_link_info,
	.ctx_arg_info_size	= 2,
	.ctx_arg_info		= {
		{ offsetof(struct bpf_iter__bpf_map_elem, key),
		  PTR_TO_RDONLY_BUF_OR_NULL },
		{ offsetof(struct bpf_iter__bpf_map_elem, value),
		  PTR_TO_RDWR_BUF_OR_NULL },
	},
};

static int __init bpf_map_iter_init(void)
{
	int ret;

	bpf_map_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_map_id;
	ret = bpf_iter_reg_target(&bpf_map_reg_info);
	if (ret)
		return ret;

	return bpf_iter_reg_target(&bpf_map_elem_reg_info);
}

late_initcall(bpf_map_iter_init);
