[{"id":38362,"web_url":"https://patchwork.libcamera.org/comment/38362/","msgid":"<678f18db-b4f8-4a8d-9b83-1b287ce6ba1c@ideasonboard.com>","date":"2026-03-18T15:54:17","subject":"Re: [PATCH v5 6/7] libcamera: mali-c55: Implement capture for\n\tmemory-to-memory","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"Hi\n\n\n2026. 03. 13. 17:14 keltezéssel, Jacopo Mondi írta:\n> From: Daniel Scally <dan.scally@ideasonboard.com>\n> \n> Plumb in the MaliC55 pipeline handler support for capturing frames\n> from memory using the CRU.\n> \n> Introduce a data flow which uses the CRU to feed the ISP through\n> the IVC.\n> \n> In detail:\n> \n> - push incoming request to a pending queue until a buffer from the CRU\n>    is available\n> - delay the call to ipa_->fillParams() to the CRU buffer ready even\n\nI think this sentence was cut of.\n\n\n> - once the IPA has computed parameters feed the ISP through the IVC\n>    with buffers from the CRU, params and statistics.\n> \n> Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n> ---\n>   src/libcamera/pipeline/mali-c55/mali-c55.cpp | 166 ++++++++++++++++++++++++++-\n>   1 file changed, 161 insertions(+), 5 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n> index 9b83927d8441..84c2a030b470 100644\n> --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n> +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n> [...]\n> @@ -1404,6 +1443,12 @@ void PipelineHandlerMaliC55::stopDevice(Camera *camera)\n>   \t\tpipe.cap->releaseBuffers();\n>   \t}\n>   \n> +\tif (std::holds_alternative<MaliC55CameraData::Memory>(data->input_)) {\n> +\t\tcancelPendingRequests();\n> +\t\tivc_->streamOff();\n> +\t\tdata->cru()->stop();\n> +\t}\n\nI think there is an issue here. Specifically, `RZG2LCRU::stop()` frees the buffers, but dangling\nreferences are still in `ivc_->V4l2VideoDevice::cache_` until `ivc_->releaseBuffers()` is called\nin `freeBuffers()`. When `ipa_->stop()` is called, it is after these cru buffers have been freed.\nIf there are pending `{params,stats}Completed` signals, those are synchronously dispatched. Those\nwill reference the already freed buffers, for example when `ivc_->queueBuffer()` is called,\nleading to a use after free.\n\n==1182==ERROR: AddressSanitizer: heap-use-after-free on address 0xfc1f8d207b30 at pc 0xffff9c2c5b3c bp 0xfbff8aff9610 sp 0xfbff8aff9628\nREAD of size 8 at 0xfc1f8d207b30 thread T1\n     #0 0xffff9c2c5b38 in libcamera::V4L2BufferCache::Entry::operator==(libcamera::FrameBuffer const&) const ../src/libcamera/v4l2_videodevice.cpp:292\n     #1 0xffff9c2d5968 in libcamera::V4L2BufferCache::get(libcamera::FrameBuffer const&) ../src/libcamera/v4l2_videodevice.cpp:243\n     #2 0xffff9c2e1648 in libcamera::V4L2VideoDevice::queueBuffer(libcamera::FrameBuffer*, libcamera::V4L2Request const*) ../src/libcamera/v4l2_videodevice.cpp:1671\n     #3 0xffff9c48e904 in libcamera::PipelineHandlerMaliC55::paramsComputed(unsigned int, unsigned int) ../src/libcamera/pipeline/mali-c55/mali-c55.cpp:1778\n     #4 0xffff99242704 in libcamera::BoundMethodBase::activatePack(std::shared_ptr<libcamera::BoundMethodPackBase>, bool) ../src/libcamera/base/bound_method.cpp:85\n     #5 0xffff9c51b0e4 in libcamera::BoundMethodMember<libcamera::PipelineHandlerMaliC55, void, unsigned int, unsigned int>::activate(unsigned int, unsigned int, bool) ../include/libcamera/base/bound_method.h:173\n     #6 0xffff9bcc7b1c in libcamera::Signal<unsigned int, unsigned int>::emit(unsigned int, unsigned int) ../include/libcamera/base/signal.h:147\n     #7 0xffff9bc8ae5c in libcamera::ipa::mali_c55::IPAProxyMaliC55Threaded::paramsComputedHandler(unsigned int, unsigned int) src/libcamera/proxy/mali-c55_ipa_proxy.cpp:166\n     #8 0xffff9924bf54 in libcamera::Object::message(libcamera::Message*) ../src/libcamera/base/object.cpp:211\n     #9 0xffff992dfaf0 in libcamera::Thread::dispatchMessages(libcamera::Message::Type, libcamera::Object*) ../src/libcamera/base/thread.cpp:662\n     #10 0xffff9bc8f274 in libcamera::ipa::mali_c55::IPAProxyMaliC55Threaded::stop() src/libcamera/proxy/mali-c55_ipa_proxy.cpp:105\n     #11 0xffff9c49599c in libcamera::PipelineHandlerMaliC55::stopDevice(libcamera::Camera*) ../src/libcamera/pipeline/mali-c55/mali-c55.cpp:1420\n     [...]\n\nand\n\n0xfc1f8d207b30 is located 0 bytes inside of 16-byte region [0xfc1f8d207b30,0xfc1f8d207b40)\nfreed by thread T1 here:\n     #0 0xffff9f8815b8 in operator delete(void*, unsigned long) (/lib64/libasan.so.8+0xd95b8)\n     #1 0xffff9c522238 in libcamera::FrameBuffer::~FrameBuffer() ../include/libcamera/framebuffer.h:63\n     #2 0xffff9c522238 in std::default_delete<libcamera::FrameBuffer>::operator()(libcamera::FrameBuffer*) const /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/unique_ptr.h:93\n     #3 0xffff9c522238 in std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >::~unique_ptr() /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/unique_ptr.h:399\n     #4 0xffff9c522238 in void std::_Destroy<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> > >(std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*) /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/stl_construct.h:166\n     #5 0xffff9c522238 in void std::_Destroy<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*>(std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*, std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*) /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/stl_construct.h:212\n     #6 0xffff9c522238 in void std::_Destroy<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*, std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> > >(std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*, std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*, std::allocator<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> > >&) /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/alloc_traits.h:1045\n     #7 0xffff9c522238 in std::vector<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >, std::allocator<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> > > >::_M_erase_at_end(std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >*) /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/stl_vector.h:2238\n     #8 0xffff9c522238 in std::vector<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> >, std::allocator<std::unique_ptr<libcamera::FrameBuffer, std::default_delete<libcamera::FrameBuffer> > > >::clear() /aarch64-buildroot-linux-gnu/include/c++/15.2.0/bits/stl_vector.h:1864\n     #9 0xffff9c522238 in libcamera::RZG2LCRU::freeBuffers() ../src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp:108\n     #10 0xffff9c52314c in libcamera::RZG2LCRU::stop() ../src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp:100\n     #11 0xffff9c495758 in libcamera::PipelineHandlerMaliC55::stopDevice(libcamera::Camera*) ../src/libcamera/pipeline/mali-c55/mali-c55.cpp:1414\n     [...]\n\n\n> +\n>   \tstats_->streamOff();\n>   \tparams_->streamOff();\n>   \tif (data->ipa_)\n> [...]\n> @@ -1645,18 +1789,27 @@ void PipelineHandlerMaliC55::paramsComputed(unsigned int requestId, uint32_t byt\n>   \n>   \t/*\n>   \t * Queue buffers for stats and params, then queue buffers to the capture\n> -\t * video devices.\n> +\t * video devices if we're running in Inline mode or with the TPG.\n> +\t *\n> +\t * If we're running in M2M buffers have been queued to the capture\n> +\t * devices at queuePendingRequests() time and here we only have to queue\n> +\t * buffers to the IVC input to start a transfer.\n>   \t */\n>   \n>   \tframeInfo.paramBuffer->_d()->metadata().planes()[0].bytesused = bytesused;\n>   \tparams_->queueBuffer(frameInfo.paramBuffer);\n>   \tstats_->queueBuffer(frameInfo.statBuffer);\n>   \n> -\tfor (auto &[stream, buffer] : request->buffers()) {\n> -\t\tMaliC55Pipe *pipe = pipeFromStream(data, stream);\n> +\tif (!std::holds_alternative<MaliC55CameraData::Memory>(data->input_)) {\n> +\t\tfor (auto &[stream, buffer] : request->buffers()) {\n> +\t\t\tMaliC55Pipe *pipe = pipeFromStream(data, stream);\n>   \n> -\t\tpipe->cap->queueBuffer(buffer);\n> +\t\t\tpipe->cap->queueBuffer(buffer);\n> +\t\t}\n>   \t}\n> +\n> +\tif (std::holds_alternative<MaliC55CameraData::Memory>(data->input_))\n> +\t\tivc_->queueBuffer(frameInfo.rawBuffer);\n\nI think `frameInfo.rawBuffer = nullptr` is missing here. If not done, then\n`findFrameInfo()` might find an \"old\" entry if the buffer is reused.\n\n\n>   }\n>   \n>   void PipelineHandlerMaliC55::statsProcessed(unsigned int requestId,\n> @@ -1793,6 +1946,9 @@ bool PipelineHandlerMaliC55::registerMemoryInputCamera()\n>   \n>   \tivc_->bufferReady.connect(data->cru(), &RZG2LCRU::cruReturnBuffer);\n>   \n> +\tV4L2VideoDevice *cruOutput = data->cru()->output();\n> +\tcruOutput->bufferReady.connect(this, &PipelineHandlerMaliC55::cruBufferReady);\n> +\n>   \treturn registerMaliCamera(std::move(data), sensor->device()->entity()->name());\n>   }\n>   \n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 1F664BE086\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 18 Mar 2026 15:54:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 52A02626E8;\n\tWed, 18 Mar 2026 16:54:23 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 75C1362010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 18 Mar 2026 16:54:21 +0100 (CET)","from [192.168.33.40] (185.182.214.153.nat.pool.zt.hu\n\t[185.182.214.153])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 516FF460;\n\tWed, 18 Mar 2026 16:53:08 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"BcXHxcXD\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1773849188;\n\tbh=d+nuQlTvDHJ78S/bMjxc/k31+BJgea1ZkeEszO7hxKs=;\n\th=Date:Subject:To:References:From:In-Reply-To:From;\n\tb=BcXHxcXD8GdaiKO7sXXnRV82ORkw0Tc+1cIKo1aumYRF2q0j76JL7xzTeaGB4T9+1\n\tO81PWdu90CmxhxHYQV7qpm/YOCVYcAFVFi+hTHR+nuJek92LTUAQsaAAXyFIbmGL5s\n\tQoGRCmgb5LdTtpFGKjtRAk3jBQkLo7hCghCllunc=","Message-ID":"<678f18db-b4f8-4a8d-9b83-1b287ce6ba1c@ideasonboard.com>","Date":"Wed, 18 Mar 2026 16:54:17 +0100","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v5 6/7] libcamera: mali-c55: Implement capture for\n\tmemory-to-memory","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>,\n\tDaniel Scally <dan.scally@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","References":"<20260313-mali-cru-v5-0-48f93e431294@ideasonboard.com>\n\t<20260313-mali-cru-v5-6-48f93e431294@ideasonboard.com>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<20260313-mali-cru-v5-6-48f93e431294@ideasonboard.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]