[FFmpeg-devel] [PATCH] avformat/librist: fix logging setting

Zhao Zhili quinkblack at foxmail.com
Tue May 25 11:01:48 EEST 2021


The librist logging API is confusing. It looks like a per instance
setting but saves a copy to global static variable quietly. So there
is a potential use-after-free issue with log_cb_arg.

librist took zero as invalid file descriptor at first. After the problem
was fixed, now it will close the zero file desscriptor. So log_socket
must be initialized to -1. See
https://code.videolan.org/rist/librist/-/issues/98
---
 libavformat/librist.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/libavformat/librist.c b/libavformat/librist.c
index 01a3f9c122..46bb71cf87 100644
--- a/libavformat/librist.c
+++ b/libavformat/librist.c
@@ -24,6 +24,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/thread.h"
 #include "libavutil/time.h"
 
 #include "avformat.h"
@@ -99,6 +100,38 @@ static int log_cb(void *arg, enum rist_log_level log_level, const char *msg)
     return 0;
 }
 
+static void librist_set_global_log_callback(void)
+{
+    static struct rist_logging_settings logging_settings = {
+        .log_level = RIST_LOG_INFO,
+        .log_cb = log_cb,
+        .log_cb_arg = NULL,
+        .log_socket = -1,
+        .log_stream = NULL,
+    };
+    rist_logging_set_global(&logging_settings);
+}
+
+static int librist_setup_log(RISTContext *s, struct rist_logging_settings *logging_settings)
+{
+    int ret;
+    static AVOnce init_static_once = AV_ONCE_INIT;
+
+    if (!logging_settings)
+        return AVERROR(EINVAL);
+
+    // set global log callback first, otherwise rist_logging_set() will copy
+    // logging_settings to a global static variable, which can leads to
+    // use-after-free
+    ff_thread_once(&init_static_once, librist_set_global_log_callback);
+
+    logging_settings->log_socket = -1;
+    ret = rist_logging_set(&logging_settings, s->log_level, log_cb, s, NULL, NULL);
+    if (ret < 0)
+        return risterr2ret(ret);
+    return 0;
+}
+
 static int librist_close(URLContext *h)
 {
     RISTContext *s = h->priv_data;
@@ -123,9 +156,9 @@ static int librist_open(URLContext *h, const char *uri, int flags)
     if ((flags & AVIO_FLAG_READ_WRITE) == AVIO_FLAG_READ_WRITE)
         return AVERROR(EINVAL);
 
-    ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL);
+    ret = librist_setup_log(s, logging_settings);
     if (ret < 0)
-        return risterr2ret(ret);
+        return ret;
 
     if (flags & AVIO_FLAG_WRITE) {
         h->max_packet_size = s->packet_size;
-- 
2.31.1



More information about the ffmpeg-devel mailing list