[lkml]   [1998]   [Jul]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    Patch in this message
    SubjectPatch against 2.0.3x for race condition in route.c

    Alan & Linux-kernel,

    This patch adds a little bit of debugging (only if RT_CACHE_DEBUG is
    set) and fixes a race condition which would cause an error
    'kfree of non-kmalloced memory: ...'
    under certain situations (one of which was easily reproducible for me,
    as it was something I wanted to actually do!).

    The race condition comes from (it appears) a call through ip_rt_unlock()
    causing ip_rt_run_bh() causing rt_kick_free_queue() which gets interrupted
    by a timer just after the sti() causing ip_rt_check_expire() to be called
    (from arp_check_expire()), where it finds ip_rt_lock == 0, grabs the lock,
    and causes a second task to enter into the rt_kick_free_queue(). As if that
    wasn't bad enough, on the exit from the second task's rt_kick_free_queue() if
    the first task hasn't been brought back yet, it calls ip_rt_unlock() which
    may cause a third entry to rt_kick_free_queue() and trigger a chain of events
    leading to over 12,000 entries to rt_kick_free_queue() inside 2 seconds.

    If any other task has done a kmalloc() between the entries to
    rt_kick_free_queue() there is a chance for a random memory scribble of
    a NULL over 4 bytes of the new allocation if a different 4 bytes of it is


    (rt_kick_free_queue runs with interrupts disabled in the sections this patch
    covers so the non-atomic increments and decrements below are safe; also
    the lack of a check for actually holding the route cache lock follows how
    things are already done in ip_rt_run_bh())

    --- linux/net/ipv4/route.c.ORIG Tue Jul 7 15:15:37 1998
    +++ linux/net/ipv4/route.c Tue Jul 7 15:17:45 1998
    @@ -925,6 +925,15 @@
    static __inline__ void rt_kick_free_queue(void)
    struct rtable *rt, **rtp;
    +#if RT_CACHE_DEBUG >= 2
    + static int in = 0;
    + if(in) {
    + printk("Attempted multiple entry: rt_kick_free_queue\n");
    + return;
    + }
    + in++;

    ip_rt_bh_mask &= ~RT_BH_FREE;

    @@ -952,6 +961,9 @@
    rtp = &rt->rt_next;
    +#if RT_CACHE_DEBUG >= 2
    + in--;

    void ip_rt_run_bh()
    @@ -974,8 +986,11 @@

    - if (ip_rt_bh_mask & RT_BH_FREE)
    + if (ip_rt_bh_mask & RT_BH_FREE) {
    + ip_rt_fast_lock();
    + ip_rt_fast_unlock();
    + }

    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to

     \ /
      Last update: 2005-03-22 13:43    [W:0.023 / U:5.104 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site