On 28 May 2015 at 21:22, Alexandr Nedvedicky
<alexandr.nedvedi...@oracle.com> wrote:
>> > > > sorry I was too brief. The snippet below comes from
>> > > > pf_create_state() with your patch applied:
>> > > >
>> > > >    3560         for (i = 0; i < PF_SN_MAX; i++)
>> > > >    3561                 if (sns[i] != NULL) {
>> > > >    3562                         struct pf_sn_item       *sni;
>> > > >    3563
>> > > >    3564                         sni = pool_get(&pf_sn_item_pl, 
>> > > > PR_NOWAIT);
>> > > >    3565                         if (sni == NULL) {
>> > > >    3566                                 REASON_SET(&reason, 
>> > > > PFRES_MEMORY);
>> > > >    3567                                 goto csfailed;
>> > > >    3568                         }
>> > > >    3569                         sni->sn = sns[i];
>> > > >    3570                         sns[i] = NULL;
>> > > >    3571                         SLIST_INSERT_HEAD(&s->src_nodes, sni, 
>> > > > next);
>> > > >    3572                         sni->sn->states++;
>> > > >    3573                 }
>> > > >    3574
>> > > >
>> > > > the point of my suggestion is to transfer ownership of source node from
>> > > > local variable sns[] to state. so the check performed later in csfailed
>> > > > at line 3617, will find NULL pointer in sns[i] field and won't attempt
>> > > > to call pf_remove_src_node().
>> > > >
>> > > >    3610 csfailed:
>> > > >    3611         if (s) {
>> > > >    3612                 pf_normalize_tcp_cleanup(s);    /* safe even 
>> > > > w/o init */
>> > > >    3613                 pf_src_tree_remove_state(s);
>> > > >    3614         }
>> > > >    3615
>> > > >    3616         for (i = 0; i < PF_SN_MAX; i++)
>> > > >    3617                 if (sns[i] != NULL)
>> > > >    3618                         pf_remove_src_node(sns[i]);
>> > > >    3619
>> > > >
>> > > >
>> > > > your patch updated by my suggestion is further below.
>> > > >
>> > >
>> > > But that introduces a potential leak, as I said in my mail:
>> > > we won't run pf_remove_src_node and cleanup source nodes that
>> > > might have been created.
>> > >
>> > > sns[] is an array of pointers to independently tracked objects
>> > > (inserted into the pf_src_tree).
>> > >
>> >
>> > yes you are right, I was completely wrong. Still my only concern is what
>> > happens in case we fail to allocate source node item (sni) for let's say
>> > PF_SN_NAT type, while there is PF_SN_ROUTE type in sns[] to be processed.
>> >
>> > I'm referring to line numbers above. So we fail to allocate PF_SN_NAT
>> > source node and taking goto at 3567, arriving to 3610.
>> >
>> > We do the right thing for state clean up (lines 3612, 3613). And now
>> > arriving to for loop 3616, which will remove all source nodes from
>> > sns[], including PF_SN_ROUTE. I completely agree we should do
>> > pf_remove_src_node(sns[PF_SN_NAT]) as we took reference at 3572 for it.
>>
>> But we'll drop this "reference" in pf_src_tree_remove_state,
>> then how will sns[PF_SN_NAT] and sns[PF_SN_ROUTE] be different?
>
> I think I should take PF class again ;-) I've just realized there
> is a test in pf_remove_src_node():
>
>     572         if (sn->states > 0 || sn->expire > time_uptime)
>     573                 return;
>
> so it will do the right thing. This is the piece I was missing.
>
>>
>> sns[] array was prepared for this state so if we can't insert
>> the state, sns entries must be cleaned up.  pf_remove_src_node
>> checks the number of associated states and if source node should
>> expire some time later.
>
> yes, it seems more clear to me now.
>

Good! At least I wasn't blind this time! (:

>>
>> Speaking of PF_SN_ROUTE, pf_set_rt_ifp should be probably called
>> before we insert the state for the very same reason, plus it
>> should check the pf_map_addr return value and do the cleanup.
>
> I don't feel entirely qualified now, to discuss the matter ;-)

Hey, don't worry about it.  Half of the people reading this have
zero clue as to what the hell are we talking about.

> however
> pf_set_rt_ifp() should indeed test return value of pf_map_addr(), In case of
> failure the error should be thrown further up, so pf_create_state() can handle
> it. Probably jumping to csfailed: should be sufficient.
>

You can't just jump to csfailed unless you do a pf_set_rt_ifp
before the pf_state_insert, but then it needs an attached key
to only get it's address family.

> regards
> sasha

Reply via email to