Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-06-03 Thread Mike Belopuhov
On Thu, May 28, 2015 at 23:46 +0200, Alexandr Nedvedicky wrote:
 /snip
  
   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.
 
 true, because once pf_state_insert() succeeds, it's no longer job for 
 csfailed:
 branch to clean up a state.  I currently have no better suggestion than taking
 the easiest move:
 
   add  af argument to pf_set_rt_ifp() and fetch it from skw,
   in pf_create_state().


I thought about it and I believe this is correct to assume that the
skw-af is correct even if we won't use this particular state key
object.

 Actually there is an option: 
   remove KASSERT() at 655 in pf_state_key_attach().
 659 pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int 
 idx)
 660 {
 661 struct pf_state_item*si;
 662 struct pf_state_key *cur;
 663 struct pf_state *olds = NULL;
 664
 665 KASSERT(s-key[idx] == NULL);
   Then we can simply do:
s-key[PF_SK_WIRE] = skw;
   in pf_create_state(), so pf_set_rt_ifp() will get what it expects.


This would be a hack and an overkill really.

 adding af argument to pf_set_rt_if() seems more clean approach to me.

Yep.

 below is your patch with reshuffled pf_create_state(), so pf_set_rt_ifp()
 gets called before, pf_state_insert(). I've introduced a new reason:
   PFRES_NOROUTE

Awesome.

 however I'm not sure if it is descriptive enough...


Nothing significantly better springs to mind.

I'd also mark pf_set_rt_ifp __inline and remove the marker from
the pf_create_state, but that can be done later.

OK?

 regards
 sasha
 
 
 ? create_state.diff
 ? pf.c.diff
 ? pf.c.patch
 Index: pf.c
 ===
 RCS file: /cvs/src/sys/net/pf.c,v
 retrieving revision 1.916
 diff -u -r1.916 pf.c
 --- pf.c  26 May 2015 16:17:51 -  1.916
 +++ pf.c  28 May 2015 21:38:09 -
 @@ -204,8 +204,8 @@
  u_int16_t pf_get_mss(struct pf_pdesc *);
  u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t, int,
   u_int16_t);
 -void  pf_set_rt_ifp(struct pf_state *,
 - struct pf_addr *);
 +int   pf_set_rt_ifp(struct pf_state *,
 + struct pf_addr *, sa_family_t);
  struct pf_divert *pf_get_divert(struct mbuf *);
  int   pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *,
   int, int, u_short *);
 @@ -2958,32 +2958,39 @@
   return (mss);
  }
  
 -void
 -pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
 +int
 +pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr, sa_family_t af)
  {
   struct pf_rule *r = s-rule.ptr;
   struct pf_src_node *sns[PF_SN_MAX];
 + int rv;
  
   s-rt_kif = NULL;
   if (!r-rt)
 - return;
 + return (0);
 +
   bzero(sns, sizeof(sns));
 - switch (s-key[PF_SK_WIRE]-af) {
 + switch (af) {
   case AF_INET:
 - pf_map_addr(AF_INET, r, saddr, s-rt_addr, NULL, sns,
 + rv = pf_map_addr(AF_INET, r, saddr, s-rt_addr, NULL, sns,
   r-route, PF_SN_ROUTE);
 - s-rt_kif = r-route.kif;
 - s-natrule.ptr = r;
   break;
  #ifdef INET6
   case AF_INET6:
 - pf_map_addr(AF_INET6, r, saddr, s-rt_addr, NULL, sns,
 + rv = pf_map_addr(AF_INET6, r, saddr, s-rt_addr, NULL, sns,
   

Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-28 Thread Alexandr Nedvedicky
/snip
 
  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.

true, because once pf_state_insert() succeeds, it's no longer job for csfailed:
branch to clean up a state.  I currently have no better suggestion than taking
the easiest move:

add  af argument to pf_set_rt_ifp() and fetch it from skw,
in pf_create_state().

Actually there is an option: 
remove KASSERT() at 655 in pf_state_key_attach().
659 pf_state_key_attach(struct pf_state_key *sk, struct pf_state *s, int 
idx)
660 {
661 struct pf_state_item*si;
662 struct pf_state_key *cur;
663 struct pf_state *olds = NULL;
664
665 KASSERT(s-key[idx] == NULL);
Then we can simply do:
 s-key[PF_SK_WIRE] = skw;
in pf_create_state(), so pf_set_rt_ifp() will get what it expects.

adding af argument to pf_set_rt_if() seems more clean approach to me.
below is your patch with reshuffled pf_create_state(), so pf_set_rt_ifp()
gets called before, pf_state_insert(). I've introduced a new reason:
PFRES_NOROUTE
however I'm not sure if it is descriptive enough...

regards
sasha


? create_state.diff
? pf.c.diff
? pf.c.patch
Index: pf.c
===
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.916
diff -u -r1.916 pf.c
--- pf.c26 May 2015 16:17:51 -  1.916
+++ pf.c28 May 2015 21:38:09 -
@@ -204,8 +204,8 @@
 u_int16_t   pf_get_mss(struct pf_pdesc *);
 u_int16_t   pf_calc_mss(struct pf_addr *, sa_family_t, int,
u_int16_t);
-voidpf_set_rt_ifp(struct pf_state *,
-   struct pf_addr *);
+int pf_set_rt_ifp(struct pf_state *,
+   struct pf_addr *, sa_family_t);
 struct pf_divert   *pf_get_divert(struct mbuf *);
 int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *,
int, int, u_short *);
@@ -2958,32 +2958,39 @@
return (mss);
 }
 
-void
-pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
+int
+pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr, sa_family_t af)
 {
struct pf_rule *r = s-rule.ptr;
struct pf_src_node *sns[PF_SN_MAX];
+   int rv;
 
s-rt_kif = NULL;
if (!r-rt)
-   return;
+   return (0);
+
bzero(sns, sizeof(sns));
-   switch (s-key[PF_SK_WIRE]-af) {
+   switch (af) {
case AF_INET:
-   pf_map_addr(AF_INET, r, saddr, s-rt_addr, NULL, sns,
+   rv = pf_map_addr(AF_INET, r, saddr, s-rt_addr, NULL, sns,
r-route, PF_SN_ROUTE);
-   s-rt_kif = r-route.kif;
-   s-natrule.ptr = r;
break;
 #ifdef INET6
case AF_INET6:
-   pf_map_addr(AF_INET6, r, saddr, s-rt_addr, NULL, sns,
+   rv = pf_map_addr(AF_INET6, r, saddr, s-rt_addr, NULL, sns,
r-route, PF_SN_ROUTE);
-   s-rt_kif = r-route.kif;
-   s-natrule.ptr = r;
break;
 #endif /* INET6 */
+   default:
+   rv = 1;
}
+
+   if (rv == 0) {
+   s-rt_kif = r-route.kif;
+   s-natrule.ptr = r;
+   }
+
+   return (rv);
 }
 
 u_int32_t
@@ -3557,16 +3564,6 @@
goto csfailed;
}
 
-   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
-  

Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-28 Thread Mike Belopuhov
On Thu, May 28, 2015 at 01:17 +0200, Alexandr Nedvedicky wrote:
 Hello,
 
 
 On Wed, May 27, 2015 at 07:44:15PM +0200, Mike Belopuhov wrote:
  On Wed, May 27, 2015 at 10:39 +0200, Alexandr Nedvedicky wrote:
   Hello,
   
 -   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
 -   pf_state_key_detach(s, PF_SK_STACK);
 -   pf_state_key_detach(s, PF_SK_WIRE);

This bug is not yours, but doing two pf_state_key_detach is wrong
and results in all kinds of protection fault fireworks.  The right
thing is to do pf_detach_state that would handle the case where
PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).
   good catch.
   

In csfailed case we do pf_remove_src_node and then call
pf_src_tree_remove_state.  With your diff this means that
pf_src_tree_remove_state will be dereferencing sni-sn that
might be pool_put by the pf_remove_src_node.  Therefore their
order needs to be reversed.
   
   I see. Another option to fix it would be to do:
   
 sni-sn = sns[i];
 sns[i] = NULL;
  
  
  I'm not sure I follow.  Where do you want to do it?
  If it's when we pool_get sni's, then this would mean
  we won't run pf_remove_src_node and cleanup source
  nodes that might have been created.
  
 
 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).



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-28 Thread Alexandr Nedvedicky
On Thu, May 28, 2015 at 11:43:02AM +0200, Mike Belopuhov wrote:
 On Thu, May 28, 2015 at 01:17 +0200, Alexandr Nedvedicky wrote:
  Hello,
  
  
  On Wed, May 27, 2015 at 07:44:15PM +0200, Mike Belopuhov wrote:
   On Wed, May 27, 2015 at 10:39 +0200, Alexandr Nedvedicky wrote:
Hello,

  -   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
  -   pf_state_key_detach(s, PF_SK_STACK);
  -   pf_state_key_detach(s, PF_SK_WIRE);
 
 This bug is not yours, but doing two pf_state_key_detach is wrong
 and results in all kinds of protection fault fireworks.  The right
 thing is to do pf_detach_state that would handle the case where
 PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).
good catch.

 
 In csfailed case we do pf_remove_src_node and then call
 pf_src_tree_remove_state.  With your diff this means that
 pf_src_tree_remove_state will be dereferencing sni-sn that
 might be pool_put by the pf_remove_src_node.  Therefore their
 order needs to be reversed.

I see. Another option to fix it would be to do:

sni-sn = sns[i];
sns[i] = NULL;
   
   
   I'm not sure I follow.  Where do you want to do it?
   If it's when we pool_get sni's, then this would mean
   we won't run pf_remove_src_node and cleanup source
   nodes that might have been created.
   
  
  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.
I'm not sure if we should be calling pf_remove_src_node(sns[PF_SN_ROUTE])
here since line 3572 was not executed for it, for loop at 3560 terminated
prematurely. Probably introducing new for-loop counter 'j' in csfailed:
will fix it:
 3616 for (j = 0; j  i; j++)


regards
sasha



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-28 Thread Mike Belopuhov
On Thu, May 28, 2015 at 13:34 +0200, Alexandr Nedvedicky wrote:
 On Thu, May 28, 2015 at 11:43:02AM +0200, Mike Belopuhov wrote:
  On Thu, May 28, 2015 at 01:17 +0200, Alexandr Nedvedicky wrote:
   Hello,
   
   
   On Wed, May 27, 2015 at 07:44:15PM +0200, Mike Belopuhov wrote:
On Wed, May 27, 2015 at 10:39 +0200, Alexandr Nedvedicky wrote:
 Hello,
 
   -   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, 
   s)) {
   -   pf_state_key_detach(s, PF_SK_STACK);
   -   pf_state_key_detach(s, PF_SK_WIRE);
  
  This bug is not yours, but doing two pf_state_key_detach is wrong
  and results in all kinds of protection fault fireworks.  The right
  thing is to do pf_detach_state that would handle the case where
  PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).
 good catch.
 
  
  In csfailed case we do pf_remove_src_node and then call
  pf_src_tree_remove_state.  With your diff this means that
  pf_src_tree_remove_state will be dereferencing sni-sn that
  might be pool_put by the pf_remove_src_node.  Therefore their
  order needs to be reversed.
 
 I see. Another option to fix it would be to do:
 
   sni-sn = sns[i];
   sns[i] = NULL;


I'm not sure I follow.  Where do you want to do it?
If it's when we pool_get sni's, then this would mean
we won't run pf_remove_src_node and cleanup source
nodes that might have been created.

   
   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'm not sure if we should be calling pf_remove_src_node(sns[PF_SN_ROUTE])
 here since line 3572 was not executed for it, for loop at 3560 terminated
 prematurely. Probably introducing new for-loop counter 'j' in csfailed:
 will fix it:
  3616 for (j = 0; j  i; j++)


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.

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.

 
 regards
 sasha
 



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-27 Thread Mike Belopuhov
On Wed, May 27, 2015 at 10:39 +0200, Alexandr Nedvedicky wrote:
 Hello,
 
   -   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
   -   pf_state_key_detach(s, PF_SK_STACK);
   -   pf_state_key_detach(s, PF_SK_WIRE);
  
  This bug is not yours, but doing two pf_state_key_detach is wrong
  and results in all kinds of protection fault fireworks.  The right
  thing is to do pf_detach_state that would handle the case where
  PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).
 good catch.
 
  
  In csfailed case we do pf_remove_src_node and then call
  pf_src_tree_remove_state.  With your diff this means that
  pf_src_tree_remove_state will be dereferencing sni-sn that
  might be pool_put by the pf_remove_src_node.  Therefore their
  order needs to be reversed.
 
 I see. Another option to fix it would be to do:
 
   sni-sn = sns[i];
   sns[i] = NULL;


I'm not sure I follow.  Where do you want to do it?
If it's when we pool_get sni's, then this would mean
we won't run pf_remove_src_node and cleanup source
nodes that might have been created.

 since your fix works my comment is kind of bikeshedding.
 
 regards
 sasha
 



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-27 Thread Alexandr Nedvedicky
Hello,


On Wed, May 27, 2015 at 07:44:15PM +0200, Mike Belopuhov wrote:
 On Wed, May 27, 2015 at 10:39 +0200, Alexandr Nedvedicky wrote:
  Hello,
  
-   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
-   pf_state_key_detach(s, PF_SK_STACK);
-   pf_state_key_detach(s, PF_SK_WIRE);
   
   This bug is not yours, but doing two pf_state_key_detach is wrong
   and results in all kinds of protection fault fireworks.  The right
   thing is to do pf_detach_state that would handle the case where
   PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).
  good catch.
  
   
   In csfailed case we do pf_remove_src_node and then call
   pf_src_tree_remove_state.  With your diff this means that
   pf_src_tree_remove_state will be dereferencing sni-sn that
   might be pool_put by the pf_remove_src_node.  Therefore their
   order needs to be reversed.
  
  I see. Another option to fix it would be to do:
  
  sni-sn = sns[i];
  sns[i] = NULL;
 
 
 I'm not sure I follow.  Where do you want to do it?
 If it's when we pool_get sni's, then this would mean
 we won't run pf_remove_src_node and cleanup source
 nodes that might have been created.
 

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.

regards
sasha

? pf.c.diff
? pf.c.patch
Index: pf.c
===
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.916
diff -u -r1.916 pf.c
--- pf.c26 May 2015 16:17:51 -  1.916
+++ pf.c27 May 2015 22:59:32 -
@@ -3557,16 +3557,6 @@
goto csfailed;
}
 
-   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
-   pf_state_key_detach(s, PF_SK_STACK);
-   pf_state_key_detach(s, PF_SK_WIRE);
-   *sks = *skw = NULL;
-   REASON_SET(reason, PFRES_STATEINS);
-   goto csfailed;
-   } else
-   *sm = s;
-
-   /* attach src nodes late, otherwise cleanup on error nontrivial */
for (i = 0; i  PF_SN_MAX; i++)
if (sns[i] != NULL) {
struct pf_sn_item   *sni;
@@ -3574,16 +3564,22 @@
sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
if (sni == NULL) {
REASON_SET(reason, PFRES_MEMORY);
-   pf_src_tree_remove_state(s);
-   STATE_DEC_COUNTERS(s);
-   pool_put(pf_state_pl, s);
-   return (PF_DROP);
+   goto csfailed;
}
sni-sn = sns[i];
+   sns[i] = NULL;
SLIST_INSERT_HEAD(s-src_nodes, sni, next);
sni-sn-states++;
}
 
+   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
+   pf_detach_state(s);
+   *sks = *skw = NULL;
+   REASON_SET(reason, PFRES_STATEINS);
+   goto csfailed;
+   } else
+   *sm = s;
+
pf_set_rt_ifp(s, pd-src);  /* needs s-state_key set */
if (tag  0) {
pf_tag_ref(tag);
@@ -3612,12 +3608,16 @@
return (PF_PASS);
 
 csfailed:
+   if (s) {
+   pf_normalize_tcp_cleanup(s);/* safe even w/o init */
+   pf_src_tree_remove_state(s);
+   }
+
for (i = 0; i  PF_SN_MAX; i++)
if (sns[i] != NULL)

Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-26 Thread Mike Belopuhov
On Thu, May 21, 2015 at 21:28 +0200, Alexandr Nedvedicky wrote:
 Hello,
 
 On Thu, May 21, 2015 at 07:43:51PM +0200, Mike Belopuhov wrote:
  On Thu, May 21, 2015 at 17:34 +0200, Alexandr Nedvedicky wrote:
   Hello,
  
  
  Hi,
  
   snippet below comes from pf_create_state():
   
  3559 if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, 
   s)) {
  3560 pf_state_key_detach(s, PF_SK_STACK);
  3561 pf_state_key_detach(s, PF_SK_WIRE);
  3562 *sks = *skw = NULL;
  3563 REASON_SET(reason, PFRES_STATEINS);
  3564 goto csfailed;
  3565 } else
  3566 *sm = s;
  3567 
  3568 /* attach src nodes late, otherwise cleanup on error 
   nontrivial */
  3569 for (i = 0; i  PF_SN_MAX; i++)
  3570 if (sns[i] != NULL) {
  3571 struct pf_sn_item   *sni;
  3572 
  3573 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
  3574 if (sni == NULL) {
  3575 REASON_SET(reason, PFRES_MEMORY);
  3576 pf_src_tree_remove_state(s);
  3577 STATE_DEC_COUNTERS(s);
  3578 pool_put(pf_state_pl, s);
  3579 return (PF_DROP);
  3580 }
  3581 sni-sn = sns[i];
  3582 SLIST_INSERT_HEAD(s-src_nodes, sni, 
   next);
  3583 sni-sn-states++;
  3584 }
   
   at line 3559 PF inserts state to table. If insert operation succeeds, then
   state can no longer be killed using simple pool_put() as it currently
   happens at line 3578. I think PF should go for pf_unlink_state() instead.
   
   patch below should kill the bug.
  
  
  Indeed.  But I don't like the comment stating that we're attaching
  src nodes late because the cleanup on error nontrivial.  Perhaps
  we should do a pf_state_insert afterwards?  This might simplify
  locking later on.
 
 perhaps swapping the for loop block with pf_state_insert() will work.
 We can then bail out using goto csfailed then (see patch below...)


Yup.

  we should do a pf_state_insert afterwards?  This might simplify
  locking later on.
 
 speaking of locking... everything is more complicated, however
 in this particular case it makes things easier for sure. basically in
 our current SMP model, once we insert state to table, the only way
 to remove it is to leave the job on garbage collector thread...


Right.

  
   also one more off-topic question:
   
 would you be interested in SMP patch for PF?
 it basically introduces fine locking and reference counting
 on PF data objects, so firewall can handle more packets at
 single instance of time.
  
  
  We would definitely be interested in such a diff, but at the moment
  there's no use for it as pf_test is called directly from the IP stack
  and hence IP stack needs to support parallel execution first.  This
  doesn't mean that we can't start integrating bits and pieces, esp.
  if they're presented as separate patches.
 
 we use a compile time switch to enable SMP code (-D_PF_SMP_).  this is
 something I'd like to keep around anyway. I'll start on syncing up our changes
 with CURRENT. It will take couple of weeks (ENOCYCLES as usually). Once
 I'll have something to show I'll share it and you'll see what can be done
 with it.


Cool.  Looking forward to!

  
  Thanks for your quality diffs btw, help is always much appreciated.
  
 I'm just trying to be useful. It's pleasure to work with PF sources.
 
 thanks and
 regards
 sasha


Unfortunately this diff has two nasty bugs (one is not even yours).

 ===
 RCS file: /cvs/src/sys/net/pf.c,v
 retrieving revision 1.913
 diff -u -r1.913 pf.c
 --- pf.c11 May 2015 12:22:14 -  1.913
 +++ pf.c21 May 2015 19:18:04 -
 @@ -3556,15 +3556,6 @@
 goto csfailed;
 }
 
 -   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
 -   pf_state_key_detach(s, PF_SK_STACK);
 -   pf_state_key_detach(s, PF_SK_WIRE);

This bug is not yours, but doing two pf_state_key_detach is wrong
and results in all kinds of protection fault fireworks.  The right
thing is to do pf_detach_state that would handle the case where
PF_SK_STACK == PF_SK_WIRE (i.e. we need only one invocation).

 -   *sks = *skw = NULL;
 -   REASON_SET(reason, PFRES_STATEINS);
 -   goto csfailed;
 -   } else
 -   *sm = s;
 -
 /* attach src nodes late, otherwise cleanup on error nontrivial */
 for (i = 0; i  PF_SN_MAX; i++)
 if (sns[i] != NULL) {
 @@ -3572,16 

Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-22 Thread Henning Brauer
* Alexandr Nedvedicky alexandr.nedvedi...@oracle.com [2015-05-21 21:31]:
 On Thu, May 21, 2015 at 07:43:51PM +0200, Mike Belopuhov wrote:
  On Thu, May 21, 2015 at 17:34 +0200, Alexandr Nedvedicky wrote:
   snippet below comes from pf_create_state():
   
  3559 if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, 
   s)) {
  3560 pf_state_key_detach(s, PF_SK_STACK);
  3561 pf_state_key_detach(s, PF_SK_WIRE);
  3562 *sks = *skw = NULL;
  3563 REASON_SET(reason, PFRES_STATEINS);
  3564 goto csfailed;
  3565 } else
  3566 *sm = s;
  3567 
  3568 /* attach src nodes late, otherwise cleanup on error 
   nontrivial */
  3569 for (i = 0; i  PF_SN_MAX; i++)
  3570 if (sns[i] != NULL) {
  3571 struct pf_sn_item   *sni;
  3572 
  3573 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
  3574 if (sni == NULL) {
  3575 REASON_SET(reason, PFRES_MEMORY);
  3576 pf_src_tree_remove_state(s);
  3577 STATE_DEC_COUNTERS(s);
  3578 pool_put(pf_state_pl, s);
  3579 return (PF_DROP);
  3580 }
  3581 sni-sn = sns[i];
  3582 SLIST_INSERT_HEAD(s-src_nodes, sni, 
   next);
  3583 sni-sn-states++;
  3584 }
   
   at line 3559 PF inserts state to table. If insert operation succeeds, then
   state can no longer be killed using simple pool_put() as it currently
   happens at line 3578. I think PF should go for pf_unlink_state() instead.
   patch below should kill the bug.
  Indeed.  But I don't like the comment stating that we're attaching
  src nodes late because the cleanup on error nontrivial.  Perhaps
  we should do a pf_state_insert afterwards?  This might simplify
  locking later on.
 perhaps swapping the for loop block with pf_state_insert() will work.
 We can then bail out using goto csfailed then (see patch below...)

makes sense, I like it.

 would you be interested in SMP patch for PF?
 it basically introduces fine locking and reference counting
 on PF data objects, so firewall can handle more packets at
 single instance of time.

I'd certainly like to see it.
As Mike points out, there's more to do before it can be useful for us
tho :/

  Thanks for your quality diffs btw, help is always much appreciated.

absolutely!

-- 
Henning Brauer, h...@bsws.de, henn...@openbsd.org
BS Web Services GmbH, http://bsws.de, Full-Service ISP
Secure Hosting, Mail and DNS. Virtual  Dedicated Servers, Root to Fully Managed
Henning Brauer Consulting, http://henningbrauer.com/



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-21 Thread Mike Belopuhov
On Thu, May 21, 2015 at 17:34 +0200, Alexandr Nedvedicky wrote:
 Hello,


Hi,

 snippet below comes from pf_create_state():
 
3559 if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
3560 pf_state_key_detach(s, PF_SK_STACK);
3561 pf_state_key_detach(s, PF_SK_WIRE);
3562 *sks = *skw = NULL;
3563 REASON_SET(reason, PFRES_STATEINS);
3564 goto csfailed;
3565 } else
3566 *sm = s;
3567 
3568 /* attach src nodes late, otherwise cleanup on error 
 nontrivial */
3569 for (i = 0; i  PF_SN_MAX; i++)
3570 if (sns[i] != NULL) {
3571 struct pf_sn_item   *sni;
3572 
3573 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
3574 if (sni == NULL) {
3575 REASON_SET(reason, PFRES_MEMORY);
3576 pf_src_tree_remove_state(s);
3577 STATE_DEC_COUNTERS(s);
3578 pool_put(pf_state_pl, s);
3579 return (PF_DROP);
3580 }
3581 sni-sn = sns[i];
3582 SLIST_INSERT_HEAD(s-src_nodes, sni, next);
3583 sni-sn-states++;
3584 }
 
 at line 3559 PF inserts state to table. If insert operation succeeds, then
 state can no longer be killed using simple pool_put() as it currently
 happens at line 3578. I think PF should go for pf_unlink_state() instead.
 
 patch below should kill the bug.


Indeed.  But I don't like the comment stating that we're attaching
src nodes late because the cleanup on error nontrivial.  Perhaps
we should do a pf_state_insert afterwards?  This might simplify
locking later on.

 also one more off-topic question:
 
   would you be interested in SMP patch for PF?
   it basically introduces fine locking and reference counting
   on PF data objects, so firewall can handle more packets at
   single instance of time.


We would definitely be interested in such a diff, but at the moment
there's no use for it as pf_test is called directly from the IP stack
and hence IP stack needs to support parallel execution first.  This
doesn't mean that we can't start integrating bits and pieces, esp.
if they're presented as separate patches.

Thanks for your quality diffs btw, help is always much appreciated.

Cheers,
Mike

 regards
 sasha
 
 ===
 RCS file: /cvs/src/sys/net/pf.c,v
 retrieving revision 1.913
 diff -u -r1.913 pf.c
 --- pf.c11 May 2015 12:22:14 -  1.913
 +++ pf.c21 May 2015 15:20:01 -
 @@ -3573,9 +3573,7 @@   
 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
 if (sni == NULL) {
 REASON_SET(reason, PFRES_MEMORY);
 -   pf_src_tree_remove_state(s);
 -   STATE_DEC_COUNTERS(s);
 -   pool_put(pf_state_pl, s);
 +   pf_unlink_state(s);
 return (PF_DROP);
 }
 sni-sn = sns[i];
 



Re: pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-21 Thread Alexandr Nedvedicky
Hello,

On Thu, May 21, 2015 at 07:43:51PM +0200, Mike Belopuhov wrote:
 On Thu, May 21, 2015 at 17:34 +0200, Alexandr Nedvedicky wrote:
  Hello,
 
 
 Hi,
 
  snippet below comes from pf_create_state():
  
 3559 if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
 3560 pf_state_key_detach(s, PF_SK_STACK);
 3561 pf_state_key_detach(s, PF_SK_WIRE);
 3562 *sks = *skw = NULL;
 3563 REASON_SET(reason, PFRES_STATEINS);
 3564 goto csfailed;
 3565 } else
 3566 *sm = s;
 3567 
 3568 /* attach src nodes late, otherwise cleanup on error 
  nontrivial */
 3569 for (i = 0; i  PF_SN_MAX; i++)
 3570 if (sns[i] != NULL) {
 3571 struct pf_sn_item   *sni;
 3572 
 3573 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
 3574 if (sni == NULL) {
 3575 REASON_SET(reason, PFRES_MEMORY);
 3576 pf_src_tree_remove_state(s);
 3577 STATE_DEC_COUNTERS(s);
 3578 pool_put(pf_state_pl, s);
 3579 return (PF_DROP);
 3580 }
 3581 sni-sn = sns[i];
 3582 SLIST_INSERT_HEAD(s-src_nodes, sni, next);
 3583 sni-sn-states++;
 3584 }
  
  at line 3559 PF inserts state to table. If insert operation succeeds, then
  state can no longer be killed using simple pool_put() as it currently
  happens at line 3578. I think PF should go for pf_unlink_state() instead.
  
  patch below should kill the bug.
 
 
 Indeed.  But I don't like the comment stating that we're attaching
 src nodes late because the cleanup on error nontrivial.  Perhaps
 we should do a pf_state_insert afterwards?  This might simplify
 locking later on.

perhaps swapping the for loop block with pf_state_insert() will work.
We can then bail out using goto csfailed then (see patch below...)

 we should do a pf_state_insert afterwards?  This might simplify
 locking later on.

speaking of locking... everything is more complicated, however
in this particular case it makes things easier for sure. basically in
our current SMP model, once we insert state to table, the only way
to remove it is to leave the job on garbage collector thread...

 
  also one more off-topic question:
  
  would you be interested in SMP patch for PF?
  it basically introduces fine locking and reference counting
  on PF data objects, so firewall can handle more packets at
  single instance of time.
 
 
 We would definitely be interested in such a diff, but at the moment
 there's no use for it as pf_test is called directly from the IP stack
 and hence IP stack needs to support parallel execution first.  This
 doesn't mean that we can't start integrating bits and pieces, esp.
 if they're presented as separate patches.

we use a compile time switch to enable SMP code (-D_PF_SMP_).  this is
something I'd like to keep around anyway. I'll start on syncing up our changes
with CURRENT. It will take couple of weeks (ENOCYCLES as usually). Once
I'll have something to show I'll share it and you'll see what can be done
with it.

 
 Thanks for your quality diffs btw, help is always much appreciated.
 
I'm just trying to be useful. It's pleasure to work with PF sources.

thanks and
regards
sasha

===
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.913
diff -u -r1.913 pf.c
--- pf.c11 May 2015 12:22:14 -  1.913
+++ pf.c21 May 2015 19:18:04 -
@@ -3556,15 +3556,6 @@
goto csfailed;
}

-   if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
-   pf_state_key_detach(s, PF_SK_STACK);
-   pf_state_key_detach(s, PF_SK_WIRE);
-   *sks = *skw = NULL;
-   REASON_SET(reason, PFRES_STATEINS);
-   goto csfailed;
-   } else
-   *sm = s;
-
/* attach src nodes late, otherwise cleanup on error nontrivial */
for (i = 0; i  PF_SN_MAX; i++)
if (sns[i] != NULL) {
@@ -3572,16 +3563,21 @@ 

sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
if (sni == NULL) {
-   REASON_SET(reason, PFRES_MEMORY);
-   pf_src_tree_remove_state(s);
-   STATE_DEC_COUNTERS(s);
-   pool_put(pf_state_pl, s);
-   return (PF_DROP);
+   goto csfailed;
}
sni-sn = sns[i];

pf_create_state() is sometimes better to use pf_unlink_state()

2015-05-21 Thread Alexandr Nedvedicky
Hello,

snippet below comes from pf_create_state():

   3559 if (pf_state_insert(BOUND_IFACE(r, pd-kif), skw, sks, s)) {
   3560 pf_state_key_detach(s, PF_SK_STACK);
   3561 pf_state_key_detach(s, PF_SK_WIRE);
   3562 *sks = *skw = NULL;
   3563 REASON_SET(reason, PFRES_STATEINS);
   3564 goto csfailed;
   3565 } else
   3566 *sm = s;
   3567 
   3568 /* attach src nodes late, otherwise cleanup on error nontrivial 
*/
   3569 for (i = 0; i  PF_SN_MAX; i++)
   3570 if (sns[i] != NULL) {
   3571 struct pf_sn_item   *sni;
   3572 
   3573 sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
   3574 if (sni == NULL) {
   3575 REASON_SET(reason, PFRES_MEMORY);
   3576 pf_src_tree_remove_state(s);
   3577 STATE_DEC_COUNTERS(s);
   3578 pool_put(pf_state_pl, s);
   3579 return (PF_DROP);
   3580 }
   3581 sni-sn = sns[i];
   3582 SLIST_INSERT_HEAD(s-src_nodes, sni, next);
   3583 sni-sn-states++;
   3584 }

at line 3559 PF inserts state to table. If insert operation succeeds, then
state can no longer be killed using simple pool_put() as it currently
happens at line 3578. I think PF should go for pf_unlink_state() instead.

patch below should kill the bug.

also one more off-topic question:

would you be interested in SMP patch for PF?
it basically introduces fine locking and reference counting
on PF data objects, so firewall can handle more packets at
single instance of time.

regards
sasha

===
RCS file: /cvs/src/sys/net/pf.c,v
retrieving revision 1.913
diff -u -r1.913 pf.c
--- pf.c11 May 2015 12:22:14 -  1.913
+++ pf.c21 May 2015 15:20:01 -
@@ -3573,9 +3573,7 @@   
sni = pool_get(pf_sn_item_pl, PR_NOWAIT);
if (sni == NULL) {
REASON_SET(reason, PFRES_MEMORY);
-   pf_src_tree_remove_state(s);
-   STATE_DEC_COUNTERS(s);
-   pool_put(pf_state_pl, s);
+   pf_unlink_state(s);
return (PF_DROP);
}
sni-sn = sns[i];