Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp4283237pxb; Tue, 2 Nov 2021 07:14:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxQ0IrIP0Nd60lv3Igw4u+46P5jaTCGr65Rj6d1585Z7tNyHSQWnrkrugcKqKxev4gaExyh X-Received: by 2002:a17:906:1558:: with SMTP id c24mr14397207ejd.553.1635862465182; Tue, 02 Nov 2021 07:14:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1635862465; cv=none; d=google.com; s=arc-20160816; b=sQVx1Olw44GZNHBKJjaL8EP3djd0BDUqBlmrPhn7ACAG87UCvRbls2g3BEnHYQqCQm KH9miEBazkJS0ejARGL1nXqa03ATfOSGNZ1vGc15cxCsp5X8DKlte9IL3m2qEUB9YIif ow5ucvM2LYykVwpaKYPYY8Vz0mysuDjqm1Vz3ch27anvsvhbJy40I1EKgWD0sdgQj0gy MQFhLAsJd6BE7K6mEpGpiFPkO7HKTgB+AlF6O+BoGfutmBo233lT5qi0xOiEkyeBfwTI ONhfld8s1cNRyYHOUU0sL93FTPdyV7Fg42TAfWkR0KgL7dZnto3oul3JNhMTjDC8biVx 2ihg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:user-agent:references:in-reply-to :subject:cc:to:from:message-id:date:dkim-signature:dkim-signature; bh=1DRWTC1TFIfMR6RNlvGI/qW1glO7XAqTrvN5XJswVzw=; b=SXN/6GblVB09BBxctQpNa1D5pW0He0LtgKM6Mmd24VyhVuBhxsxFV5n+tYVRLQy8Cx u+QwSuVXWTTbTzIhiutDxkDgL22qcmqtm8HXoJttsLcscrZSa239OCkicjmbLxYVbUFd xpBB99xpne1Wl3TrKAopDw71NGifXQmPIF4+1IZB3fAklpYFmeZyEdJ/tM46V/8X3Ur+ H5AHsG8/sAssDjGD66sgbs1UOQOtQ+cn7dC3W2RtQjN3ArL8toNeyYEHIlrxZmTkkc+T yefdJoOQEiliSoDaYXEfRyww92fkz1B8QXbv6t/3ZBzVChKVL5Xo/mRXJWdnDy8cRhlv hX5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=ewYngEG3; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c4si25823476edk.560.2021.11.02.07.14.00; Tue, 02 Nov 2021 07:14:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.de header.s=susede2_rsa header.b=ewYngEG3; dkim=neutral (no key) header.i=@suse.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=suse.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230522AbhKBONZ (ORCPT + 99 others); Tue, 2 Nov 2021 10:13:25 -0400 Received: from smtp-out2.suse.de ([195.135.220.29]:45256 "EHLO smtp-out2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230286AbhKBONY (ORCPT ); Tue, 2 Nov 2021 10:13:24 -0400 Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id C16361FD4C; Tue, 2 Nov 2021 14:10:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1635862248; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=1DRWTC1TFIfMR6RNlvGI/qW1glO7XAqTrvN5XJswVzw=; b=ewYngEG3ImcmH8UfbJOem+z+BO4lsqJ4FnYkvyQqknNqbVgtUjzVWE3eQGr2U72pBiTs5u rn1Q5mAk57KtTLyC7Uc5vYVZ0uQ1huw6OCv9rBwcQ5BuAWuruJzWFU/ueDVwGAO8Z1SCIY 3EoXJDGvKoJmcMIzXKAs8qbRnHl4CQQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1635862248; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=1DRWTC1TFIfMR6RNlvGI/qW1glO7XAqTrvN5XJswVzw=; b=dzF1lpO49/xA1F+tOalq+n4/LIVwzpx3dEgxuHiMS/2mB7M3yfc7vxTvS1cWg1v2Z7IVid VQv7QJlOpsIxCMCA== Received: from alsa1.suse.de (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id 99CB6A3B81; Tue, 2 Nov 2021 14:10:48 +0000 (UTC) Date: Tue, 02 Nov 2021 15:10:48 +0100 Message-ID: From: Takashi Iwai To: Wang Wensheng Cc: , , , , , , Subject: Re: [PATCH -next] ALSA: timer: Fix use-after-free problem In-Reply-To: <20211102134107.35126-1-wangwensheng4@huawei.com> References: <20211102134107.35126-1-wangwensheng4@huawei.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, 02 Nov 2021 14:41:07 +0100, Wang Wensheng wrote: > > When the timer instance was add into ack_list but was not currently in > process, the user could stop it via snd_timer_stop1() without delete it > from the ack_list. Then the user could free the timer instance and when > it was actually processed UAF occurred. > > This issue could be reproduced via testcase snd_timer01 in ltp - running > several instances of that testcase at the same time. > > What I actually met was that the ack_list of the timer broken and the > kernel went into deadloop with irqoff. That could be detected by > hardlockup detector on board or when we run it on qemu, we could use gdb > to dump the ack_list when the console has no response. > > To fix this issue, we introduce a new flag SNDRV_TIMER_IFLG_ACKING to > indicate the state where the timer instance is in ack_list but not > currently processed and check against the new flag in snd_timer_stop1() > and delete it from ack_list if the flag is set. > > Signed-off-by: Wang Wensheng Thanks for the patch. Just through a quick glance, I wonder whether it'd be easier to do list_del_init(&timeri->ack_list) unconditionally before the check of timeri->flags in snd_timer1_stop(). Ditto for active_list. So something like: --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -624,13 +624,13 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) if (!timer) return -EINVAL; spin_lock_irqsave(&timer->lock, flags); + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START))) { result = -EBUSY; goto unlock; } - list_del_init(&timeri->ack_list); - list_del_init(&timeri->active_list); if (timer->card && timer->card->shutdown) goto unlock; if (stop) { Takashi > --- > include/sound/timer.h | 1 + > sound/core/timer.c | 12 +++++++++--- > 2 files changed, 10 insertions(+), 3 deletions(-) > > diff --git a/include/sound/timer.h b/include/sound/timer.h > index 760e132cc0cd..549288e94a39 100644 > --- a/include/sound/timer.h > +++ b/include/sound/timer.h > @@ -31,6 +31,7 @@ > #define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */ > #define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */ > #define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */ > +#define SNDRV_TIMER_IFLG_ACKING 0x00000100 /* the timeri was added to ack_list */ > > #define SNDRV_TIMER_FLG_CHANGE 0x00000001 > #define SNDRV_TIMER_FLG_RESCHED 0x00000002 /* need reschedule */ > diff --git a/sound/core/timer.c b/sound/core/timer.c > index 92b7008fcdb8..1d1e4274919c 100644 > --- a/sound/core/timer.c > +++ b/sound/core/timer.c > @@ -625,10 +625,12 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) > return -EINVAL; > spin_lock_irqsave(&timer->lock, flags); > if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | > - SNDRV_TIMER_IFLG_START))) { > + SNDRV_TIMER_IFLG_START | > + SNDRV_TIMER_IFLG_ACKING))) { > result = -EBUSY; > goto unlock; > } > + > list_del_init(&timeri->ack_list); > list_del_init(&timeri->active_list); > if (timer->card && timer->card->shutdown) > @@ -649,7 +651,8 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) > } > } > } > - timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); > + timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START | > + SNDRV_TIMER_IFLG_ACKING); > if (stop) > timeri->flags &= ~SNDRV_TIMER_IFLG_PAUSED; > else > @@ -786,6 +789,7 @@ static void snd_timer_process_callbacks(struct snd_timer *timer, > > /* remove from ack_list and make empty */ > list_del_init(&ti->ack_list); > + ti->flags &= ~SNDRV_TIMER_IFLG_ACKING; > > if (!(ti->flags & SNDRV_TIMER_IFLG_DEAD)) { > ticks = ti->pticks; > @@ -890,8 +894,10 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) > ack_list_head = &timer->ack_list_head; > else > ack_list_head = &timer->sack_list_head; > - if (list_empty(&ti->ack_list)) > + if (list_empty(&ti->ack_list)) { > list_add_tail(&ti->ack_list, ack_list_head); > + ti->flags |= SNDRV_TIMER_IFLG_ACKING; > + } > list_for_each_entry(ts, &ti->slave_active_head, active_list) { > ts->pticks = ti->pticks; > ts->resolution = resolution; > -- > 2.17.1 >