From 21c412dc4942efe8f40541963090a72f7e59deb1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 21 Sep 2021 14:44:17 +0200 Subject: [PATCH] libcamera: fix a use-after-free due an attempt to stop the camera twice Camera is currently stopped and started in the spa_libcamera_set_format() function, but this leads to a segfault due attempting to access a buffers field of an already freed libcamera::FrameBufferAllocator instance. The FrameBufferAllocator instance is freed in LibCamera::stop(), that is called by spa_libcamera_stream_off() as handler of the node commands SPA_NODE_COMMAND_Pause and SPA_NODE_COMMAND_Suspend. Since the camera was already stopped, there's no need to attempt to stop it again. In fact, the camera shouldn't be stopped/started at all in the spa_libcamera_set_format() function but instead only as an action of the SPA_NODE_COMMAND_{Pause,Suspend} and SPA_NODE_COMMAND_Start commands. And same for the stop that's done in the LibCamera::close() function, it shouldn't be needed because the camera is already stopped before closing. Fixes #1513 --- spa/plugins/libcamera/libcamera-utils.c | 8 ++------ spa/plugins/libcamera/libcamera_wrapper.cpp | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/spa/plugins/libcamera/libcamera-utils.c b/spa/plugins/libcamera/libcamera-utils.c index bc34d9082..4a57c6774 100644 --- a/spa/plugins/libcamera/libcamera-utils.c +++ b/spa/plugins/libcamera/libcamera-utils.c @@ -470,9 +470,6 @@ static int spa_libcamera_set_format(struct impl *this, struct spa_video_info *fo if ((res = spa_libcamera_open(dev)) < 0) return res; - /* stop the camera first. It might have opened with different configuration*/ - libcamera_stop_capture(dev->camera); - spa_log_info(dev->log, "libcamera: set %s %dx%d %d/%d\n", (char *)&info->fourcc, fmt.width, fmt.height, fmt.denominator, fmt.numerator); @@ -485,9 +482,6 @@ static int spa_libcamera_set_format(struct impl *this, struct spa_video_info *fo return -EINVAL; } - /* start the camera now with the configured params */ - libcamera_start_capture(dev->camera); - dev->have_format = true; size->width = libcamera_get_streamcfg_width(dev->camera); size->height = libcamera_get_streamcfg_height(dev->camera); @@ -871,6 +865,8 @@ static int spa_libcamera_stream_on(struct impl *this) libcamera_connect(dev->camera); + libcamera_start_capture(dev->camera); + port->source.func = libcamera_on_fd_events; port->source.data = this; port->source.fd = spa_system_eventfd_create(this->system, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK); diff --git a/spa/plugins/libcamera/libcamera_wrapper.cpp b/spa/plugins/libcamera/libcamera_wrapper.cpp index 00dda7a91..037058af0 100644 --- a/spa/plugins/libcamera/libcamera_wrapper.cpp +++ b/spa/plugins/libcamera/libcamera_wrapper.cpp @@ -540,7 +540,6 @@ extern "C" { } void LibCamera::close() { - this->stop(); this->cam_->release(); }