Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp5643220imu; Mon, 26 Nov 2018 03:25:54 -0800 (PST) X-Google-Smtp-Source: AJdET5d1ePHR9xJo4lB1FP1Ec78dbe1XUtzNDK2bxqR6zlV8l6kB016eah0MoS/Ig6NcpcPSktDj X-Received: by 2002:a62:81c1:: with SMTP id t184mr27468237pfd.246.1543231554497; Mon, 26 Nov 2018 03:25:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543231554; cv=none; d=google.com; s=arc-20160816; b=cj7QSF5ybY2n8Lw8Gco2F7dZlVgqou4OYHJ+MHC+9STgyrW+YHvyUIblJSTmJfueEc /6n085jJfRF14l02PZPH6eqhukRb0KazzGcIP2bD3MTKrLIK79tKUSTJyYPKmdXYd8/z MT6r7kW+G6jbJT4oCaLrcArA3y4bpbske1UcXIQP/l6+iKDZ5tRkKlgpPS2JVwyFmaZl 4OwoVh8OGhzbW+X4tsz8WCzhzijzo4kUk1sRyFtkMwWvTEGUFk/QxuiExa6Cjqu4E2dt JNV5898ye0OTwiUN5LA8nbcq5M8Hd3xJTD6WCbp7GHS2sypXdEx9NEPbSF8bTH+jf1DE iY6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Fk8wnW4QvUOY3LIvM3R9no+pO/o2enNYwWoWJKw3a70=; b=05C7pLoK9YbesQdiOmqjdM5oBtvRpodYyT2KtizaqPNCx+uqWA93+0GBKUxTKGIvPS UZj5RsfqcDMY+bAB900ni1LQRlf4vN5SuyiA5SR3l962UFT07zbtFGRjumIcaMrpZmD8 e4IgK01t+Ox+HY3UOiNcloroZe4gaDpTVYHb7QEp3Oyi5uB5pPXtiOiAgemoYWZBId/L 96Ggt7et9ZczEwUWIQ+PujXDqiZRC/FNqc1m8XSkVA3SeR2Ojxif0Xn8D3YhVwBSlktm gkVnt4TPnQU0daS4zh7RPCymf2x7HQTlzQ6ghUfNGoePnLgB20Db+vCESAXYtpkgXot3 PL4w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=vDt4+HD0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i13si12336pgi.260.2018.11.26.03.25.34; Mon, 26 Nov 2018 03:25:54 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=vDt4+HD0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728160AbeKZVti (ORCPT + 99 others); Mon, 26 Nov 2018 16:49:38 -0500 Received: from mail.kernel.org ([198.145.29.99]:58604 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726561AbeKZVth (ORCPT ); Mon, 26 Nov 2018 16:49:37 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 42D3820817; Mon, 26 Nov 2018 10:55:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543229752; bh=g/vqBZnaXwYuR6pIcil7kXku1QBip54vnPbh/5LRpKc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vDt4+HD02Ahbkp6/7aI+DQXIlXArBG3J+DrgnYebhSZpUq8VbfashUj1mftWqZXIx vjpFgMFokZ99uTsRk3WpCypsZzVVJ+nSQWtcTOdkRckVVNK4GksUYBhLFQH06HWLj0 aTIZVhsRldJgP4mPFChPJTKmuyKAY1N1nmknDakQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Dave Stevenson , Sakari Ailus , Hans Verkuil , Mauro Carvalho Chehab Subject: [PATCH 4.4 60/70] media: v4l: event: Add subscription to list before calling "add" operation Date: Mon, 26 Nov 2018 11:51:15 +0100 Message-Id: <20181126105052.503135604@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181126105046.722096341@linuxfoundation.org> References: <20181126105046.722096341@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Sakari Ailus commit 92539d3eda2c090b382699bbb896d4b54e9bdece upstream. Patch ad608fbcf166 changed how events were subscribed to address an issue elsewhere. As a side effect of that change, the "add" callback was called before the event subscription was added to the list of subscribed events, causing the first event queued by the add callback (and possibly other events arriving soon afterwards) to be lost. Fix this by adding the subscription to the list before calling the "add" callback, and clean up afterwards if that fails. Fixes: ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions while accessed") Reported-by: Dave Stevenson Signed-off-by: Sakari Ailus Tested-by: Dave Stevenson Reviewed-by: Hans Verkuil Tested-by: Hans Verkuil Cc: stable@vger.kernel.org (for 4.14 and up) Signed-off-by: Mauro Carvalho Chehab [Sakari Ailus: Backported to v4.9 stable] Signed-off-by: Sakari Ailus Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-event.c | 43 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -197,6 +197,22 @@ int v4l2_event_pending(struct v4l2_fh *f } EXPORT_SYMBOL_GPL(v4l2_event_pending); +static void __v4l2_event_unsubscribe(struct v4l2_subscribed_event *sev) +{ + struct v4l2_fh *fh = sev->fh; + unsigned int i; + + lockdep_assert_held(&fh->subscribe_lock); + assert_spin_locked(&fh->vdev->fh_lock); + + /* Remove any pending events for this subscription */ + for (i = 0; i < sev->in_use; i++) { + list_del(&sev->events[sev_pos(sev, i)].list); + fh->navailable--; + } + list_del(&sev->list); +} + int v4l2_event_subscribe(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub, unsigned elems, const struct v4l2_subscribed_event_ops *ops) @@ -228,27 +244,23 @@ int v4l2_event_subscribe(struct v4l2_fh spin_lock_irqsave(&fh->vdev->fh_lock, flags); found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); + if (!found_ev) + list_add(&sev->list, &fh->subscribed); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); if (found_ev) { /* Already listening */ kfree(sev); - goto out_unlock; - } - - if (sev->ops && sev->ops->add) { + } else if (sev->ops && sev->ops->add) { ret = sev->ops->add(sev, elems); if (ret) { + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + __v4l2_event_unsubscribe(sev); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); kfree(sev); - goto out_unlock; } } - spin_lock_irqsave(&fh->vdev->fh_lock, flags); - list_add(&sev->list, &fh->subscribed); - spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - -out_unlock: mutex_unlock(&fh->subscribe_lock); return ret; @@ -283,7 +295,6 @@ int v4l2_event_unsubscribe(struct v4l2_f { struct v4l2_subscribed_event *sev; unsigned long flags; - int i; if (sub->type == V4L2_EVENT_ALL) { v4l2_event_unsubscribe_all(fh); @@ -295,14 +306,8 @@ int v4l2_event_unsubscribe(struct v4l2_f spin_lock_irqsave(&fh->vdev->fh_lock, flags); sev = v4l2_event_subscribed(fh, sub->type, sub->id); - if (sev != NULL) { - /* Remove any pending events for this subscription */ - for (i = 0; i < sev->in_use; i++) { - list_del(&sev->events[sev_pos(sev, i)].list); - fh->navailable--; - } - list_del(&sev->list); - } + if (sev != NULL) + __v4l2_event_unsubscribe(sev); spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);