• Thomas Gleixner's avatar
    net/3com/3c515: Fix timer handling, prevent leaks and crashes · e28ceeb1
    Thomas Gleixner authored
    The timer handling in this driver is broken in several ways:
    
    - corkscrew_open() initializes and arms a timer before requesting the
      device interrupt. If the request fails the timer stays armed.
    
      A second call to corkscrew_open will unconditionally reinitialize the
      quued timer and arm it again. Also a immediate device removal will leave
      the timer queued because close() is not called (open() failed) and
      therefore nothing issues del_timer().
    
      The reinitialization corrupts the link chain in the timer wheel hash
      bucket and causes a NULL pointer dereference when the timer wheel tries
      to operate on that hash bucket. Immediate device removal lets the link
      chain poke into freed and possibly reused memory.
    
      Solution: Arm the timer after the successful irq request.
    
    - corkscrew_close() uses del_timer()
    
      On close the timer is disarmed with del_timer() which lets the following
      code race against a concurrent timer expiry function.
    
      Solution: Use del_timer_sync() instead
    
    - corkscrew_close() calls del_timer() unconditionally
    
      del_timer() is invoked even if the timer was never initialized. This
      works by chance because the struct containing the timer is zeroed at
      allocation time.
    
      Solution: Move the setup of the timer into corkscrew_setup().
    Reported-by: default avatarMatthew Whitehead <tedheadster@gmail.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: netdev@vger.kernel.org
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    e28ceeb1
3c515.c 48.4 KB