• Takashi Iwai's avatar
    ALSA: rawmidi: Make snd_rawmidi_transmit() race-free · 06ab3003
    Takashi Iwai authored
    A kernel WARNING in snd_rawmidi_transmit_ack() is triggered by
    syzkaller fuzzer:
      WARNING: CPU: 1 PID: 20739 at sound/core/rawmidi.c:1136
    Call Trace:
     [<     inline     >] __dump_stack lib/dump_stack.c:15
     [<ffffffff82999e2d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
     [<ffffffff81352089>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
     [<ffffffff813522b9>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
     [<ffffffff84f80bd5>] snd_rawmidi_transmit_ack+0x275/0x400 sound/core/rawmidi.c:1136
     [<ffffffff84fdb3c1>] snd_virmidi_output_trigger+0x4b1/0x5a0 sound/core/seq/seq_virmidi.c:163
     [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
     [<ffffffff84f87ed9>] snd_rawmidi_kernel_write1+0x549/0x780 sound/core/rawmidi.c:1223
     [<ffffffff84f89fd3>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1273
     [<ffffffff817b0323>] __vfs_write+0x113/0x480 fs/read_write.c:528
     [<ffffffff817b1db7>] vfs_write+0x167/0x4a0 fs/read_write.c:577
     [<     inline     >] SYSC_write fs/read_write.c:624
     [<ffffffff817b50a1>] SyS_write+0x111/0x220 fs/read_write.c:616
     [<ffffffff86336c36>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
    
    Also a similar warning is found but in another path:
    Call Trace:
     [<     inline     >] __dump_stack lib/dump_stack.c:15
     [<ffffffff82be2c0d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
     [<ffffffff81355139>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
     [<ffffffff81355369>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
     [<ffffffff8527e69a>] rawmidi_transmit_ack+0x24a/0x3b0 sound/core/rawmidi.c:1133
     [<ffffffff8527e851>] snd_rawmidi_transmit_ack+0x51/0x80 sound/core/rawmidi.c:1163
     [<ffffffff852d9046>] snd_virmidi_output_trigger+0x2b6/0x570 sound/core/seq/seq_virmidi.c:185
     [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
     [<ffffffff85285a0b>] snd_rawmidi_kernel_write1+0x4bb/0x760 sound/core/rawmidi.c:1252
     [<ffffffff85287b73>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1302
     [<ffffffff817ba5f3>] __vfs_write+0x113/0x480 fs/read_write.c:528
     [<ffffffff817bc087>] vfs_write+0x167/0x4a0 fs/read_write.c:577
     [<     inline     >] SYSC_write fs/read_write.c:624
     [<ffffffff817bf371>] SyS_write+0x111/0x220 fs/read_write.c:616
     [<ffffffff86660276>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
    
    In the former case, the reason is that virmidi has an open code
    calling snd_rawmidi_transmit_ack() with the value calculated outside
    the spinlock.   We may use snd_rawmidi_transmit() in a loop just for
    consuming the input data, but even there, there is a race between
    snd_rawmidi_transmit_peek() and snd_rawmidi_tranmit_ack().
    
    Similarly in the latter case, it calls snd_rawmidi_transmit_peek() and
    snd_rawmidi_tranmit_ack() separately without protection, so they are
    racy as well.
    
    The patch tries to address these issues by the following ways:
    - Introduce the unlocked versions of snd_rawmidi_transmit_peek() and
      snd_rawmidi_transmit_ack() to be called inside the explicit lock.
    - Rewrite snd_rawmidi_transmit() to be race-free (the former case).
    - Make the split calls (the latter case) protected in the rawmidi spin
      lock.
    
    BugLink: http://lkml.kernel.org/r/CACT4Y+YPq1+cYLkadwjWa5XjzF1_Vki1eHnVn-Lm0hzhSpu5PA@mail.gmail.com
    BugLink: http://lkml.kernel.org/r/CACT4Y+acG4iyphdOZx47Nyq_VHGbpJQK-6xNpiqUjaZYqsXOGw@mail.gmail.comReported-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
    06ab3003
Name
Last commit
Last update
..
ac97_codec.h Loading commit data...
aci.h Loading commit data...
ad1816a.h Loading commit data...
ad1843.h Loading commit data...
adau1373.h Loading commit data...
aess.h Loading commit data...
ak4113.h Loading commit data...
ak4114.h Loading commit data...
ak4117.h Loading commit data...
ak4531_codec.h Loading commit data...
ak4641.h Loading commit data...
ak4xxx-adda.h Loading commit data...
alc5623.h Loading commit data...
asequencer.h Loading commit data...
asound.h Loading commit data...
asoundef.h Loading commit data...
atmel-abdac.h Loading commit data...
atmel-ac97c.h Loading commit data...
compress_driver.h Loading commit data...
control.h Loading commit data...
core.h Loading commit data...
cs4231-regs.h Loading commit data...
cs4271.h Loading commit data...
cs42l52.h Loading commit data...
cs42l56.h Loading commit data...
cs42l73.h Loading commit data...
cs8403.h Loading commit data...
cs8427.h Loading commit data...
da7213.h Loading commit data...
da7218.h Loading commit data...
da7219-aad.h Loading commit data...
da7219.h Loading commit data...
da9055.h Loading commit data...
designware_i2s.h Loading commit data...
dmaengine_pcm.h Loading commit data...
emu10k1.h Loading commit data...
emu10k1_synth.h Loading commit data...
emu8000.h Loading commit data...
emu8000_reg.h Loading commit data...
emux_legacy.h Loading commit data...
emux_synth.h Loading commit data...
es1688.h Loading commit data...
gus.h Loading commit data...
hda_hwdep.h Loading commit data...
hda_i915.h Loading commit data...
hda_register.h Loading commit data...
hda_regmap.h Loading commit data...
hda_verbs.h Loading commit data...
hdaudio.h Loading commit data...
hdaudio_ext.h Loading commit data...
hwdep.h Loading commit data...
i2c.h Loading commit data...
info.h Loading commit data...
initval.h Loading commit data...
jack.h Loading commit data...
l3.h Loading commit data...
max9768.h Loading commit data...
max98088.h Loading commit data...
max98090.h Loading commit data...
max98095.h Loading commit data...
memalloc.h Loading commit data...
minors.h Loading commit data...
mixer_oss.h Loading commit data...
mpu401.h Loading commit data...
omap-hdmi-audio.h Loading commit data...
omap-pcm.h Loading commit data...
opl3.h Loading commit data...
opl4.h Loading commit data...
pcm-indirect.h Loading commit data...
pcm.h Loading commit data...
pcm_drm_eld.h Loading commit data...
pcm_iec958.h Loading commit data...
pcm_oss.h Loading commit data...
pcm_params.h Loading commit data...
pt2258.h Loading commit data...
pxa2xx-lib.h Loading commit data...
rawmidi.h Loading commit data...
rt286.h Loading commit data...
rt298.h Loading commit data...
rt5640.h Loading commit data...
rt5645.h Loading commit data...
rt5651.h Loading commit data...
rt5659.h Loading commit data...
rt5670.h Loading commit data...
rt5677.h Loading commit data...
s3c24xx_uda134x.h Loading commit data...
sb.h Loading commit data...
sb16_csp.h Loading commit data...
seq_device.h Loading commit data...
seq_kernel.h Loading commit data...
seq_midi_emul.h Loading commit data...
seq_midi_event.h Loading commit data...
seq_oss.h Loading commit data...
seq_oss_legacy.h Loading commit data...
seq_virmidi.h Loading commit data...
sh_dac_audio.h Loading commit data...
sh_fsi.h Loading commit data...
simple_card.h Loading commit data...
snd_wavefront.h Loading commit data...
soc-dai.h Loading commit data...
soc-dapm.h Loading commit data...
soc-dpcm.h Loading commit data...
soc-topology.h Loading commit data...
soc.h Loading commit data...
soundfont.h Loading commit data...
spear_dma.h Loading commit data...
spear_spdif.h Loading commit data...
sta32x.h Loading commit data...
sta350.h Loading commit data...
tas2552-plat.h Loading commit data...
tas5086.h Loading commit data...
tea6330t.h Loading commit data...
timer.h Loading commit data...
tlv.h Loading commit data...
tlv320aic32x4.h Loading commit data...
tlv320aic3x.h Loading commit data...
tlv320dac33-plat.h Loading commit data...
tpa6130a2-plat.h Loading commit data...
uda134x.h Loading commit data...
uda1380.h Loading commit data...
util_mem.h Loading commit data...
vx_core.h Loading commit data...
wavefront.h Loading commit data...
wm0010.h Loading commit data...
wm1250-ev1.h Loading commit data...
wm2000.h Loading commit data...
wm2200.h Loading commit data...
wm5100.h Loading commit data...
wm8903.h Loading commit data...
wm8904.h Loading commit data...
wm8955.h Loading commit data...
wm8960.h Loading commit data...
wm8962.h Loading commit data...
wm8993.h Loading commit data...
wm8996.h Loading commit data...
wm9081.h Loading commit data...
wm9090.h Loading commit data...
wss.h Loading commit data...