Repository navigation
Conversation
The global SIGCHLD handler reaped any child with waitpid(-1, ...). When
GTK/glycin forks a bwrap sandbox to load an SVG icon and then waits on
it, ettercap's handler could reap that child first, so glycin's own wait
returned ECHILD ("No child processes") and aborted the process:
Gtk:ERROR ...ensure_surface_for_gicon: assertion failed (error == NULL):
Failed to load .../image-missing.svg: IO error: No child processes
(os error 10) "bwrap" ... Bail out!
It surfaces after the GUI has been idle because glycin tears down its
loader subprocess on an idle timeout and respawns it on the next icon
load; the respawn-and-wait path loses the race with the global reaper.
Stop reaping children we don't own: drop the waitpid(-1) SIGCHLD handler
(leave SIGCHLD at SIG_DFL, not SIG_IGN which would auto-reap and break
glycin the same way) and reap every child ettercap forks by its specific
PID at the fork site instead:
- ec_filter.c func_execreplace: waitpid(child_pid) after reading output
- ec_filter.c func_exec: double-fork so the long-running command is
reparented to init; the parent reaps the short-lived intermediate
- ec_redirect.c, os/ec_linux.c: wait() -> waitpid(child_pid, ...)
- remote_browser plugin: double-fork the browser launch (another
fire-and-forget fork that relied on the global reaper)
The popen()/system() call sites already wait internally and also benefit,
since the old reaper could make their waits fail with ECHILD too.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ViA4iMt6akg2RoxdN2QNVS
|
Tested the equivalent of this fix on Kali Linux Rolling ARM64 ( However, this exposes the second failure anticipated in the PR description: once the In this setup, Ettercap runs with This suggests that the Could we also investigate whether Ettercap can avoid this real/effective UID combination for the GUI, or whether a supported fallback is possible when Bubblewrap cannot start? Either approach would need to preserve the intended security boundaries. I can provide the For local testing only, I was able to keep the GUI running by combining the shim with a |
I've now setup a latest Kali in a KVM. Providing info how to reproduces would be appreciated. |
|
Steps to reproduce are given in the bug report that this MR intends to fix: #1310. |
|
@koeppea let me know if you're able to reproduce this. I don't have access to a Kali VM. |
Adding one more piece on the second failure (the one beyond the SIGCHLD race), with a deterministic 5-second repro that removes the "sporadic" factor. Context: ettercap opens its pcap socket as root, then drops privileges to Repro (simulates ettercap's post-privilege-drop state, $ sudo setpriv --ruid 0 --euid 65534 --regid 65534 --clear-groups \
bwrap --unshare-all --die-with-parent --chdir / --ro-bind /usr /usr \
--dev /dev --symlink usr/lib /lib --symlink usr/bin /bin /usr/bin/true
bwrap: setuid use of bubblewrap is not supported
$ echo $?
1Controls (same bwrap command, only the UIDs change; both succeed): $ sudo setpriv --ruid 0 --euid 0 ... # exit 0
$ sudo setpriv --ruid 65534 --euid 65534 ... # exit 0So bubblewrap refuses only in the mixed-UID state ettercap leaves the process in ( Resulting failure chain:
|
|
Hi @eaescob yes I've been able to reproduce the issue: Opened Ettercap in setup-screen and left it there. Opened some other applications for a couple of minutes. Then proceeded Ettercap from setup screen hitting the Accept Button, then it crashed with the above output on its calling terminal. |
|
Ok, taking a stab at this.
Emilio Escobar / ***@***.***
…On Sat, Oct 24, 2026 at 10:52 AM Alexander Köppe ***@***.***> wrote:
*koeppea* left a comment (Ettercap/ettercap#1315)
<#1315 (comment)>
Hi @eaescob <https://github.com/eaescob>
yes I've been able to reproduce the issue:
┌──(kali㉿kali)-[~]
└─$ sudo ettercap -G
[sudo] password for kali:
ettercap 0.8.4.1 copyright 2001-2026 Ettercap Development Team
(ettercap:3419): IBUS-WARNING **: 13:49:20.907: Failed to mkdir /root/.config/ibus/bus: Not a directory
(ettercap:3419): Gtk-WARNING **: 13:49:21.053: Could not load a pixbuf from icon theme.
This may indicate that pixbuf loaders or the mime database could not be found.
**
Gtk:ERROR:../../../gtk/gtkiconhelper.c:495:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Tango/16x16/status/image-missing.png: Loader process exited early with status '1'Command:
"bwrap" "--unshare-all" "--die-with-parent" "--chdir" "/" "--ro-bind" "/usr" "/usr" "--dev" "/dev" "--ro-bind-try" "/etc/ld.so.cache" "/etc/ld.so.cache" "--ro-bind-try" "/nix/store" "/nix/store" "--tmpfs" "/tmp-home" "--tmpfs" "/tmp-run" "--clearenv" "--setenv" "HOME" "/tmp-home" "--setenv" "XDG_RUNTIME_DIR" "/tmp-run" "--symlink" "/usr/lib64" "/lib64" "--symlink" "/usr/lib" "/lib" "--symlink" "/usr/lib32" "/lib32" "--seccomp" "27" "/usr/libexec/glycin-loaders/2+/glycin-image-rs" "--dbus-fd" "26" (gdk-pixbuf-error-quark, 0)
Bail out! Gtk:ERROR:../../../gtk/gtkiconhelper.c:495:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Tango/16x16/status/image-missing.png: Loader process exited early with status '1'Command: "bwrap" "--unshare-all" "--die-with-parent" "--chdir" "/" "--ro-bind" "/usr" "/usr" "--dev" "/dev" "--ro-bind-try" "/etc/ld.so.cache" "/etc/ld.so.cache" "--ro-bind-try" "/nix/store" "/nix/store" "--tmpfs" "/tmp-home" "--tmpfs" "/tmp-run" "--clearenv" "--setenv" "HOME" "/tmp-home" "--setenv" "XDG_RUNTIME_DIR" "/tmp-run" "--symlink" "/usr/lib64" "/lib64" "--symlink" "/usr/lib" "/lib" "--symlink" "/usr/lib32" "/lib32" "--seccomp" "27" "/usr/libexec/glycin-loaders/2+/glycin-image-rs" "--dbus-fd" "26" (gdk-pixbuf-error-quark, 0)
zsh: abort sudo ettercap -G
┌──(kali㉿kali)-[~]
└─$
—
Reply to this email directly, view it on GitHub
<#1315?email_source=notifications&email_token=AAEQ2SJTOLV25HROCLJTWR35VTT4PA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTMMZYG42TKMRYGUZ2M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-6387552853>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEQ2SKBQCQ6JJC3F7RMVGD5VTT4PAVCNFSNUABDKJSXA33TNF2G64TZHM2TANBRGEZTGO2JONZXKZJ3GUZDONBQGM4DCNRTUF3AE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
@koeppea @0x03c1 @elboulangero, thanks for the repro. The second failure (
The two PRs are independent, so the full fix for #1310 needs both. To test them together: git fetch origin fix-1310-sigchld-glycin devin/1793039564-drop-privs-ruid
git checkout -b test-1310 origin/fix-1310-sigchld-glycin
git merge --no-edit origin/devin/1793039564-drop-privs-ruid
mkdir build && cd build && cmake .. -DGTK_BUILD_TYPE=GTK3 && make -j$(nproc) && sudo make install
sudo ettercap -GThen:
I reproduced the abort on master in a debian:testing container (glycin-loaders 2.x, bubblewrap). With #1338, and with #1338 + #1315 combined, ettercap stayed up after the idle period. Confirmation on Kali would help. |
Taking care of that. |
Addresses #1310.
Root cause
The GTK GUI aborts with:
No child processesisECHILD, returned from await()/waitpid()call. Glycin isn't failing to render the SVG — it's failing to wait on thebwrapsandbox process it just forked, because something reaped that child first.That something is ettercap's global
SIGCHLDhandler, which reaped any child:When GTK/glycin forks its sandbox loader and waits on that specific PID, ettercap's handler wins the race and reaps it, so glycin's own wait returns
ECHILDand it aborts.It shows up after the GUI has been idle because glycin tears down its loader subprocess on an idle timeout and respawns it on the next icon load; the respawn-and-wait path reliably loses the race with the global reaper.
Fix
Stop reaping children ettercap doesn't own. Drop the
waitpid(-1)SIGCHLDhandler (leaveSIGCHLDatSIG_DFL— notSIG_IGN, which would auto-reap and break glycin the same way) and reap every child ettercap forks by its specific PID at the fork site:ec_filter.cfunc_execreplace:waitpid(child_pid)after reading the child's output (already synchronous there)ec_filter.cfunc_exec: double-fork so the long-running command reparents to init; the parent reaps the short-lived intermediate childec_redirect.c,os/ec_linux.c:wait()→waitpid(child_pid, ...)remote_browserplugin: double-fork the browser launch (another fire-and-forget fork that relied on the global reaper)The existing
popen()/system()call sites already wait internally and also benefit, since the old reaper could make their waits fail withECHILDtoo.Testing
debian:testingcontainer with GTK + GeoIP enabled (clean, no new warnings).ECHILDabort specifically; ifbwrapalso fails for a privilege/namespace reason after the privilege drop, that would surface as a different error message worth reporting separately.🤖 Generated with Claude Code