Re: [PATCH v3] netfilter: ipset: Fix serious failure in CIDR tracking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday 11 September 2013 21:32:26 Jozsef Kadlecsik wrote:
> On Wed, 11 Sep 2013, Oliver wrote:
> > On Wednesday 11 September 2013 16:01:18 Jozsef Kadlecsik wrote:
> > > On Wed, 11 Sep 2013, Oliver wrote:
<snip>
> > > 
> > > If you restored the original code in the part above, then the whole
> > > thing
> > > could be collapsed into starting the next loop from j = i + 1 (and
> > > changing the indices in the for body accordingly).
> > 
> > I'm not sure I follow; the whole problem is that the proceeding loop
> > fails because the element at j gets set to zero, causing it to be
> > skipped when we do our shift-up below - why would we want to bother with
> > looping when we can just decrement and return immediately?
> 
> The for loop below would not be started due to the conditions: actually,
> then conditions above ("i == net_end || !h->nets[i + 1].nets[n]") would be
> "moved" here. In another words, would not be duplicated:
> 
> 	for (j = i + 1; j < nets_length - 1 && h->nets[j].nets[n]; j++)
> 		h->nets[j - 1].cidr[n] = h->nets[j + 1].cidr[n];
> 		..
> 	}
> 	if (j < nets_length)
> 		h->nets[j - 1].nets[n] = 0;
> 

I don't really like this idea; i + 1 after the second iteration will point to 
whatever was shifted up, this obviously doesn't really present a problem since 
if the element is empty, we won't iterate any more, but I don't think it looks 
good for code clarity and it's just going to be a non-changing value that the 
processor must pointlessly compare on every iteration (first and second run 
notwithstanding).

Checking i against net_end is not a problem either, but again, I don't see why 
we would want to make the processor pointlessly recompare something that is 
guaranteed to be true on every iteration, especially since it's not going to 
make the code "simpler" or easier to follow.

> > > > -	for (j = i; j < nets_length - 1 && h->nets[j].nets[n]; j++) {
> > > > +	for (j = i; j < net_end && h->nets[j].nets[n]; j++) {
> > > > 
> > > >  		h->nets[j].cidr[n] = h->nets[j + 1].cidr[n];
> > > >  		h->nets[j].nets[n] = h->nets[j + 1].nets[n];
> > > >  	
> > > >  	}
> > > > 
> > > > +	h->nets[j].nets[n] = 0;
> > > 
> > > Here the checking of the value "j" is missing.
> > 
> > I suppose we can check this, but what's the point really? j is always
> > going to be nets_length - 1, so setting that element to zero is either
> > necessary for cleanup, or won't do anything of use (nor harm) - why add
> > in a memory read to see if we need to do a memory write when there's no
> > harm in just doing it regardless?
> 
> What is the difference between the first for loop in this function and
> this second one, from the loop variable point of view? Or, what is the
> value of "j" after the for loop, if all nets[j] slots are filled up?

Sorry, I explained this inaccurately; obviously if the array is not completely 
filled, the last element is going to be taken care of by virtue of the fact 
that j+1 would have had to be zero, thereby making the unconditional write 
after the loop basically a do-nothing operation. However, if it was completely 
filled, we *do* then need to zero it since net_end would be the reason for 
termination of loop iteration, leaving the old "copy" of the net element right 
at the end. So the question is, what is faster - reading and checking if we 
need to write the memory location before we do so, or just unconditionally 
writing it? Evidently in most cases the value is most likely going to be 0 
already, so is a mem write slower than a read and compare? Do we really care 
that much?

In any case, I do see scope for redoing the flow so that we just do everything 
we need under the very first for loop in the function, so I'll refactor it 
accordingly and mail it out. But, I would prefer not to be pontificating over 
syntactic sugar. Anything to do with errors I'll of course happily discuss 
endlessly, so if you believe one still exists, no problem.

My hope was to get a change in that fixes the issue with minimal reorganisation 
of the code flow so that anyone looking at it later on can see, relatively 
quickly, exactly what was done to resolve the issue - if you want to then 
clean up the semantics too, fine, throw that in as a separate commit - that 
also avoids undermining git bisect should the clean-up introduce its own 
errors, somehow.

Kind Regards,
Oliver.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux