netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [iproute PATCH] lib/bpf: Fix bytecode-file parsing
@ 2017-08-29 15:09 Phil Sutter
  2017-08-30 13:53 ` Daniel Borkmann
  2017-09-04 19:09 ` Stephen Hemminger
  0 siblings, 2 replies; 5+ messages in thread
From: Phil Sutter @ 2017-08-29 15:09 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Daniel Borkmann

The signedness of char type is implementation dependent, and there are
architectures on which it is unsigned by default. In that case, the
check whether fgetc() returned EOF failed because the return value was
assigned an (unsigned) char variable prior to comparison with EOF (which
is defined to -1). Fix this by using int as type for 'c' variable, which
also matches the declaration of fgetc().

While being at it, fix the parser logic to correctly handle multiple
empty lines and consecutive whitespace and tab characters to further
improve the parser's robustness. Note that this will still detect double
separator characters, so doesn't soften up the parser too much.

Fixes: 3da3ebfca85b8 ("bpf: Make bytecode-file reading a little more robust")
Cc: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 lib/bpf.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lib/bpf.c b/lib/bpf.c
index 0bd0a95eafe6c..77eb8ee27114f 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -208,8 +208,9 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
 
 	if (from_file) {
 		size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,");
-		char *tmp_string, *pos, c, c_prev = ' ';
+		char *tmp_string, *pos, c_prev = ' ';
 		FILE *fp;
+		int c;
 
 		tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len;
 		tmp_string = pos = calloc(1, tmp_len);
@@ -228,18 +229,20 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
 			case '\n':
 				if (c_prev != ',')
 					*(pos++) = ',';
+				c_prev = ',';
 				break;
 			case ' ':
 			case '\t':
 				if (c_prev != ' ')
 					*(pos++) = c;
+				c_prev = ' ';
 				break;
 			default:
 				*(pos++) = c;
+				c_prev = c;
 			}
 			if (pos - tmp_string == tmp_len)
 				break;
-			c_prev = c;
 		}
 
 		if (!feof(fp)) {
-- 
2.13.1

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

* Re: [iproute PATCH] lib/bpf: Fix bytecode-file parsing
  2017-08-29 15:09 [iproute PATCH] lib/bpf: Fix bytecode-file parsing Phil Sutter
@ 2017-08-30 13:53 ` Daniel Borkmann
  2017-08-30 14:11   ` Phil Sutter
  2017-09-04 19:09 ` Stephen Hemminger
  1 sibling, 1 reply; 5+ messages in thread
From: Daniel Borkmann @ 2017-08-30 13:53 UTC (permalink / raw)
  To: Phil Sutter, Stephen Hemminger; +Cc: netdev

On 08/29/2017 05:09 PM, Phil Sutter wrote:
> The signedness of char type is implementation dependent, and there are
> architectures on which it is unsigned by default. In that case, the
> check whether fgetc() returned EOF failed because the return value was
> assigned an (unsigned) char variable prior to comparison with EOF (which
> is defined to -1). Fix this by using int as type for 'c' variable, which
> also matches the declaration of fgetc().
>
> While being at it, fix the parser logic to correctly handle multiple
> empty lines and consecutive whitespace and tab characters to further
> improve the parser's robustness. Note that this will still detect double
> separator characters, so doesn't soften up the parser too much.
>
> Fixes: 3da3ebfca85b8 ("bpf: Make bytecode-file reading a little more robust")
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Signed-off-by: Phil Sutter <phil@nwl.cc>

Definitely ack on the EOF bug:

Acked-by: Daniel Borkmann <daniel@iogearbox.net>

[...]
> @@ -228,18 +229,20 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
>   			case '\n':
>   				if (c_prev != ',')
>   					*(pos++) = ',';
> +				c_prev = ',';
>   				break;
>   			case ' ':
>   			case '\t':
>   				if (c_prev != ' ')
>   					*(pos++) = c;
> +				c_prev = ' ';
>   				break;
>   			default:
>   				*(pos++) = c;
> +				c_prev = c;
>   			}
>   			if (pos - tmp_string == tmp_len)
>   				break;
> -			c_prev = c;

I don't really have a strong opinion on this, but the logic for
normalizing here is getting a bit convoluted. Is your use case
for making the parser more robust mainly so you can just use the
-ddd output from tcpdump for cBPF w/o piping through tr? But even
that shouldn't give multiple empty lines afaik, no?

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

* Re: [iproute PATCH] lib/bpf: Fix bytecode-file parsing
  2017-08-30 13:53 ` Daniel Borkmann
@ 2017-08-30 14:11   ` Phil Sutter
  2017-09-01 19:13     ` Daniel Borkmann
  0 siblings, 1 reply; 5+ messages in thread
From: Phil Sutter @ 2017-08-30 14:11 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: Stephen Hemminger, netdev

Hi Daniel,

On Wed, Aug 30, 2017 at 03:53:59PM +0200, Daniel Borkmann wrote:
> On 08/29/2017 05:09 PM, Phil Sutter wrote:
[...]
> > @@ -228,18 +229,20 @@ static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len,
> >   			case '\n':
> >   				if (c_prev != ',')
> >   					*(pos++) = ',';
> > +				c_prev = ',';
> >   				break;
> >   			case ' ':
> >   			case '\t':
> >   				if (c_prev != ' ')
> >   					*(pos++) = c;
> > +				c_prev = ' ';
> >   				break;
> >   			default:
> >   				*(pos++) = c;
> > +				c_prev = c;
> >   			}
> >   			if (pos - tmp_string == tmp_len)
> >   				break;
> > -			c_prev = c;
> 
> I don't really have a strong opinion on this, but the logic for
> normalizing here is getting a bit convoluted. Is your use case
> for making the parser more robust mainly so you can just use the
> -ddd output from tcpdump for cBPF w/o piping through tr? But even
> that shouldn't give multiple empty lines afaik, no?

Well, using tcpdump output was functional before already. I just noticed
that if I add an empty line to the end of bytecode-file, it will fail
and I didn't like that. Then while searching for the EOF issue, I
noticed that the parser logic above is a bit faulty in that it will
treat different characters equally but doesn't make sure c_prev will be
assigned only one of them. So apart from the added robustness, it really
fixes an inconsistency in the parsing logic.

Cheers, Phil

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

* Re: [iproute PATCH] lib/bpf: Fix bytecode-file parsing
  2017-08-30 14:11   ` Phil Sutter
@ 2017-09-01 19:13     ` Daniel Borkmann
  0 siblings, 0 replies; 5+ messages in thread
From: Daniel Borkmann @ 2017-09-01 19:13 UTC (permalink / raw)
  To: Phil Sutter, Stephen Hemminger, netdev

On 08/30/2017 04:11 PM, Phil Sutter wrote:
> On Wed, Aug 30, 2017 at 03:53:59PM +0200, Daniel Borkmann wrote:
>> On 08/29/2017 05:09 PM, Phil Sutter wrote:
[...]
>>
>> I don't really have a strong opinion on this, but the logic for
>> normalizing here is getting a bit convoluted. Is your use case
>> for making the parser more robust mainly so you can just use the
>> -ddd output from tcpdump for cBPF w/o piping through tr? But even
>> that shouldn't give multiple empty lines afaik, no?
>
> Well, using tcpdump output was functional before already. I just noticed
> that if I add an empty line to the end of bytecode-file, it will fail
> and I didn't like that. Then while searching for the EOF issue, I
> noticed that the parser logic above is a bit faulty in that it will
> treat different characters equally but doesn't make sure c_prev will be
> assigned only one of them. So apart from the added robustness, it really
> fixes an inconsistency in the parsing logic.

Ok, fine by me.

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

* Re: [iproute PATCH] lib/bpf: Fix bytecode-file parsing
  2017-08-29 15:09 [iproute PATCH] lib/bpf: Fix bytecode-file parsing Phil Sutter
  2017-08-30 13:53 ` Daniel Borkmann
@ 2017-09-04 19:09 ` Stephen Hemminger
  1 sibling, 0 replies; 5+ messages in thread
From: Stephen Hemminger @ 2017-09-04 19:09 UTC (permalink / raw)
  To: Phil Sutter; +Cc: netdev, Daniel Borkmann

On Tue, 29 Aug 2017 17:09:45 +0200
Phil Sutter <phil@nwl.cc> wrote:

> The signedness of char type is implementation dependent, and there are
> architectures on which it is unsigned by default. In that case, the
> check whether fgetc() returned EOF failed because the return value was
> assigned an (unsigned) char variable prior to comparison with EOF (which
> is defined to -1). Fix this by using int as type for 'c' variable, which
> also matches the declaration of fgetc().
> 
> While being at it, fix the parser logic to correctly handle multiple
> empty lines and consecutive whitespace and tab characters to further
> improve the parser's robustness. Note that this will still detect double
> separator characters, so doesn't soften up the parser too much.
> 
> Fixes: 3da3ebfca85b8 ("bpf: Make bytecode-file reading a little more robust")
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Signed-off-by: Phil Sutter <phil@nwl.cc>

Looks fine applied.

Although I think only Android is using unsigned for char type at this point.

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

end of thread, other threads:[~2017-09-04 19:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-29 15:09 [iproute PATCH] lib/bpf: Fix bytecode-file parsing Phil Sutter
2017-08-30 13:53 ` Daniel Borkmann
2017-08-30 14:11   ` Phil Sutter
2017-09-01 19:13     ` Daniel Borkmann
2017-09-04 19:09 ` Stephen Hemminger

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).