psutil
psutil copied to clipboard
[linux] how can psutil show `exe` if the linx is not readable?
Summary
- OS: Linux 6.5.13
- Architecture: 64bit
- Psutil version: 5.9.5
- Python version: 3.11.7
- Type: core
Description
I wondered how psutil
the following can happen.
As a normal user:
$ id -u
1000
$
$ readlink /proc/3763/exe; echo $?
1
$ readlink /proc/4372/exe; echo $?
1
the exe
information (and others) for these processes (which are Xorg
and lightdm
) cannot be read.
But their cmdline
can:
$ hd /proc/3763/cmdline
00000000 2f 75 73 72 2f 6c 69 62 2f 78 6f 72 67 2f 58 6f |/usr/lib/xorg/Xo|
00000010 72 67 00 3a 30 00 2d 73 65 61 74 00 73 65 61 74 |rg.:0.-seat.seat|
00000020 30 00 2d 61 75 74 68 00 2f 76 61 72 2f 72 75 6e |0.-auth./var/run|
00000030 2f 6c 69 67 68 74 64 6d 2f 72 6f 6f 74 2f 3a 30 |/lightdm/root/:0|
00000040 00 2d 6e 6f 6c 69 73 74 65 6e 00 74 63 70 00 76 |.-nolisten.tcp.v|
00000050 74 37 00 2d 6e 6f 76 74 73 77 69 74 63 68 00 |t7.-novtswitch.|
0000005f
$ hd /proc/4372/cmdline
00000000 6c 69 67 68 74 64 6d 00 2d 2d 73 65 73 73 69 6f |lightdm.--sessio|
00000010 6e 2d 63 68 69 6c 64 00 31 33 00 32 34 00 |n-child.13.24.|
0000001e
Now, when again as the same user (UID 1000
), I do the following with psutil:
>>> import psutil
>>> p1=psutil.Process(pid=3763)
>>> p2=psutil.Process(pid=4372)
>>> p1.exe()
'/usr/lib/xorg/Xorg'
>>> p2.exe()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/psutil/__init__.py", line 671, in exe
return guess_it(fallback=err)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/psutil/__init__.py", line 664, in guess_it
raise fallback
File "/usr/lib/python3/dist-packages/psutil/__init__.py", line 669, in exe
exe = self._proc.exe()
^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/psutil/_pslinux.py", line 1767, in exe
raise AccessDenied(self.pid, self._name)
psutil.AccessDenied: (pid=4372)
>>>
So if exe
is unreadable in both cases, how can it know the exe
in the first case?
My assumption is, that it somehow takes cmdline
, but perhaps only if that starts with an absolute path?
I tried to look it up in the code, but couldn't find anything at a first glance:
https://github.com/giampaolo/psutil/blob/master/psutil/_pslinux.py#L1763-L1773
If it would somehow use cmdline
, that would IMO be a security hole. Processes can modify their own cmdline
so when another process would e.g. trust that exe()
returns the right executable, this might be wrong and so the user of exe()
could be lead into doing bad things.
Any idea how your code does the magic to get the executable despite the symlink in /proc
not being readable?
Thanks, Chris.
Magic explained: https://github.com/giampaolo/psutil/blob/4407540e720c46641622a33bb579430e047cd511/psutil/init.py#L662-L687. :)
Well but as I wrote quite lengthy, this is actually a security hole as any process may thereby fake it's executable to be something else.
So could you please reopen and ... well simply not do this?
Sorry, I was in a rush and only focused on the first part of your post.
I see your point. Reopening, but I'll have to think about this. Maybe we can add a guess=True
argument.
No worries.
Uhm, I would rather suggest to call it unsafe
. That makes it much more of a heads up and people have a better chance to actually realise what's going on and make a proper choice.
And adding some warning box in the documentation, that when this is True
processes might hide their own true executable, would be nice.