Skip to content

Make --chroot and --discovery work at the same time#236

Open
tomangert wants to merge 1 commit intochristgau:masterfrom
tomangert:master
Open

Make --chroot and --discovery work at the same time#236
tomangert wants to merge 1 commit intochristgau:masterfrom
tomangert:master

Conversation

@tomangert
Copy link
Copy Markdown

The discovery thread had errors when running under chroot. Tested on Ubuntu/jammy/22.04 and Ubuntu/noble/24.04

@christgau
Copy link
Copy Markdown
Owner

thread

Thread?!

had errors

Can you provide the error message(s) you encountered? I wonder why name resolution would be required, since the WSD protocol usually employs IP addresses for data exchange and not host names. I could imagine that urllib needs a resolver, but I'd like to figure that out.

@tomangert
Copy link
Copy Markdown
Author

sadie-24:~$ uname -a
Linux sadie-24 6.14.0-1014-azure #14~24.04.1-Ubuntu SMP Fri Oct  3 20:52:11 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
sadie-24:~$ wsdd -V
wsdd - Web Service Discovery Daemon, v0.7.1

sadie-24:~$ sudo systemctl start wsdd-server.service
sadie-24:~$ psg wsdd
 EUID EUSER        PID    PPID  C STIME   RSS    VSZ TT           TIME CMD
64757 wsdd        3822       1  1 13:54 30600  36828 ?        00:00:00 python3 /usr/bin/wsdd --shortlog --chroot=/run/wsdd --discovery --listen 2424 --ipv4only --interface eth0 --workgroup HOME
EUSER
sadie-24:~$ sudo netstat -antp|grep pyth
tcp        0      0 172.28.0.81:5357        0.0.0.0:*               LISTEN      3822/python3

Not listening on 2424
No errors in log until service is stopped. Then:

2025-10-27T13:56:36.705513-04:00 sadie-24 systemd[1]: Stopping wsdd-server.service - Web Services Dynamic Discovery host daemon...
2025-10-27T13:56:36.713646-04:00 sadie-24 wsdd[3822]: Traceback (most recent call last):
2025-10-27T13:56:36.713713-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1965, in main
2025-10-27T13:56:36.713741-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 641, in run_forever
2025-10-27T13:56:36.713758-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1987, in _run_once
2025-10-27T13:56:36.713771-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/events.py", line 88, in _run
2025-10-27T13:56:36.713785-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1736, in sigterm_handler
2025-10-27T13:56:36.713800-04:00 sadie-24 wsdd[3822]: SystemExit: 0
2025-10-27T13:56:36.713812-04:00 sadie-24 wsdd[3822]: During handling of the above exception, another exception occurred:
2025-10-27T13:56:36.713825-04:00 sadie-24 wsdd[3822]: Traceback (most recent call last):
2025-10-27T13:56:36.713867-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1981, in <module>
2025-10-27T13:56:36.713891-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1969, in main
2025-10-27T13:56:36.713938-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
2025-10-27T13:56:36.713954-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1190, in cleanup
2025-10-27T13:56:36.713970-04:00 sadie-24 wsdd[3822]:   File "/usr/bin/wsdd", line 1117, in create_server
2025-10-27T13:56:36.713982-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/streams.py", line 84, in start_server
2025-10-27T13:56:36.713994-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1528, in create_server
2025-10-27T13:56:36.714007-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1460, in _create_server_getaddrinfo
2025-10-27T13:56:36.714019-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1456, in _ensure_resolved
2025-10-27T13:56:36.714062-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 901, in getaddrinfo
2025-10-27T13:56:36.714076-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 858, in run_in_executor
2025-10-27T13:56:36.714089-04:00 sadie-24 wsdd[3822]:   File "/usr/lib/python3.12/concurrent/futures/__init__.py", line 49, in __getattr__
2025-10-27T13:56:36.714101-04:00 sadie-24 wsdd[3822]: ModuleNotFoundError: **No module named 'concurrent.futures.thread'**
2025-10-27T13:56:36.728117-04:00 sadie-24 systemd[1]: wsdd-server.service: Main process exited, code=exited, status=1/FAILURE
2025-10-27T13:56:36.728213-04:00 sadie-24 systemd[1]: wsdd-server.service: Failed with result 'exit-code'.
2025-10-27T13:56:36.728395-04:00 sadie-24 systemd[1]: Stopped wsdd-server.service - Web Services Dynamic Discovery host daemon.

Add the import concurrent.futures.thread

2025-10-27T14:00:24.649491-04:00 sadie-24 systemd[1]: Stopping wsdd-server.service - Web Services Dynamic Discovery host daemon...
2025-10-27T14:00:24.650333-04:00 sadie-24 wsdd[3865]: Traceback (most recent call last):
2025-10-27T14:00:24.650409-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1965, in main
2025-10-27T14:00:24.650454-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 641, in run_forever
2025-10-27T14:00:24.650484-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1987, in _run_once
2025-10-27T14:00:24.650538-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/events.py", line 88, in _run
2025-10-27T14:00:24.650567-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1736, in sigterm_handler
2025-10-27T14:00:24.650588-04:00 sadie-24 wsdd[3865]: SystemExit: 0
2025-10-27T14:00:24.650612-04:00 sadie-24 wsdd[3865]: During handling of the above exception, another exception occurred:
2025-10-27T14:00:24.650651-04:00 sadie-24 wsdd[3865]: Traceback (most recent call last):
2025-10-27T14:00:24.650678-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1981, in <module>
2025-10-27T14:00:24.650711-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1969, in main
2025-10-27T14:00:24.650760-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
2025-10-27T14:00:24.650779-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1190, in cleanup
2025-10-27T14:00:24.650826-04:00 sadie-24 wsdd[3865]:   File "/usr/bin/wsdd", line 1117, in create_server
2025-10-27T14:00:24.650847-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/streams.py", line 84, in start_server
2025-10-27T14:00:24.650863-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1528, in create_server
2025-10-27T14:00:24.650884-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1460, in _create_server_getaddrinfo
2025-10-27T14:00:24.650908-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 1456, in _ensure_resolved
2025-10-27T14:00:24.650920-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/asyncio/base_events.py", line 901, in getaddrinfo
2025-10-27T14:00:24.650931-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/concurrent/futures/thread.py", line 58, in run
2025-10-27T14:00:24.650947-04:00 sadie-24 wsdd[3865]:   File "/usr/lib/python3.12/socket.py", line 963, in getaddrinfo
2025-10-27T14:00:24.650960-04:00 sadie-24 wsdd[3865]: socket.gaierror: [Errno -3] **Temporary failure in name resolution**
2025-10-27T14:00:24.673671-04:00 sadie-24 systemd[1]: wsdd-server.service: Main process exited, code=exited, status=1/FAILURE
2025-10-27T14:00:24.673763-04:00 sadie-24 systemd[1]: wsdd-server.service: Failed with result 'exit-code'.
2025-10-27T14:00:24.673964-04:00 sadie-24 systemd[1]: Stopped wsdd-server.service - Web Services Dynamic Discovery host daemon.

Add the rest of the patch and it works.

@tomangert
Copy link
Copy Markdown
Author

That example is with the ubuntu 24.04 apt version of wsdd. Same results with 0.8/0.9/latest.

@christgau
Copy link
Copy Markdown
Owner

Thanks. I'll take a closer look as soon as time allows

@christgau
Copy link
Copy Markdown
Owner

My understanding is that localhost here causes the host lookup (v0.7.1, but is still in HEAD):

wsdd/src/wsdd.py

Lines 1117 to 1119 in 2b1a764

self.server = await aio_loop.create_task(asyncio.start_server( # type: ignore
self.on_connect, host='localhost', port=int(listen_address), reuse_address=True,
reuse_port=True))

Changing it to 127.0.0.1 or ::1 solves the issue, but unnecessarily fixes the address family. Looking at the alternatives below, maybe this is the easiest solution, after looking the nasty

On the other hand, copying files from within wsdd to the new root doesn't feel right, IMO. I'd suggest to copy files in the service file, like in the systemd unit, e.g. using ExecStartPre. In addition, etc/hosts might be sufficient. So something like this in the unit file might be sufficient:

ExecStartPre=mkdir -p /run/wsdd/etc
ExecStartPre=cp /etc/hosts /run/wsdd/etc/

However: The error message ModuleNotFoundError: **No module named 'concurrent.futures.thread'** is caused by the implementation of futures. I dont think it is a good idea to directly import in implementation-specific module. The documentation on futures also states:

The asynchronous execution can be performed with threads, using ThreadPoolExecutor or InterpreterPoolExecutor, or separate processes, using ProcessPoolExecutor.

How can one be sure which one is chosen at runtime? Including all seems dirty as well. Overall, chroot'ing a python script generally appears to be an issue. So in case a chroot environment is needed, one may create a virtual environment and chroot into that to avoid those issues.

@marcosfrm
Copy link
Copy Markdown

Note that the systemd units set DynamicUser=yes, which already implies these hardening options: RemoveIPC=yes, PrivateTmp=disconnected, NoNewPrivileges=yes, RestrictSUIDSGID=yes, ProtectSystem=strict, ProtectHome=read-only.

There are additional options to lock it down further, and you might consider dropping the chroot:

https://docs.arbitrary.ch/security/systemd.html

Just be careful not to require very recent systemd versions -- check the "Availability" field for each option. I'd say systemd 239 (as in RHEL 8) is a very conservative upper baseline for compatibility.

@christgau
Copy link
Copy Markdown
Owner

Note that the systemd units set DynamicUser=yes, which already implies these hardening options [...]

Thanks for this "heads up". That doesn't sound bad, IMO. I could remove the --chroot option from the service/unit file, after tuning the settings there, but downstream would have to adjust as well.

@marcosfrm
Copy link
Copy Markdown

I think adding the following options is a good first step toward removing the chroot:

  • ProtectHome=yes to override the implied ProtectHome=read-only (wsdd will not see /home/, /root, or /run/user)
  • PrivateDevices=yes to expose only /dev/null, /dev/zero, and /dev/urandom (and nothing else from /dev)

Then remove RuntimeDirectory=... and AmbientCapabilities=CAP_SYS_CHROOT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants