From patchwork Wed Nov 15 22:49:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 10060489 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6C1C86023A for ; Wed, 15 Nov 2017 22:49:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5DBC22A25C for ; Wed, 15 Nov 2017 22:49:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 528952A2C4; Wed, 15 Nov 2017 22:49:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 454842A25C for ; Wed, 15 Nov 2017 22:49:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932977AbdKOWtO (ORCPT ); Wed, 15 Nov 2017 17:49:14 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:41846 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932843AbdKOWtH (ORCPT ); Wed, 15 Nov 2017 17:49:07 -0500 Received: from avalon.ideasonboard.com (unknown [182.232.80.106]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 9ECEA201F5; Wed, 15 Nov 2017 23:47:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1510786066; bh=0Z2ZM7N1CJHZgkvwCc2iDTrGx2TiwVboUrEQMF5Dk6k=; h=From:To:Cc:Subject:Date:From; b=h/0kvhQcslAv5E7ZztesEs7YWE90PTPkcvP10wHmxLDWPuVSjOnAmiHyZIUrpsFPA 5UbqcsD2z0lpWFpt+y5gaOjFAkWRF1I6ywHtvUvSsrJsbPS5UR0/7g+LoGUko9HyI2 ovnluJ5e7D77lw23y0K676tGT0xoHk75HnXE/qr8= From: Laurent Pinchart To: linux-media@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org, =?UTF-8?q?Niklas=20S=C3=B6derlund?= Subject: [PATCH] v4l: rcar-vin: Implement V4L2 video node release handler Date: Thu, 16 Nov 2017 00:49:07 +0200 Message-Id: <20171115224907.392-1-laurent.pinchart+renesas@ideasonboard.com> X-Mailer: git-send-email 2.13.6 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The rvin_dev data structure contains driver private data for an instance of the VIN. It is allocated dynamically at probe time, and must be freed once all users are gone. The structure is currently allocated with devm_kzalloc(), which results in memory being freed when the device is unbound. If a userspace application is currently performing an ioctl call, or just keeps the device node open and closes it later, this will lead to accessing freed memory. Fix the problem by implementing a V4L2 release handler for the video node associated with the VIN instance (called when the last user of the video node releases it), and freeing memory explicitly from the release handler. Signed-off-by: Laurent Pinchart Acked-by: Niklas Söderlund --- drivers/media/platform/rcar-vin/rcar-core.c | 29 +++++++++++++++++++---------- drivers/media/platform/rcar-vin/rcar-v4l2.c | 9 ++++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/rcar-vin/rcar-core.c b/drivers/media/platform/rcar-vin/rcar-core.c index 495610949457..bd7976efa1fb 100644 --- a/drivers/media/platform/rcar-vin/rcar-core.c +++ b/drivers/media/platform/rcar-vin/rcar-core.c @@ -1208,7 +1208,7 @@ static int rcar_vin_probe(struct platform_device *pdev) struct resource *mem; int irq, ret; - vin = devm_kzalloc(&pdev->dev, sizeof(*vin), GFP_KERNEL); + vin = kzalloc(sizeof(*vin), GFP_KERNEL); if (!vin) return -ENOMEM; @@ -1224,20 +1224,26 @@ static int rcar_vin_probe(struct platform_device *pdev) vin->info = attr->data; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem == NULL) - return -EINVAL; + if (mem == NULL) { + ret = -EINVAL; + goto error_free; + } vin->base = devm_ioremap_resource(vin->dev, mem); - if (IS_ERR(vin->base)) - return PTR_ERR(vin->base); + if (IS_ERR(vin->base)) { + ret = PTR_ERR(vin->base); + goto error_free; + } irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto error_free; + } ret = rvin_dma_probe(vin, irq); if (ret) - return ret; + goto error_free; platform_set_drvdata(pdev, vin); if (vin->info->use_mc) @@ -1245,15 +1251,18 @@ static int rcar_vin_probe(struct platform_device *pdev) else ret = rvin_digital_graph_init(vin); if (ret < 0) - goto error; + goto error_dma; pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_enable(&pdev->dev); return 0; -error: + +error_dma: rvin_dma_remove(vin); v4l2_async_notifier_cleanup(&vin->notifier); +error_free: + kfree(vin); return ret; } diff --git a/drivers/media/platform/rcar-vin/rcar-v4l2.c b/drivers/media/platform/rcar-vin/rcar-v4l2.c index 2c14d44950b2..25f1d24c1d2d 100644 --- a/drivers/media/platform/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/rcar-vin/rcar-v4l2.c @@ -1026,6 +1026,13 @@ static void rvin_notify(struct v4l2_subdev *sd, } } +static void rvin_v4l2_release(struct video_device *vdev) +{ + struct rvin_dev *vin = container_of(vdev, struct rvin_dev, vdev); + + kfree(vin); +} + int rvin_v4l2_register(struct rvin_dev *vin) { struct video_device *vdev = &vin->vdev; @@ -1038,7 +1045,7 @@ int rvin_v4l2_register(struct rvin_dev *vin) vdev->queue = &vin->queue; snprintf(vdev->name, sizeof(vdev->name), "%s %s", KBUILD_MODNAME, dev_name(vin->dev)); - vdev->release = video_device_release_empty; + vdev->release = rvin_v4l2_release; vdev->lock = &vin->lock; vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;