netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Strange samples/bpf loading error for maps on net-next?
@ 2017-04-27 11:15 Jesper Dangaard Brouer
  2017-04-28  5:49 ` Alexei Starovoitov
  0 siblings, 1 reply; 7+ messages in thread
From: Jesper Dangaard Brouer @ 2017-04-27 11:15 UTC (permalink / raw)
  To: Daniel Borkmann, Martin KaFai Lau; +Cc: brouer, netdev@vger.kernel.org


To provoke this bug, remember that you MUST call:

 make headers_install

In the kernels root directory, else you will be compiling samples/bpf/
against the older headers previously installed.

The error looks like:

 $ sudo ./sockex1
 bpf_load_program() err=22
 fd 0 is not pointing to valid bpf_map
 sockex1: [...]/samples/bpf/sockex1_user.c:26: main: Assertion `setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd, sizeof(prog_fd[0])) == 0' failed.
 Aborted

I've found that the bug were introduced in
 commit: fb30d4b71214 ("bpf: Add tests for map-in-map")

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Strange samples/bpf loading error for maps on net-next?
  2017-04-27 11:15 Strange samples/bpf loading error for maps on net-next? Jesper Dangaard Brouer
@ 2017-04-28  5:49 ` Alexei Starovoitov
  2017-04-28  6:28   ` Jesper Dangaard Brouer
  0 siblings, 1 reply; 7+ messages in thread
From: Alexei Starovoitov @ 2017-04-28  5:49 UTC (permalink / raw)
  To: Jesper Dangaard Brouer
  Cc: Daniel Borkmann, Martin KaFai Lau, netdev@vger.kernel.org, eric

On Thu, Apr 27, 2017 at 01:15:42PM +0200, Jesper Dangaard Brouer wrote:
> 
> To provoke this bug, remember that you MUST call:
> 
>  make headers_install
> 
> In the kernels root directory, else you will be compiling samples/bpf/
> against the older headers previously installed.
> 
> The error looks like:
> 
>  $ sudo ./sockex1
>  bpf_load_program() err=22
>  fd 0 is not pointing to valid bpf_map
>  sockex1: [...]/samples/bpf/sockex1_user.c:26: main: Assertion `setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd, sizeof(prog_fd[0])) == 0' failed.
>  Aborted
> 
> I've found that the bug were introduced in
>  commit: fb30d4b71214 ("bpf: Add tests for map-in-map")

Great debugging!
Indeed that change made samples/bpf/bpf_load.c to be incompatible with .o
generated earlier. We should really get rid of that loader and
switch to tools/lib/bpf/. I believe Eric Leblond already made it
resilient to 'struct bpf_map_def' changes.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Strange samples/bpf loading error for maps on net-next?
  2017-04-28  5:49 ` Alexei Starovoitov
@ 2017-04-28  6:28   ` Jesper Dangaard Brouer
  2017-04-28 14:25     ` [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong Jesper Dangaard Brouer
  0 siblings, 1 reply; 7+ messages in thread
From: Jesper Dangaard Brouer @ 2017-04-28  6:28 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Daniel Borkmann, Martin KaFai Lau, netdev@vger.kernel.org, eric,
	brouer

On Thu, 27 Apr 2017 22:49:51 -0700
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:

> On Thu, Apr 27, 2017 at 01:15:42PM +0200, Jesper Dangaard Brouer wrote:
> > 
> > To provoke this bug, remember that you MUST call:
> > 
> >  make headers_install
> > 
> > In the kernels root directory, else you will be compiling samples/bpf/
> > against the older headers previously installed.
> > 
> > The error looks like:
> > 
> >  $ sudo ./sockex1
> >  bpf_load_program() err=22
> >  fd 0 is not pointing to valid bpf_map
> >  sockex1: [...]/samples/bpf/sockex1_user.c:26: main: Assertion `setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, prog_fd, sizeof(prog_fd[0])) == 0' failed.
> >  Aborted
> > 
> > I've found that the bug were introduced in
> >  commit: fb30d4b71214 ("bpf: Add tests for map-in-map")  
> 
> Great debugging!
> Indeed that change made samples/bpf/bpf_load.c to be incompatible with .o
> generated earlier. We should really get rid of that loader and
> switch to tools/lib/bpf/. I believe Eric Leblond already made it
> resilient to 'struct bpf_map_def' changes.

Yes, exactly it is problem in samples/bpf/bpf_load.c.  As it assumes
the contents of the ELF file maps section will always chunks in
sizeof(struct bpf_map_def) and just uses that directly as a pointer to
an array of type struct bpf_map_def, which of-cause silently blows up
when changing struct bpf_map_def.  That cost me many hours to discover
that yesterday.

I started implementing more correct parsing of the ELF maps section, it
is doable, but as you say, maybe we should just get rid of this loader?
I will at least fixup bpf_load.c and perhaps just abort the program the
program if I detect a difference between the ELF size and struct size.
And send this as a patch later today...

I've also looked at the loaded Daniel implemented[1] in iproute2, and
it is much cleaner.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git/tree/lib/bpf.c
-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong
  2017-04-28  6:28   ` Jesper Dangaard Brouer
@ 2017-04-28 14:25     ` Jesper Dangaard Brouer
  2017-04-29  3:35       ` Alexei Starovoitov
  2017-05-01  2:43       ` David Miller
  0 siblings, 2 replies; 7+ messages in thread
From: Jesper Dangaard Brouer @ 2017-04-28 14:25 UTC (permalink / raw)
  To: kafai
  Cc: netdev, eric, Daniel Borkmann, Alexei Starovoitov,
	Jesper Dangaard Brouer

The struct bpf_map_def was extended in commit fb30d4b71214 ("bpf: Add tests
for map-in-map") with member unsigned int inner_map_idx.  This changed the size
of the maps section in the generated ELF _kern.o files.

Unfortunately the loader in bpf_load.c does not detect or handle this.  Thus,
older _kern.o files became incompatible, and caused hard-to-debug errors
where the syscall validation rejected BPF_MAP_CREATE request.

This patch only detect the situation and aborts load_bpf_file(). It also
add code comments warning people that read this loader for inspiration
for these pitfalls.

Fixes: fb30d4b71214 ("bpf: Add tests for map-in-map")
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
Is it worth to implement proper backward-compat loading of older ELF objects
with this bpf-loader?

 samples/bpf/bpf_load.c |   40 +++++++++++++++++++++++++++++++---------
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 0d449d8032d1..b84ac9dbff18 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -185,12 +185,16 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 	return 0;
 }
 
-static int load_maps(struct bpf_map_def *maps, int len,
+static int load_maps(struct bpf_map_def *maps, int nr_maps,
 		     const char **map_names, fixup_map_cb fixup_map)
 {
 	int i;
-
-	for (i = 0; i < len / sizeof(struct bpf_map_def); i++) {
+	/*
+	 * Warning: Using "maps" pointing to ELF data_maps->d_buf as
+	 * an array of struct bpf_map_def is a wrong assumption about
+	 * the ELF maps section format.
+	 */
+	for (i = 0; i < nr_maps; i++) {
 		if (fixup_map)
 			fixup_map(&maps[i], map_names[i], i);
 
@@ -269,6 +273,10 @@ static int parse_relo_and_apply(Elf_Data *data, Elf_Data *symbols,
 			return 1;
 		}
 		insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
+		/*
+		 * Warning: Using sizeof(struct bpf_map_def) here is a
+		 * wrong assumption about ELF maps section format
+		 */
 		insn[insn_idx].imm = map_fd[sym.st_value / sizeof(struct bpf_map_def)];
 	}
 
@@ -311,18 +319,18 @@ static int get_sorted_map_names(Elf *elf, Elf_Data *symbols, int maps_shndx,
 		map_name = elf_strptr(elf, strtabidx, map_symbols[i].st_name);
 		if (!map_name) {
 			printf("cannot get map symbol\n");
-			return 1;
+			return -1;
 		}
 
 		map_names[i] = strdup(map_name);
 		if (!map_names[i]) {
 			printf("strdup(%s): %s(%d)\n", map_name,
 			       strerror(errno), errno);
-			return 1;
+			return -1;
 		}
 	}
 
-	return 0;
+	return nr_maps;
 }
 
 static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map)
@@ -396,11 +404,25 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map)
 	}
 
 	if (data_maps) {
-		if (get_sorted_map_names(elf, symbols, maps_shndx, strtabidx,
-					 map_names))
+		int nr_maps;
+		int prog_elf_map_sz;
+
+		nr_maps = get_sorted_map_names(elf, symbols, maps_shndx,
+					       strtabidx, map_names);
+		if (nr_maps < 0)
 			goto done;
 
-		if (load_maps(data_maps->d_buf, data_maps->d_size,
+		/* Deduce map struct size stored in ELF maps section */
+		prog_elf_map_sz = data_maps->d_size / nr_maps;
+		if (prog_elf_map_sz != sizeof(struct bpf_map_def)) {
+			printf("Error: ELF maps sec wrong size (%d/%lu),"
+			       " old kern.o file?\n",
+			       prog_elf_map_sz, sizeof(struct bpf_map_def));
+			ret = 1;
+			goto done;
+		}
+
+		if (load_maps(data_maps->d_buf, nr_maps,
 			      (const char **)map_names, fixup_map))
 			goto done;
 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong
  2017-04-28 14:25     ` [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong Jesper Dangaard Brouer
@ 2017-04-29  3:35       ` Alexei Starovoitov
  2017-04-29  7:57         ` Jesper Dangaard Brouer
  2017-05-01  2:43       ` David Miller
  1 sibling, 1 reply; 7+ messages in thread
From: Alexei Starovoitov @ 2017-04-29  3:35 UTC (permalink / raw)
  To: Jesper Dangaard Brouer; +Cc: kafai, netdev, eric, Daniel Borkmann

On Fri, Apr 28, 2017 at 04:25:04PM +0200, Jesper Dangaard Brouer wrote:
> The struct bpf_map_def was extended in commit fb30d4b71214 ("bpf: Add tests
> for map-in-map") with member unsigned int inner_map_idx.  This changed the size
> of the maps section in the generated ELF _kern.o files.
> 
> Unfortunately the loader in bpf_load.c does not detect or handle this.  Thus,
> older _kern.o files became incompatible, and caused hard-to-debug errors
> where the syscall validation rejected BPF_MAP_CREATE request.
> 
> This patch only detect the situation and aborts load_bpf_file(). It also
> add code comments warning people that read this loader for inspiration
> for these pitfalls.
> 
> Fixes: fb30d4b71214 ("bpf: Add tests for map-in-map")
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>

Thanks!
Acked-by: Alexei Starovoitov <ast@kernel.org>

> Is it worth to implement proper backward-compat loading of older ELF objects
> with this bpf-loader?

probably yes, since it looks like a bunch of code in samples/bpf/ still
depend on it and some features are missing in tools/lib/bpf,
so unless we actively work on improving libbpf.a 
we won't be able to get rid of this 'sample' loader for some time.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong
  2017-04-29  3:35       ` Alexei Starovoitov
@ 2017-04-29  7:57         ` Jesper Dangaard Brouer
  0 siblings, 0 replies; 7+ messages in thread
From: Jesper Dangaard Brouer @ 2017-04-29  7:57 UTC (permalink / raw)
  To: Alexei Starovoitov; +Cc: kafai, netdev, eric, Daniel Borkmann, brouer

On Fri, 28 Apr 2017 20:35:21 -0700
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:

> On Fri, Apr 28, 2017 at 04:25:04PM +0200, Jesper Dangaard Brouer wrote:
> > The struct bpf_map_def was extended in commit fb30d4b71214 ("bpf: Add tests
> > for map-in-map") with member unsigned int inner_map_idx.  This changed the size
> > of the maps section in the generated ELF _kern.o files.
> > 
> > Unfortunately the loader in bpf_load.c does not detect or handle this.  Thus,
> > older _kern.o files became incompatible, and caused hard-to-debug errors
> > where the syscall validation rejected BPF_MAP_CREATE request.
> > 
> > This patch only detect the situation and aborts load_bpf_file(). It also
> > add code comments warning people that read this loader for inspiration
> > for these pitfalls.
> > 
> > Fixes: fb30d4b71214 ("bpf: Add tests for map-in-map")
> > Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>  
> 
> Thanks!
> Acked-by: Alexei Starovoitov <ast@kernel.org>

Thanks!

> > Is it worth to implement proper backward-compat loading of older ELF objects
> > with this bpf-loader?  
> 
> probably yes, since it looks like a bunch of code in samples/bpf/ still
> depend on it and some features are missing in tools/lib/bpf,
> so unless we actively work on improving libbpf.a 
> we won't be able to get rid of this 'sample' loader for some time.

Okay, I'll work on that next week. Hoping I can make the merge window,
so we avoid having a non-backward compat bpf_load in a kernel release.

p.s. I'll be presenting about XDP in Sweden Thur+Friday next week:
 https://lundlinuxcon.org/?page=current

-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong
  2017-04-28 14:25     ` [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong Jesper Dangaard Brouer
  2017-04-29  3:35       ` Alexei Starovoitov
@ 2017-05-01  2:43       ` David Miller
  1 sibling, 0 replies; 7+ messages in thread
From: David Miller @ 2017-05-01  2:43 UTC (permalink / raw)
  To: brouer; +Cc: kafai, netdev, eric, borkmann, alexei.starovoitov

From: Jesper Dangaard Brouer <brouer@redhat.com>
Date: Fri, 28 Apr 2017 16:25:04 +0200

> The struct bpf_map_def was extended in commit fb30d4b71214 ("bpf: Add tests
> for map-in-map") with member unsigned int inner_map_idx.  This changed the size
> of the maps section in the generated ELF _kern.o files.
> 
> Unfortunately the loader in bpf_load.c does not detect or handle this.  Thus,
> older _kern.o files became incompatible, and caused hard-to-debug errors
> where the syscall validation rejected BPF_MAP_CREATE request.
> 
> This patch only detect the situation and aborts load_bpf_file(). It also
> add code comments warning people that read this loader for inspiration
> for these pitfalls.
> 
> Fixes: fb30d4b71214 ("bpf: Add tests for map-in-map")
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>

Applied.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-05-01  2:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-27 11:15 Strange samples/bpf loading error for maps on net-next? Jesper Dangaard Brouer
2017-04-28  5:49 ` Alexei Starovoitov
2017-04-28  6:28   ` Jesper Dangaard Brouer
2017-04-28 14:25     ` [net-next PATCH V1] samples/bpf: bpf_load.c detect and abort if ELF maps section size is wrong Jesper Dangaard Brouer
2017-04-29  3:35       ` Alexei Starovoitov
2017-04-29  7:57         ` Jesper Dangaard Brouer
2017-05-01  2:43       ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).