[nft,3/4] segtree: Fix for potential NULL-pointer deref in ei_insert()
diff mbox series

Message ID 20200120162540.9699-4-phil@nwl.cc
State Not Applicable
Delegated to: Pablo Neira
Headers show
Series
  • Fixes for a recent covscan run
Related show

Commit Message

Phil Sutter Jan. 20, 2020, 4:25 p.m. UTC
Covscan complained about potential deref of NULL 'lei' pointer,
Interestingly this can't happen as the relevant goto leading to that
(in line 260) sits in code checking conflicts between new intervals and
since those are sorted upon insertion, only the lower boundary may
conflict (or both, but that's covered before).

Given the needed investigation to proof covscan wrong and the actually
wrong (but impossible) code, better fix this as if element ordering was
arbitrary to avoid surprises if at some point it really becomes that.

Fixes: 4d6ad0f310d6c ("segtree: check for overlapping elements at insertion")
Signed-off-by: Phil Sutter <phil@nwl.cc>
---
 src/segtree.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

Comments

Pablo Neira Ayuso Jan. 21, 2020, 12:56 p.m. UTC | #1
On Mon, Jan 20, 2020 at 05:25:39PM +0100, Phil Sutter wrote:
> Covscan complained about potential deref of NULL 'lei' pointer,
> Interestingly this can't happen as the relevant goto leading to that
> (in line 260) sits in code checking conflicts between new intervals and
> since those are sorted upon insertion, only the lower boundary may
> conflict (or both, but that's covered before).
> 
> Given the needed investigation to proof covscan wrong and the actually
> wrong (but impossible) code, better fix this as if element ordering was
> arbitrary to avoid surprises if at some point it really becomes that.
> 
> Fixes: 4d6ad0f310d6c ("segtree: check for overlapping elements at insertion")

Not fixing anything. Tell them to fix covscan :-)
Phil Sutter Jan. 27, 2020, 1:24 p.m. UTC | #2
Hi Pablo,

On Tue, Jan 21, 2020 at 01:56:12PM +0100, Pablo Neira Ayuso wrote:
> On Mon, Jan 20, 2020 at 05:25:39PM +0100, Phil Sutter wrote:
> > Covscan complained about potential deref of NULL 'lei' pointer,
> > Interestingly this can't happen as the relevant goto leading to that
> > (in line 260) sits in code checking conflicts between new intervals and
> > since those are sorted upon insertion, only the lower boundary may
> > conflict (or both, but that's covered before).
> > 
> > Given the needed investigation to proof covscan wrong and the actually
> > wrong (but impossible) code, better fix this as if element ordering was
> > arbitrary to avoid surprises if at some point it really becomes that.
> > 
> > Fixes: 4d6ad0f310d6c ("segtree: check for overlapping elements at insertion")
> 
> Not fixing anything. Tell them to fix covscan :-)

Well, I guess covscan is simply not intelligent enough to detect the
impact of previous element sorting. :)

Please see my follow-up series which changes the code to actually make
use of the sorted input data. As noted in its cover letter, the code may
change again if we implement merging new with existing elements.
Depending on actual implementation, a completely different logic may be
required then since "changed" existing elements have to be recorded (so
their original version is removed from kernel).

Cheers, Phil
Phil Sutter Feb. 21, 2020, 10:07 p.m. UTC | #3
On Mon, Jan 27, 2020 at 02:24:48PM +0100, Phil Sutter wrote:
> Hi Pablo,
> 
> On Tue, Jan 21, 2020 at 01:56:12PM +0100, Pablo Neira Ayuso wrote:
> > On Mon, Jan 20, 2020 at 05:25:39PM +0100, Phil Sutter wrote:
> > > Covscan complained about potential deref of NULL 'lei' pointer,
> > > Interestingly this can't happen as the relevant goto leading to that
> > > (in line 260) sits in code checking conflicts between new intervals and
> > > since those are sorted upon insertion, only the lower boundary may
> > > conflict (or both, but that's covered before).
> > > 
> > > Given the needed investigation to proof covscan wrong and the actually
> > > wrong (but impossible) code, better fix this as if element ordering was
> > > arbitrary to avoid surprises if at some point it really becomes that.
> > > 
> > > Fixes: 4d6ad0f310d6c ("segtree: check for overlapping elements at insertion")
> > 
> > Not fixing anything. Tell them to fix covscan :-)
> 
> Well, I guess covscan is simply not intelligent enough to detect the
> impact of previous element sorting. :)

Or maybe I am not intelligent enough to read and comprehend the sorting
function. ;)

Meanwhile I managed to find a reproducer for covscan's complaint:

With a ruleset of:

| table ip t {
| 	set s {
| 		type inet_service
| 		flags interval
| 	}
| }

The following command segfaults:

| # nft add element t s '{ 10-40, 5-15 }'

According to gdb it happens the line above
'return expr_binary_error(...)' in ei_insert(), namely segtree.c:279. No
idea why it's in the wrong line, but it seems to be just the reported
issue as 'lei' is NULL.

Interestingly, adding a rule with an anonymous set and the same elements
works fine, no idea why.

What do you think, should I continue investigating or can we just go
with my original fix (for now at least)?

Cheers, Phil

Patch
diff mbox series

diff --git a/src/segtree.c b/src/segtree.c
index e8e32412f3a41..04c0e915263b9 100644
--- a/src/segtree.c
+++ b/src/segtree.c
@@ -205,8 +205,11 @@  static int ei_insert(struct list_head *msgs, struct seg_tree *tree,
 		pr_gmp_debug("insert: [%Zx %Zx]\n", new->left, new->right);
 
 	if (lei != NULL && rei != NULL && lei == rei) {
-		if (!merge)
+		if (!merge) {
+			expr_binary_error(msgs, lei->expr, new->expr,
+					  "conflicting intervals specified");
 			goto err;
+		}
 		/*
 		 * The new interval is entirely contained in the same interval,
 		 * split it into two parts:
@@ -228,8 +231,11 @@  static int ei_insert(struct list_head *msgs, struct seg_tree *tree,
 		ei_destroy(lei);
 	} else {
 		if (lei != NULL) {
-			if (!merge)
+			if (!merge) {
+				expr_binary_error(msgs, lei->expr, new->expr,
+						  "conflicting intervals specified");
 				goto err;
+			}
 			/*
 			 * Left endpoint is within lei, adjust it so we have:
 			 *
@@ -248,8 +254,11 @@  static int ei_insert(struct list_head *msgs, struct seg_tree *tree,
 			}
 		}
 		if (rei != NULL) {
-			if (!merge)
+			if (!merge) {
+				expr_binary_error(msgs, rei->expr, new->expr,
+						  "conflicting intervals specified");
 				goto err;
+			}
 			/*
 			 * Right endpoint is within rei, adjust it so we have:
 			 *
@@ -276,8 +285,7 @@  static int ei_insert(struct list_head *msgs, struct seg_tree *tree,
 	return 0;
 err:
 	errno = EEXIST;
-	return expr_binary_error(msgs, lei->expr, new->expr,
-				 "conflicting intervals specified");
+	return -1;
 }
 
 /*