After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 656621 - g_spawn_*() calls executables in current directory without G_SPAWN_SEARCH_PATH
g_spawn_*() calls executables in current directory without G_SPAWN_SEARCH_PATH
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
2.29.x
Other Linux
: Normal major
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2011-08-16 06:27 UTC by Martin Pitt
Modified: 2011-10-16 20:10 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Clarify g_spawn_*() behaviour without full path (1.42 KB, patch)
2011-08-17 07:03 UTC, Martin Pitt
none Details | Review
Clarify g_spawn_*() behaviour without full path (1.42 KB, patch)
2011-10-16 20:09 UTC, Matthias Clasen
committed Details | Review
Add a tests of some GVfs functions (2.79 KB, patch)
2011-10-16 20:10 UTC, Matthias Clasen
committed Details | Review

Description Martin Pitt 2011-08-16 06:27:17 UTC
When specifying a program name without a path, and without specifying G_SPAWN_SEARCH_PATH, the g_spawn_* functions call the specified program from the current directory:

  $ cd /tmp/
  $ echo -e '#!/bin/sh\ntouch /tmp/pwned' > ls
  $ chmod 755 ls
  $ python -c 'from gi.repository import GLib; print GLib.spawn_sync(None, ["ls"], None, 0, None, None)'
  (True, '', '', 0)
  $ ls pwned 
  pwned

This also happens when specifying "/tmp" as first argument (working_dir), and also happens in C (that's where I originally noticed it from).

This behaves like "." was in $PATH, which isn't the case for good reason.

The documentation says

  "By default, the name of the program must be a full path; the PATH shell variable will only be searched if you pass the G_SPAWN_SEARCH_PATH flag."

so this case is actually undefined. But I think it would be safer and Linux/$PATH compliant to just fail with "command not found" instead of running stuff from cwd, which hides programming errors and introduces security flaws.
Comment 1 Matthias Clasen 2011-08-16 12:14:42 UTC
It is not undefined.

If you don't specify SEARCH_PATH, the executable name is taken as-is, so if you don't pass an absolute path, you get what see.

A patch to clarify the docs would be welcome.
Comment 2 Martin Pitt 2011-08-16 12:40:44 UTC
(In reply to comment #1)
> It is not undefined.

The documentation does not specify the case where you don't specify the full path without G_SPAWN_SEARCH_PATH, so from the POV of the documentation it is undefined.

> If you don't specify SEARCH_PATH, the executable name is taken as-is, so if you
> don't pass an absolute path, you get what see.

"taken as-is" seems to mean "run it from the current directory". That's precisely what I think should be changed :-)

> A patch to clarify the docs would be welcome.

If you think that the current behaviour is correct, then I can write a patch for this, but only reluctantly. I think this is seriously wrong behaviour, encourages sloppy usage of g_spawn_* and hides programming errors (forgetting to specify G_SPAWN_SEARCH_PATH as the most common cause).
Comment 3 Christian Dywan 2011-08-16 15:02:36 UTC
The behavior matches what you expect when you fopen, os.popen etc. so it doesn't seem surprising to me. And arguably it is very unlikely to develop code in /usr/bin or analoguous folders.

I second Matthias here, documentation is unclear if you've not already learnt other similar functions.
Comment 4 Martin Pitt 2011-08-17 06:54:00 UTC
(In reply to comment #3)
> The behavior matches what you expect when you fopen, os.popen etc. so it
> doesn't seem surprising to me.

Interesting, I never thought about running programs as opening files.

> And arguably it is very unlikely to develop code in /usr/bin or analoguous folders.

Erm, yes, but that's not related to this problem? It's not unlikely for programs to have their cwd in an user or even world writable directory such as /tmp/, so if other users can sneak in a rogue /tmp/ls, /tmp/cp, or whatnot, the process would unexpectedly use that one instead of the expected /bin/cp etc.

Of course that hopefully wouldn't happen, as when testing the software it should still complain about not finding the binary you are looking for (and thus make you specify G_SPAWN_SEARCH_PATH). But there are corner cases when this could happen, which is why I opened it as a normal bug and not as an "OMGsecurity!" urgent one.

> I second Matthias here, documentation is unclear if you've not already learnt
> other similar functions.

Well, if everyone else agrees that this is correct behaviour, then I give in and agree that this should at least be documented.
Comment 5 Martin Pitt 2011-08-17 07:03:56 UTC
Created attachment 194011 [details] [review]
Clarify g_spawn_*() behaviour without full path

FTR, I'm still convinced that the current behaviour is overzealous and dangerous, but at least documenting it is better than the status quo.

This patch documents this case.
Comment 6 Martin Pitt 2011-08-17 07:14:58 UTC
(In reply to comment #3)
> And arguably it is very unlikely to develop code in /usr/bin or analoguous folders.

To clarify, this is a scenario where this would be dangerous:

(1) Develop software in your source tree, which has

   ./myapp
   ./apphelper

(2) myapp.c does g_spawn_sync(NULL, ['apphelper'], NULL, 0, ...), i. e. forgets to specify G_SPAWN_SEARCH_PATH

(3) This works in the source tree when you run ./myapp, as apphelper is in the cwd

(4) make install, run "myapp"; as this calls /usr/bin/myapp, this is expected to call /usr/bin/apphelper, but actually calls ./apphelper

(5) developer thinks "yes, it works" and ships it

(6) does not work for the user, as he probably doesn't have /usr/bin/ as his cwd, so it would crash with "program not found"

(7) if you happen to run this in /tmp/, and there is a malicious /tmp/myapphelper (put there by another user), bad things happen

Arguably this is an unlikely scenario (again, which is why I didn't escalate this as OMGsecurity!), but even if it's not considered a major security issue, it's still unexpected. It should have failed with "no such program" in step (4).
Comment 7 Matthias Clasen 2011-10-16 20:09:56 UTC
The following fixes have been pushed:
1435db4 Clarify g_spawn_*() behaviour without full path
8ff94df Add a tests of some GVfs functions
Comment 8 Matthias Clasen 2011-10-16 20:09:59 UTC
Created attachment 199142 [details] [review]
Clarify g_spawn_*() behaviour without full path

Document the previously uncovered case of calling g_spawn_async_with_pipes()
without a full path but no G_SPAWN_SEARCH_PATH. This runs programs from the
current directory, which might be unexpected and even dangerous in some corner
cases.
Comment 9 Matthias Clasen 2011-10-16 20:10:02 UTC
Created attachment 199143 [details] [review]
Add a tests of some GVfs functions