Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys.executable is sometimes wrong #124241

Open
tecki opened this issue Sep 19, 2024 · 9 comments
Open

sys.executable is sometimes wrong #124241

tecki opened this issue Sep 19, 2024 · 9 comments
Labels
type-bug An unexpected behavior, bug, or error

Comments

@tecki
Copy link
Contributor

tecki commented Sep 19, 2024

Bug report

Bug description:

On Linux, sys.executable is determined using argv[0], and trying to find that in the PATH. This presumes that the Python interpreter has been started by a shell that interprets PATH in the canonical way. There is no guarantee that this happens at all, so sys.executable may point to something completely different, or is even the empty string.

As an example:

bash -c 'exec -a whatever python -c "import sys;print(sys.executable)"'

should output the path of the Python executable, but simply outputs nothing.

Even worse, one can make Python output a wrong executable, as in

bash -c 'exec -a /usr/bin/python python -c "import sys;print(sys.executable)"'

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

@tecki tecki added the type-bug An unexpected behavior, bug, or error label Sep 19, 2024
@skirpichev skirpichev added type-feature A feature request or enhancement and removed type-bug An unexpected behavior, bug, or error labels Sep 19, 2024
@skirpichev
Copy link
Member

I can confirm first behaviour:

sk@note:~/src/peps $ which python
sk@note:~/src/peps $ which python3
/usr/local/bin/python3
sk@note:~/src/peps $ bash -c 'exec -a whatever python3 -c "import sys;print(sys.executable)"'

But not the second:

$ bash -c 'exec -a /usr/local/bin/python3 python3 -c "import sys;print(sys.executable)"'
/usr/local/bin/python3

Could you, please, show us output of which python?

Anyway, this seems to be documented: "If Python is unable to retrieve the real path to its executable, sys.executable will be an empty string or None."

Meanwhile, I'll relabel your issue as a feature request.

@ZeroIntensity
Copy link
Member

@skirpichev, maybe this is a permissions issue? I'm on a root user, and I was able to reproduce the second behavior. Running the following on my results in /usr/bin/echo being printed:

$ bash -c 'exec -a echo python3 -c "import sys;print(sys.executable)"'
/usr/bin/echo

Interestingly, running it with a path that doesn't exist results in a fatal error:

$ bash -c 'exec -a evil python3 -c "import sys;print(sys.executable)"'
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007f8899f14080 (most recent call first):
  <no Python frame>

Injection of arbitrary files into sys.executable seems like a security problem to me (but maybe not if this only occurs on root users).

@skirpichev
Copy link
Member

skirpichev commented Sep 19, 2024

maybe this is a permissions issue?

Maybe PATH settings?

That does work for me and doesn't look right:

$ bash -c 'exec -a /usr/bin/evil python3 -c "import sys;print(sys.executable)"'
/usr/bin/evil

Edit:

Perhaps, this should mentioned somehow in docs.

Injection of arbitrary files into sys.executable seems like a security problem

I doubt you can do too much with this mechanism. Unless there are other options to override arg0. There are e.g. various exec*() calls in POSIX, but it's essentially same. Yes, you can abuse mechanism for yourself (regardless on your rights), but what you gain? I doubt this will be a security issue without decent part of social engineering;)

@skirpichev skirpichev added type-bug An unexpected behavior, bug, or error and removed type-feature A feature request or enhancement labels Sep 19, 2024
@ZeroIntensity
Copy link
Member

I could see it being a problem for applications that use subprocess.blah_blah([sys.executable, "..."))

It's not a terrible vulnerability, but e.g. a user on a Linux machine owned by their company could use it to mess with whatever software the employer has installed to their computer. (Kind of a bad example, but you get the general idea.)

@skirpichev
Copy link
Member

But what evil you could do with this, assuming you can point sys.executable to an arbitrary file? Company software will execute one?

Wait, but that means that someone else put in system some file, that you already can run (suitable permissions, including executable bit). Then why not run directly?

@ZeroIntensity
Copy link
Member

Possibly, I'm just speculating 😃

Regardless, this is a bug. I think we should try to stop sys.executable from holding the wrong thing, rather than just documenting it.

@skirpichev
Copy link
Member

I think we should try to stop sys.executable from holding the wrong thing

I don't know universal ways to do so. E.g. on Linux (and I think BSD nowadays), you can use /proc//exe symlink.

@ZeroIntensity
Copy link
Member

I don't know universal ways to do so.

Me neither. But I'm not too sure who to CC on this. I guess if this only affects Linux then /proc/exe should work.

@skirpichev
Copy link
Member

I guess if this only affects Linux

No, I think it should affect any system with POSIX exec*() functions, for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants