I have two files, a.py:
import os, subprocess
os.chroot(".")
subprocess.run(["./b.sh"])
and b.sh:
#!/usr/bin/env bash
echo whateva
in an otherwise empty directory. b.sh has executable permission.
Why does python3 a.py fail with:
Traceback (most recent call last):
File "/yadda/yadda/a.py", line 5, in <module>
File "/usr/lib/python3.11/subprocess.py", line 548, in run
File "/usr/lib/python3.11/subprocess.py", line 1024, in __init__
File "/usr/lib/python3.11/subprocess.py", line 1917, in _execute_child
FileNotFoundError: [Errno 2] No such file or directory: './b.sh'
This is running as root, uname -a is Linux me 6.4.1-arch2-1 #1 SMP PREEMPT_DYNAMIC Tue, 04 Jul 2023 08:39:40 +0000 x86_64 GNU/Linux (I get the same behavior in a Ubuntu Docker container). What am I not understanding? Do I need a shell binary in the chroot?
Thank you!
You are missing the
envexecutable, or it exist in a different path under your chrooted tree (i.e. not under/usr/env/). This can be easily demonstrated even without chroot. Let's remove the chroot, and change b.sh as follows:Unix (in my case MacOS, but also Linux) will fail executing no_such_file like so:
But simply changing it to a valid executable (back to
env) will load just fine:If you don't need the shell script to be portable, and as you mentioned in a comment that you already have a
bashcross-compiled binary, you can simply use that instead ofenv, such as#!/bin/bash. The path to the binary must be within the chroot environment, so in case it resides elsewhere - make sure to update it accordingly.Diving a bit deeper,
execve(2)'s man page somewhat explains thatENOENTis set if the executable cannot be found. I've also found this page which might provide a better explanation as to why the failure seems to be related tob.shexistence instead of the binary itself.