libzmq
libzmq copied to clipboard
libzmq/ffmpeg: "Address family not supported by protocol (src/ip_resolver.cpp:542) / Aborted" from mpd.service "RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK"
tl;dr: libzmq errors out when RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
is in the mpd systemd unit file when mpd, running as a system service, calls ffmpeg ... zmq:tcp://127.0.0.1:5555
directly (i.e., in the systemd environment). How to get around this while retaining security in the systemd unit?
Issue description
I was able to get ffmpeg's libzmq implementation to work on the cli either using cat /tmp/mpd.fifo | ffmpeg ... -i - ... zmq:tcp://127.0.0.1:5555
pipe as stdin or just using the named pipe as direct input ffmepg ... -i /tmp/mpd.fifo ... zmq:tcp://127.0.0.1:5555
but it kept erroring out when called directly by mpd's pipe output, e.g.,
audio_output {
name "ffmpeg zmq"
enabled "no"
type "pipe"
format "48000:16:2"
command "ffmpeg -hide_banner -f s16le -ar 48000 -ac 2 -i - -f mpegts -acodec libopus -b:a 128k zmq:tcp://127.0.0.1:5555 >> /var/log/mpd/ffmpeg.log 2>&1"
}
results in ffmpeg reporting,"Address family not supported by protocol (src/ip_resolver.cpp:542) / Aborted" and mpd just saying it was a broken pipe.
Upon a good bit of investigation and helpful suggestions from #ffmpeg, #bash, and #systemd the offending line in systemd unit file mpd.service was: RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
What is the best way to let libzmq have whatever access it needs without significantly sacrificing security (which is described in the mpd.service unit file as one of the "# more paranoid security settings")?
replacing the RestrictAddressFamlies=...
with
IPAddressAllow=localhost
IPAddressDeny=any
does solve the problem so if that's the best solution then this can be closed and left for anyone else looking to solve this problem.
Environment
- libzmq version (commit hash if unreleased):
these probably came from apt
ii libzmq3-dev:amd64 4.3.5-1build2 amd64
ii libzmq5:amd64 4.3.5-1build2 amd64
however I also compiled libzmq from source because I wasn't sure if libzmq3-dev would work and:
$ ldd $(which ffmpeg) | grep zmq; pkg-config --modversion libzmq
libzmq.so.5 => /usr/local/lib/libzmq.so.5 (0x000073830ca6c000)
4.3.6
so when ffmpeg was compiled (after its libzmq was patched) with --enable=libzmq
it presumably used the 4.3.6 that pkgconfig displayed. (If it's super duper relevant I'm sure I could recompile ffmpeg again to test.)
- OS: Rhino Linux 2024.02
- ffmpeg version:
ffmpeg version N-116842-ga87a96105e Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14 (Ubuntu 14.2.0-4ubuntu1)
configuration: --bindir=/usr/local/bin --prefix=/cache/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/cache/ffmpeg_build/include --extra-ldflags=-L/cache/ffmpeg_build/lib --extra-libs='-lpthread -lm' --ld=g++ ... --enable-libzmq
- Music Player Daemon 0.24 (v0.23.15-1377-g381215fd7+)
Minimal test code / Steps to reproduce the issue
- See above...
- run mpd as system service using the default systemd unit file included with mpd source.
- create an mpd pipe output shown above with the ffmpeg command:
command "ffmpeg -hide_banner -f s16le -ar 48000 -ac 2 -i - -f mpegts -acodec libopus -b:a 128k zmq:tcp://127.0.0.1:5555 >> /var/log/mpd/ffmpeg.log 2>&1"
- enable the pipe output to ffmpeg/zmq
- hear no sound
- look at the logs
What's the actual result? (include assertion message & call stack if applicable)
mpd can't use the output, it results in ffmpeg reporting,"Address family not supported by protocol (src/ip_resolver.cpp:542) / Aborted" and mpd just saying it was a broken pipe.
I put an strace in front of ffmpeg in the mpd pipe command in mpd.conf:
$ for i in /var/lib/mpd/ffmpegstrace.log.*; do cat "$i"; hr; done
⋮
read(3, "?\376\v\374\226\375d\373\256\375y\373s\3753\373\17\375\302\372\340\374\205\372I\375\347\372a\375\37\373"..., 36864) = 4096
read(3, "h\3731\372-\373\356\371\302\373\201\372\350\373\214\372\247\373=\372\375\373\242\372\307\373e\372\332\373\212\372"..., 32768) = 8192
read(3, "\203\371\22\371\0\371R\370$\3716\370\260\371{\370\264\372a\371\316\373t\372\320\373]\372\300\372;\371"..., 65536) = 4096
read(3, "f\375\306\376\310\375\312\376Q\376\2\377\3\377L\377o\377@\377\f\377o\376\267\376\250\375]\376\325\374"..., 61440) = 4096
read(3, "w\0Z\377\7\0\355\376\277\377\276\376\254\377\260\376v\377n\376\336\376\303\375s\3769\375\221\376D\375"..., 57344) = 4096
read(3, "u\2#\4\307\2\322\4\362\2J\5\340\2\205\5_\2B\5B\2W\5_\2\256\5\360\1`\5"..., 53248) = 4096
read(3, "\245\374\t\371\220\374\6\371\225\374\30\371v\375\3\372\255\376O\373\317\376\225\373;\376\37\3739\376P\373"..., 49152) = 4096
read(3, "\251\376\"\3752\377D\375O\377\32\375\373\376k\374\374\376\"\374\323\376\317\373\353\376\267\373\235\3777\374"..., 45056) = 4096
read(3, "\237\375H\377k\375\372\376&\375\235\376\24\375\206\376\262\374\23\376\307\373\17\375\241\373\323\374\236\373\263\374"..., 40960) = 4096
read(3, "\246\3\350\3\352\2\31\3@\2v\2\374\1\16\2\271\1\241\1q\1<\1\202\1\16\1\f\1`\0"..., 36864) = 4096
read(3, "\345\4\270\7\230\4\245\7U\4\254\0073\4\314\7\r\4\303\7\363\3\332\7\372\3\360\7\251\3\256\7"..., 32768) = 4096
read(3, "g\6\272\2\263\6-\3\372\6\251\3\307\6\272\3[\6\255\3K\6\354\3w\6\207\4\7\7~\5"..., 65536) = 4096
read(3, "\321\377I\1\252\0\261\1\273\1[\2\266\2\356\2S\0037\3<\3\362\2\263\2B\2\331\1R\1"..., 61440) = 4096
read(3, "\6\365\277\370x\365\372\370\355\365W\371I\366\301\371\261\3667\3726\367\335\372\223\367\\\3732\370\360\373"..., 57344) = 4096
read(3, "\336\372v\1\327\372L\1\355\3727\0014\373/\1/\373\323\0\335\372.\0\312\372\302\3774\373\322\377"..., 53248) = 4096
read(3, "\343\3706\1\242\370\26\1o\370\7\1T\370\365\0\213\370\7\1\311\370#\1\t\371A\1b\371~\1"..., 49152) = 8192
read(3, "\227\361\374\362u\361T\363e\361\237\363!\361\277\363\334\360\356\363\344\360c\364\243\360\216\364G\360\233\364"..., 40960) = 4096
read(3, "\330\377\34\376\203\377!\376\335\376\323\375$\376\201\375\236\375B\375\2\375\367\374\224\374\330\374{\374\343\374"..., 36864) = 4096
brk(0x5a490936a000) = 0x5a490936a000
read(3, ">\21<\f\355\20\2\f\7\21,\f\16\21N\f-\21\244\fV\21\346\fV\21\r\r^\21D\r"..., 32768) = 4096
read(3, "\367\5\333\2\241\6c\3\7\7\310\3\220\7L\4\243\7j\4x\7Y\4\207\7`\4\\\79\4"..., 65536) = 4096
read(3, "\301\367\256\363[\367%\363\23\367\315\362\31\367\302\362S\367\345\362\245\3679\363\20\370\231\363J\370\310\363"..., 61440) = 4096
read(3, "\255\377P\0K\377\273\3777\377m\377\24\377\n\3771\377\343\376`\377\311\376*\377M\3768\377\23\376"..., 57344) = 4096
read(3, "@\377\216\372\16\377\221\372\0\377\244\372\17\377\314\372u\377[\373\264\377\237\373\256\377\261\373\225\377\307\373"..., 53248) = 4096
read(3, "%\367<\366\20\367.\366-\367@\366~\367\223\366\202\367\223\366e\367b\366M\367D\366\26\367\2\366"..., 49152) = 4096
read(3, "\230\2\265\0\343\2\n\1g\3\232\1x\3\274\1i\3\267\1H\3\247\1J\3\324\1\253\3N\2"..., 45056) = 4096
read(3, "\244\r\355\f\374\6\220\6\332\4\230\4x\vq\n`\v\371\10\342\n\257\10\341\7\221\7\337\5\367\4"..., 40960) = 4096
read(3, "k\372B\375=\374\240\377\372\375c\2;\1\275\4\376\3\222\6\223\0\210\4\226\375\3\2\367\3730\377"..., 36864) = 4096
read(3, "\204\374q\375\243\373\257\374\266\374\357\374\t\375K\375\256\3732\374\352\3738\374?\375\235\375\7\376p\376"..., 32768) = 4096
read(3, "\215\4Q\5\214\4i\5A\4\21\5\226\3\204\4\335\2\f\4\205\2\314\3\221\3\v\5D\4\25\6"..., 65536) = 4096
read(3, ")\372v\370\374\371\30\370q\372o\370\344\372\344\370\352\372\331\370\205\373q\371,\374%\372\r\375\t\373"..., 61440) = 4096
fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
ioctl(2, TCGETS, 0x7ffd2e003870) = -1 ENOTTY (Inappropriate ioctl for device)
write(2, "[aist#0:0/pcm_s16le @ 0x5a490935"..., 38) = 38
write(2, "Guessed Channel Layout: stereo\n", 31) = 31
write(2, "Input #0, s16le, from 'fd:':\n", 29) = 29
write(2, " Duration: ", 12) = 12
write(2, "N/A", 3) = 3
write(2, ", bitrate: ", 11) = 11
write(2, "1536 kb/s", 9) = 9
write(2, "\n", 1) = 1
write(2, " Stream #0", 11) = 11
write(2, ":0", 2) = 2
write(2, ": Audio: pcm_s16le, 48000 Hz, st"..., 52) = 52
write(2, "\n", 1) = 1
eventfd2(0, EFD_CLOEXEC) = 4
fcntl(4, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
fcntl(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
getpid() = 360340
getpid() = 360340
eventfd2(0, EFD_CLOEXEC) = 5
fcntl(5, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
fcntl(5, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
getpid() = 360340
epoll_create1(EPOLL_CLOEXEC) = 6
epoll_ctl(6, EPOLL_CTL_ADD, 5, {events=0, data={u32=154481152, u64=99269733593600}}) = 0
epoll_ctl(6, EPOLL_CTL_MOD, 5, {events=EPOLLIN, data={u32=154481152, u64=99269733593600}}) = 0
getpid() = 360340
rt_sigaction(SIGRT_1, {sa_handler=0x77902289e830, sa_mask=[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x779022845250}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x779021000000
mprotect(0x779021001000, 8388608, PROT_READ|PROT_WRITE) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
clone3({flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, child_tid=0x779021800990, parent_tid=0x779021800990, exit_signal=0, stack=0x779021000000, stack_size=0x7ffc80, tls=0x7790218006c0}, 88) = -1 ENOSYS (Function not implemented)
clone(child_stack=0x7790217ffc70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tid=[360346], tls=0x7790218006c0, child_tidptr=0x779021800990) = 360346
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
eventfd2(0, EFD_CLOEXEC) = 7
fcntl(7, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(7, F_SETFL, O_RDWR|O_NONBLOCK) = 0
fcntl(7, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
fcntl(7, F_SETFL, O_RDWR|O_NONBLOCK) = 0
getpid() = 360340
epoll_create1(EPOLL_CLOEXEC) = 8
epoll_ctl(8, EPOLL_CTL_ADD, 7, {events=0, data={u32=154491008, u64=99269733603456}}) = 0
epoll_ctl(8, EPOLL_CTL_MOD, 7, {events=EPOLLIN, data={u32=154491008, u64=99269733603456}}) = 0
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x779020600000
mprotect(0x779020601000, 8388608, PROT_READ|PROT_WRITE) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
clone(child_stack=0x779020dffc70, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tid=[360347], tls=0x779020e006c0, child_tidptr=0x779020e00990) = 360347
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
eventfd2(0, EFD_CLOEXEC) = 9
fcntl(9, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK) = 0
fcntl(9, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
fcntl(9, F_SETFL, O_RDWR|O_NONBLOCK) = 0
getpid() = 360340
getpid() = 360340
poll([{fd=9, events=POLLIN}], 1, 0) = 0 (Timeout)
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = -1 EAFNOSUPPORT (Address family not supported by protocol)
write(2, "Address family not supported by "..., 67) = 67
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid() = 360340
getpid() = 360340
tgkill(360340, 360340, SIGABRT) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=360340, si_uid=113} ---
+++ killed by SIGABRT +++
######################################################################################################################
rseq(0x779021800fe0, 0x20, 0, 0x53053053) = 0
set_robust_list(0x7790218009a0, 24) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], NULL, 8) = 0
sched_getparam(360346, [0]) = 0
sched_getscheduler(360346) = 0 (SCHED_OTHER)
sched_setscheduler(360346, SCHED_OTHER, [0]) = 0
prctl(PR_SET_NAME, "ZMQbg/Reaper") = 0
epoll_wait(6, <unfinished ...>) = ?
+++ killed by SIGABRT +++
######################################################################################################################
rseq(0x779020e00fe0, 0x20, 0, 0x53053053) = 0
set_robust_list(0x779020e009a0, 24) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], NULL, 8) = 0
sched_getparam(360347, [0]) = 0
sched_getscheduler(360347) = 0 (SCHED_OTHER)
sched_setscheduler(360347, SCHED_OTHER, [0]) = 0
prctl(PR_SET_NAME, "ZMQbg/IO/0") = 0
epoll_wait(8, <unfinished ...>) = ?
+++ killed by SIGABRT +++
#####################################################################################################################
What's the expected result?
I just want ffmpeg to stream music from one machine to the other and I want mpd to be able to use an unnamed pipe so ffmpeg can be called directly from mpd like I've been doing with rtsp instead of some workaround:
audio_output {
name "pipe to ffmpeg - suffix"
enabled "no"
type "pipe"
format "48000:16:2"
command "ffmpeg -loglevel error -hide_banner -y -f s16le -ar 48000 -ac 2 -vn -i - -c libopus -b:a 64k -f rtsp
rtsp://localhost:8554/mpd/mpd.opus"
}