contrib/plugins/dlcall.c | 32 +++++++++++++------ docs/about/emulation.rst | 31 ++++++++++++------ .../multiarch/test-plugin-syscall-filter.c | 9 ++++-- 3 files changed, 50 insertions(+), 22 deletions(-)
Hi,
Three small follow-ups to the dlcall plugin merged for 11.1. There is no
functional change: all of them are comment and documentation fixes.
The first one matters most. The plugin picks 4096 as its magic syscall number,
and the comment justified that by saying every Linux ABI keeps its syscall
numbers well below it. That is not true for MIPS O32, which bases its numbering
at 4000, so 4000 + 96 is a real getpriority. Loading the plugin on such a guest
would let the filter consume a legitimate getpriority() and read its arguments
as a dlcall request, where the first one selects an operation and the second is
taken as a string pointer.
Raising the number does not rescue that case, which is the part I had wrong at
first. O32 answers numbers its table does not define with ENOSYS in cpu_loop(),
before do_syscall() and therefore before the filter, so on O32 there is no
number that is both free and reachable. Its N32 and N64 ABIs base at 6000 and
5000 and have no such gate, so they are unaffected.
I checked this under qemu-mips rather than only reading cpu_loop(), using a
plugin that logs what its syscall filter receives. A plain getpriority() from
the guest arrives at the filter as num=4096 a1=0, which is what dlcall would
read as an operation ID with a NULL key, while syscall(8192, ...) returns
ENOSYS and never reaches the filter at all.
There is an upper bound elsewhere too. arm32 answers anything past ARM_NR_BASE
(0xf0000) with ENOSYS or SIGILL before do_syscall(), as the comment in
tests/tcg/multiarch/test-plugin-syscall-filter.c already notes, so a large
number is not a safe default either. 4096 sits below that and above the
ordinary syscall numbers, which is why it works on the targets people use this
with.
That test carried the same wrong reason, so the second patch corrects it. It
picked 4096 believing no ISA uses the number, when what actually keeps it safe
is that the filter matches on the first argument as well: a real syscall
carrying this number falls through untouched. tests/tcg/plugins/setpc.c matches
on the number alone, which works for the single test program it is loaded with,
but the collision applies there too, so neither test shows that 4096 is free.
I have deliberately not changed the default, nor restricted which guests may
load the plugin. The number is already configurable with syscall_num=N, and
dlcall is generic infrastructure rather than something tied to one userspace
project, so it should not decide which guest architectures people may
experiment with. What was wrong here was the reasoning in the comments, so they
now describe what a target actually does with the number.
The last patch extends the guest_base == 0 warning, since the guest must match
the host's pointer width and endianness as well, and tidies two things in the
prose: a library is not turned into thunks but has thunks produced for it, and
argument marshalling, callbacks and variadic functions belong with Lorelei
rather than in the plugin's description, since they are precisely what it does
not do.
Also in the first patch, two out pointers were dereferenced without the assert
the others carry.
Thanks,
Ziyang Zhang
Ziyang Zhang (3):
contrib/plugins/dlcall: correct the syscall number claim, note the
data model
tests/tcg: correct why the magic syscall number is safe here
docs/about/emulation: sharpen the dlcall boundary and its guest
requirements
contrib/plugins/dlcall.c | 32 +++++++++++++------
docs/about/emulation.rst | 31 ++++++++++++------
.../multiarch/test-plugin-syscall-filter.c | 9 ++++--
3 files changed, 50 insertions(+), 22 deletions(-)
--
2.34.1
On 7/19/2026 12:47 AM, Ziyang Zhang wrote: > Hi, > > Three small follow-ups to the dlcall plugin merged for 11.1. There is no > functional change: all of them are comment and documentation fixes. > > The first one matters most. The plugin picks 4096 as its magic syscall number, > and the comment justified that by saying every Linux ABI keeps its syscall > numbers well below it. That is not true for MIPS O32, which bases its numbering > at 4000, so 4000 + 96 is a real getpriority. Loading the plugin on such a guest > would let the filter consume a legitimate getpriority() and read its arguments > as a dlcall request, where the first one selects an operation and the second is > taken as a string pointer. > > Raising the number does not rescue that case, which is the part I had wrong at > first. O32 answers numbers its table does not define with ENOSYS in cpu_loop(), > before do_syscall() and therefore before the filter, so on O32 there is no > number that is both free and reachable. Its N32 and N64 ABIs base at 6000 and > 5000 and have no such gate, so they are unaffected. > > I checked this under qemu-mips rather than only reading cpu_loop(), using a > plugin that logs what its syscall filter receives. A plain getpriority() from > the guest arrives at the filter as num=4096 a1=0, which is what dlcall would > read as an operation ID with a NULL key, while syscall(8192, ...) returns > ENOSYS and never reaches the filter at all. > > There is an upper bound elsewhere too. arm32 answers anything past ARM_NR_BASE > (0xf0000) with ENOSYS or SIGILL before do_syscall(), as the comment in > tests/tcg/multiarch/test-plugin-syscall-filter.c already notes, so a large > number is not a safe default either. 4096 sits below that and above the > ordinary syscall numbers, which is why it works on the targets people use this > with. > > That test carried the same wrong reason, so the second patch corrects it. It > picked 4096 believing no ISA uses the number, when what actually keeps it safe > is that the filter matches on the first argument as well: a real syscall > carrying this number falls through untouched. tests/tcg/plugins/setpc.c matches > on the number alone, which works for the single test program it is loaded with, > but the collision applies there too, so neither test shows that 4096 is free. > > I have deliberately not changed the default, nor restricted which guests may > load the plugin. The number is already configurable with syscall_num=N, and > dlcall is generic infrastructure rather than something tied to one userspace > project, so it should not decide which guest architectures people may > experiment with. What was wrong here was the reasoning in the comments, so they > now describe what a target actually does with the number. > > The last patch extends the guest_base == 0 warning, since the guest must match > the host's pointer width and endianness as well, and tidies two things in the > prose: a library is not turned into thunks but has thunks produced for it, and > argument marshalling, callbacks and variadic functions belong with Lorelei > rather than in the plugin's description, since they are precisely what it does > not do. > > Also in the first patch, two out pointers were dereferenced without the assert > the others carry. > > Thanks, > Ziyang Zhang > > Ziyang Zhang (3): > contrib/plugins/dlcall: correct the syscall number claim, note the > data model > tests/tcg: correct why the magic syscall number is safe here > docs/about/emulation: sharpen the dlcall boundary and its guest > requirements > > contrib/plugins/dlcall.c | 32 +++++++++++++------ > docs/about/emulation.rst | 31 ++++++++++++------ > .../multiarch/test-plugin-syscall-filter.c | 9 ++++-- > 3 files changed, 50 insertions(+), 22 deletions(-) > This was merged into master (83e8f88135cba892934b1d4d04f4c063e213700a). Thank you for your contribution! Regards, Pierrick
© 2016 - 2026 Red Hat, Inc.