aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2015-11-26 15:38:43 +0100
committerStephen Hemminger <shemming@brocade.com>2015-11-29 11:55:16 -0800
commit9e607f2e722604a57a2c1ec9a174fcc505d9c451 (patch)
tree492d8203e184f1b3bd451db62c04c6d806e1dca9
parent910b543dcce52290ce723758e1d9bb436188a26b (diff)
downloadandroid_external_iproute2-9e607f2e722604a57a2c1ec9a174fcc505d9c451.tar.gz
android_external_iproute2-9e607f2e722604a57a2c1ec9a174fcc505d9c451.tar.bz2
android_external_iproute2-9e607f2e722604a57a2c1ec9a174fcc505d9c451.zip
{f, m}_bpf: check map attributes when fetching as pinned
Make use of the new show_fdinfo() facility and verify that when a pinned map is being fetched that its basic attributes are the same as the map we declared from the ELF file. I.e. when placed into the globalns, collisions could occur. In such a case warn the user and bail out. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--tc/tc_bpf.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/tc/tc_bpf.c b/tc/tc_bpf.c
index c3adc23..b44b123 100644
--- a/tc/tc_bpf.c
+++ b/tc/tc_bpf.c
@@ -205,6 +205,52 @@ void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
ops[i].jf, ops[i].k);
}
+static int bpf_map_selfcheck_pinned(int fd, const struct bpf_elf_map *map)
+{
+ char file[PATH_MAX], buff[4096];
+ struct bpf_elf_map tmp, zero;
+ unsigned int val;
+ FILE *fp;
+
+ snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
+
+ fp = fopen(file, "r");
+ if (!fp) {
+ fprintf(stderr, "No procfs support?!\n");
+ return -EIO;
+ }
+
+ memset(&tmp, 0, sizeof(tmp));
+ while (fgets(buff, sizeof(buff), fp)) {
+ if (sscanf(buff, "map_type:\t%u", &val) == 1)
+ tmp.type = val;
+ else if (sscanf(buff, "key_size:\t%u", &val) == 1)
+ tmp.size_key = val;
+ else if (sscanf(buff, "value_size:\t%u", &val) == 1)
+ tmp.size_value = val;
+ else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
+ tmp.max_elem = val;
+ }
+
+ fclose(fp);
+
+ if (!memcmp(&tmp, map, offsetof(struct bpf_elf_map, id))) {
+ return 0;
+ } else {
+ memset(&zero, 0, sizeof(zero));
+ /* If kernel doesn't have eBPF-related fdinfo, we cannot do much,
+ * so just accept it. We know we do have an eBPF fd and in this
+ * case, everything is 0. It is guaranteed that no such map exists
+ * since map type of 0 is unloadable BPF_MAP_TYPE_UNSPEC.
+ */
+ if (!memcmp(&tmp, &zero, offsetof(struct bpf_elf_map, id)))
+ return 0;
+
+ fprintf(stderr, "Map specs from pinned file differ!\n");
+ return -EINVAL;
+ }
+}
+
static int bpf_valid_mntpt(const char *mnt, unsigned long magic)
{
struct statfs st_fs;
@@ -816,6 +862,13 @@ static int bpf_map_attach(const char *name, const struct bpf_elf_map *map,
fd = bpf_probe_pinned(name, map->pinning);
if (fd > 0) {
+ ret = bpf_map_selfcheck_pinned(fd, map);
+ if (ret < 0) {
+ close(fd);
+ fprintf(stderr, "Map \'%s\' self-check failed!\n",
+ name);
+ return ret;
+ }
if (verbose)
fprintf(stderr, "Map \'%s\' loaded as pinned!\n",
name);