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