Opened 3 years ago

Closed 2 years ago

Last modified 2 years ago

#9711 closed defect (fixed)

RTMP play command response exposes undefined stack content

Reported by: Mattias Wadman Owned by:
Priority: normal Component: avformat
Version: unspecified Keywords: rtmp
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:

When replying to a "play" command the response might expose undefined stack content.

How to reproduce:

# latest ffmpeg from brew as of 2022-04-04
$ ffmpeg -version
ffmpeg version 5.0 Copyright (c) 2000-2022 the FFmpeg developers
built with Apple clang version 13.0.0 (clang-1300.0.29.30)
configuration: --prefix=/usr/local/Cellar/ffmpeg/5.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
libavutil      57. 17.100 / 57. 17.100
libavcodec     59. 18.100 / 59. 18.100
libavformat    59. 16.100 / 59. 16.100
libavdevice    59.  4.100 / 59.  4.100
libavfilter     8. 24.100 /  8. 24.100
libswscale      6.  4.100 /  6.  4.100
libswresample   4.  3.100 /  4.  3.100
libpostproc    56.  3.100 / 56.  3.100

In three separate terminals:
$ ffmpeg -hide_banner -f lavfi -i sine=sample_rate=44100 -acodec aac -ac 2 -f flv -t 200ms -listen 1 rtmp://127.0.0.1:1935/test_stream
$ ffmpeg -i rtmp://127.0.0.1:1935/test_stream -f null -
$ tcpdump -w rtmp.pcap -i lo0

Inspect pcap:

$ tshark -T json -r rtmp.pcap | grep -C 10 published
                "Name: code": {
                  "amf.stringlength": "4",
                  "amf.string": "code"
                },
                "String 'NetStream.Play.Start'": {
                  "amf.amf0_type": "0x02",
                  "amf.stringlength": "20",
                  "amf.string": "NetStream.Play.Start"
                }
              },
              "Property 'description' String '���2 is now published'": {
                "Name: description": {
                  "amf.stringlength": "11",
                  "amf.string": "description"
                },
                "String '���2 is now published'": {
                  "amf.amf0_type": "0x02",
                  "amf.stringlength": "21",
                  "amf.string": "���2 is now published"
                }
              },
              "Property 'details' String '���2'": {
                "Name: details": {
                  "amf.stringlength": "7",
                  "amf.string": "details"
                },
                "String '���2'": {
                  "amf.amf0_type": "0x02",
                  "amf.stringlength": "4",

Or use master version of https://github.com/wader/fq (was adding rtmp support to fq when i found this issue)

$ fq '.tcp_connections[].server_stream.messages? | grep("published") | parent | parent | parent | d({line_bytes: 10})'  rtmp.pcap
    │00 01 02 03 04 05 06 07 08 09│0123456789│.tcp_connections[0].server_stream.messages[9].arguments[0].value[0:5]:
    │                             │          │  [0]{}:
0x14│      00 05 6c 65 76 65 6c   │  ..level │    key: "level"
    │                             │          │    value{}:
0x14│                           02│         .│      type: "string" (2)
0x1e│00 06 73 74 61 74 75 73      │..status  │      value: "status"
    │                             │          │  [1]{}:
0x1e│                        00 04│        ..│    key: "code"
0x28│63 6f 64 65                  │code      │
    │                             │          │    value{}:
0x28│            02               │    .     │      type: "string" (2)
0x28│               00 14 4e 65 74│     ..Net│      value: "NetStream.Play.Start"
0x32│53 74 72 65 61 6d 2e 50 6c 61│Stream.Pla│
0x3c│79 2e 53 74 61 72 74         │y.Start   │
    │                             │          │  [2]{}:
0x3c│                     00 0b 64│       ..d│    key: "description"
0x46│65 73 63 72 69 70 74 69 6f 6e│escription│
    │                             │          │    value{}:
0x50│02                           │.         │      type: "string" (2)
0x50│   00 15 ff ff aa 32 20 69 73│ .....2 is│      value: "���2 is now published"
0x5a│20 6e 6f 77 20 70 75 62 6c 69│ now publi│
0x64│73 68 65 64                  │shed      │
    │                             │          │  [3]{}:
0x64│            00 07 64 65 74 61│    ..deta│    key: "details"
0x6e│69 6c 73                     │ils       │
    │                             │          │    value{}:
0x6e│         02                  │   .      │      type: "string" (2)
0x6e│            00 04 ff ff aa 32│    .....2│      value: "���2"
    │                             │          │  [4]{}:
0x78│00 00                        │..        │    key: ""
    │                             │          │    value{}:
0x78│      09│                    │  .│      │      type: "object_end" (9)

The description and details strings seems to have garbage bytes. Looking at the code for rtmpproto.c:send_invoke_response it seems like the stack variable char filename[128] is read (by write_status) without being initialized in the "play" command case. I think this might expose uninitialized stack content or might cause unintended UB compiler optimizations.

Change History (3)

comment:2 by Marton Balint, 2 years ago

Resolution: fixed
Status: newclosed

comment:3 by Mattias Wadman, 2 years ago

Great thanks!

Note: See TracTickets for help on using tickets.