• Duoming Zhou's avatar
    ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs · 051e0840
    Duoming Zhou authored
    The dreamcastcard->timer could schedule the spu_dma_work and the
    spu_dma_work could also arm the dreamcastcard->timer.
    
    When the snd_pcm_substream is closing, the aica_channel will be
    deallocated. But it could still be dereferenced in the worker
    thread. The reason is that del_timer() will return directly
    regardless of whether the timer handler is running or not and
    the worker could be rescheduled in the timer handler. As a result,
    the UAF bug will happen. The racy situation is shown below:
    
          (Thread 1)                 |      (Thread 2)
    snd_aicapcm_pcm_close()          |
     ...                             |  run_spu_dma() //worker
                                     |    mod_timer()
      flush_work()                   |
      del_timer()                    |  aica_period_elapsed() //timer
      kfree(dreamcastcard->channel)  |    schedule_work()
                                     |  run_spu_dma() //worker
      ...                            |    dreamcastcard->channel-> //USE
    
    In order to mitigate this bug and other possible corner cases,
    call mod_timer() conditionally in run_spu_dma(), then implement
    PCM sync_stop op to cancel both the timer and worker. The sync_stop
    op will be called from PCM core appropriately when needed.
    
    Fixes: 198de43d ("[ALSA] Add ALSA support for the SEGA Dreamcast PCM device")
    Suggested-by: default avatarTakashi Iwai <tiwai@suse.de>
    Signed-off-by: default avatarDuoming Zhou <duoming@zju.edu.cn>
    Message-ID: <20240326094238.95442-1-duoming@zju.edu.cn>
    Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
    051e0840
aica.c 16.7 KB