tree 2d5ec53192186cdc9171ed4d2bb36316385edd56
parent 2bd6c95c3a00dadee6378e13c699006830d7e8e0
author Neil Horman <[EMAIL PROTECTED]> Wed, 27 Jul 2005 03:30:06 -0700
committer David S. Miller <[EMAIL PROTECTED]> Wed, 27 Jul 2005 03:30:06 -0700

[IPVS]: Close race conditions on ip_vs_conn_tab list modification

In an smp system, it is possible for an connection timer to expire, calling
ip_vs_conn_expire while the connection table is being flushed, before
ct_write_lock_bh is acquired.

Since the list iterator loop in ip_vs_con_flush releases and re-acquires the
spinlock (even though it doesn't re-enable softirqs), it is possible for the
expiration function to modify the connection list, while it is being traversed
in ip_vs_conn_flush.

The result is that the next pointer gets set to NULL, and subsequently
dereferenced, resulting in an oops.

Signed-off-by: Neil Horman <[EMAIL PROTECTED]>
Acked-by: JulianAnastasov
Signed-off-by: David S. Miller <[EMAIL PROTECTED]>

 net/ipv4/ipvs/ip_vs_conn.c |   25 ++++---------------------
 1 files changed, 4 insertions(+), 21 deletions(-)

diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -1248,7 +1248,6 @@ void ip_vs_conn_expire_now(struct ip_vs_
 {
        cp->timeout = 0;
        mod_timer(&cp->timer, jiffies);
-       __ip_vs_conn_put(cp);
 }
 
 /*
@@ -1414,7 +1413,6 @@ void ip_vs_random_dropentry(void)
        int idx;
        struct ip_vs_conn *cp;
        struct list_head *l,*e;
-       struct ip_vs_conn *ct;
 
        /*
         * Randomly scan 1/32 of the whole table every second
@@ -1448,21 +1446,12 @@ void ip_vs_random_dropentry(void)
                                continue;
                        }
 
-                       /*
-                        * Drop the entry, and drop its ct if not referenced
-                        */
-                       atomic_inc(&cp->refcnt);
-                       ct_write_unlock(hash);
-
-                       if ((ct = cp->control))
-                               atomic_inc(&ct->refcnt);
                        IP_VS_DBG(4, "del connection\n");
                        ip_vs_conn_expire_now(cp);
-                       if (ct) {
+                       if (cp->control) {
                                IP_VS_DBG(4, "del conn template\n");
-                               ip_vs_conn_expire_now(ct);
+                               ip_vs_conn_expire_now(cp->control);
                        }
-                       ct_write_lock(hash);
                }
                ct_write_unlock(hash);
        }
@@ -1477,7 +1466,6 @@ static void ip_vs_conn_flush(void)
        int idx;
        struct ip_vs_conn *cp;
        struct list_head *l,*e;
-       struct ip_vs_conn *ct;
 
   flush_again:
        for (idx=0; idx<IP_VS_CONN_TAB_SIZE; idx++) {
@@ -1489,18 +1477,13 @@ static void ip_vs_conn_flush(void)
                l = &ip_vs_conn_tab[idx];
                for (e=l->next; e!=l; e=e->next) {
                        cp = list_entry(e, struct ip_vs_conn, c_list);
-                       atomic_inc(&cp->refcnt);
-                       ct_write_unlock(idx);
 
-                       if ((ct = cp->control))
-                               atomic_inc(&ct->refcnt);
                        IP_VS_DBG(4, "del connection\n");
                        ip_vs_conn_expire_now(cp);
-                       if (ct) {
+                       if (cp->control) {
                                IP_VS_DBG(4, "del conn template\n");
-                               ip_vs_conn_expire_now(ct);
+                               ip_vs_conn_expire_now(cp->control);
                        }
-                       ct_write_lock(idx);
                }
                ct_write_unlock_bh(idx);
        }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-24" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to