[Swan-dev] making coverity happy

D. Hugh Redelmeier hugh at mimosa.com
Wed Sep 6 16:11:17 UTC 2017


| From: Paul Wouters <paul at nohats.ca>

| On Wed, 6 Sep 2017, D. Hugh Redelmeier wrote:
| 
| > I just noticed this code in 0f69bb7d2d33c64739e83388e8a9e4d914a8971a
| > 
| > +                               struct payload_digest *p;
| > +                               for (p = md->chain[ISAKMP_NEXT_v2N]; p !=
| > NULL; p = p->next) {
| > +                                       if (p->payload.v2n.isan_type ==
| > v2N_SIGNATURE_HASH_ALGORITHMS)
| > +                                               break;
| > +                               }
| > +                               passert(p != NULL); /* Make Coverity happy
| > */
| > +                               if
| > (!negotiate_hash_algo_from_notification(p,st))
| >                                        return STF_FATAL;
| > 
| > The assertion may have made Coverity happy but it makes me nervous.
| > Based on purely local analysis (I haven't actually tried to understand
| > the code).
| > 
| > Is it OK for p to be NULL at this point?
| 
| It can never be NULL. A previous loop runs over md, storing the fact
| that there is a v2N_SIGNATURE_HASH_ALGORITHMS notify in seen_ntfy_hash.
| The code quoted above is wrapped in a if (seen_ntfy_hash) { } block.

Yes.  In the interest of clarity:

- the FOR should have an empty test

- the passert should be at the start of the FOR's body.

This eliminates useless redundancy.

| When we loop over it at first, we haven't commited to a state yet, so
| we cannot store it yet in st_seen_hashnotify, hence the local variable.

Right.  But it isn't a win (as I point out later).

| > - if not, the FOR loop condition is scary.
| 
| Well, I thought about making it a while(1) loop, since we KNOW the
| payload is there. It would make presumably make coverity happy, but
| that was something I found too scary to do :)

If is naturally a FOR.  With an empty test.

| > And another thing: are multiple v2N_SIGNATURE_HASH_ALGORITHMS
| > notification payloads legal?  If so, what should be done with them?
| > If not, what should be done with them?
| 
| It's not legal. There should only be one. If there are more, I'm happy
| with undefined behaviour (even if it now means "pick the first one")

Back in the good old days, I always diagnosed this kind of thing.
This seems to have been appreciated by implementors of other IKE
daemons.

| > ================
| > 
| > Along the same lines, could
| > 
| > 		if (seen_ntfy_frag)
| > 			st->st_seen_fragvid = TRUE;
| > 
| > be simplified to this?
| > 
| > 		st->st_seen_fragvid = seen_ntfy_frag;
| 
| Did you mis-paste st_seen_fragvid for st_seen_hashnotify ?

No.  I was looking at code just above "if (seen_ntfy_hash) {".

| But yes, we could do:
| 
| 		st->st_seen_hashnotify = seen_ntfy_frag;

No, you cannot.  This incorrectly handles the case where
IMPAIR_IGNORE_HASH_NOTIFY_REQUEST is selected.

| > ================
| > 
| > Perhaps, at an inconsequential cost in CPU time, the seen_ntfy_hash
| > variable could be eliminated, resulting in simpler code.  The loop is
| > moved up two levels in the control structure: one IF is eliminated and
| > one is moved inside the loop.
| > 
| > 		for (struct payload_digest *p = md->chain[ISAKMP_NEXT_v2N]; p
| > != NULL; p = p->next) {
| > 			if (p->payload.v2n.isan_type ==
| > v2N_SIGNATURE_HASH_ALGORITHMS) {
| > 				if (DBGP(IMPAIR_IGNORE_HASH_NOTIFY_REQUEST)) {
| > 					libreswan_log("Impair: Ignoring the
| > Signature hash notify in IKE_SA_INIT Request");
| > 				} else {
| > 					st->st_seen_hashnotify = TRUE;
| > 					if
| > (!negotiate_hash_algo_from_notification(p,st))
| > 						return STF_FATAL;
| > 				}
| > 				break;	/* ??? what about multiple payloads */
| > 			}
| > 		}
| > 
| > (The declaration and setting of the local variable seen_ntfy_frag can
| > then be deleted.)

This parenthetical comment is wrong.  I meant seen_ntfy_hash.

| In one of the two cases, we have not commited to creating a state yet,
| which is why the use of local variables happens. We are looping over
| the notify's to check for a DCOOKIE, and we might send a reply without
| creating a state (preventing ddos)

The code I changed is directly after a new state is created.  That is
the only code that consumes the value of the local variable
seen_ntfy_hash.

Interestingly enough, the only consumer of seen_ntfy_frag is here too.
So setting the st field could be done directly too, in the same loop,
if only it did not break upon finding v2N_SIGNATURE_HASH_ALGORITHMS.

What would happens if negotiate_hash_algo_from_notification were
called multiple times (due to multiple v2N_SIGNATURE_HASH_ALGORITHMS
payloads)?  Would the behaviour be benign?



More information about the Swan-dev mailing list