config dir owned by root

Hi all,
I've run into an aspect of matplotlib's setup that seems awkward. I'm seeing this on Ubuntu, but I imagine it would happen on any *nix platform.

If python is running under sudo the first time matplotlib is imported, then matplotlib creates its config dir (~/.matplotlib) with root as the owner. Subsequent attempts to import matplotlib while running python as a non-privileged user result in this:

···

-----------------------------------------------------------------
RuntimeError: '/home/philip' is not a writable dir; you must set /home/philip/.matplotlib to be a writable dir. You can also set environment variable MPLCONFIGDIR to any writable directory where you want matplotlib data stored
-----------------------------------------------------------------

A simple way to re-create this --
1. Delete or rename ~/.matplotlib
2. sudo python -c "import matplotlib"
3. python -c "import matplotlib"

This not-improbable real-world scenario would create ~/.matplotlib owned by root --
1) Download app FooBar that has matplotlib as a dependency
2) Install matplotlib
3) Run FooBar's setup.py as sudo. It imports matplotlib, perhaps just to ensure that matplotlib is installed and working.

We ran into a similar situation with our app ('sudo python setup.py install' created desktop icons owned by root) and we resolved it by invoking chown after using a getenv() call to sniff out who we really wanted to own the file.

It looks like the diff below (untested!) applied to lib/matplotlib/__init__.py would prevent this from happening. Does it seems reasonable to add it?

474a475,485

        if not sys.platform.lower().startswith("win"):
            # Ensure that we didn't just create a root-owned directory in the
            # user's HOME directory. That happens if this is being run under
            # sudo. If the SUDO_USER env. var (which contains the user that
            # invoked sudo) then we're running under sudo. If it doesn't
            # exist, we're not running under sudo.
            current_user = os.getenv("SUDO_USER")
            if current_user:
                subprocess.call(["chown", "-R", current_user, p])

Thanks
Philip

If you don't have any special use for the config dir, this might be a more straightforward solution that doesn't require patching matplotlib.

Simply paste this in your code, before importing matplotlib :

import os
os.environ['HOME'] = '/tmp/'

Might be safer to use 'MPLCONFIGDIR' instead of 'HOME'.

Hope this helps.

Matthieu

···

Le 04/11/2010 16:49, Philip Semanchuk a écrit :

Hi all,
I've run into an aspect of matplotlib's setup that seems awkward. I'm seeing this on Ubuntu, but I imagine it would happen on any *nix platform.

If python is running under sudo the first time matplotlib is imported, then matplotlib creates its config dir (~/.matplotlib) with root as the owner. Subsequent attempts to import matplotlib while running python as a non-privileged user result in this:

-----------------------------------------------------------------
RuntimeError: '/home/philip' is not a writable dir; you must set /home/philip/.matplotlib to be a writable dir. You can also set environment variable MPLCONFIGDIR to any writable directory where you want matplotlib data stored
-----------------------------------------------------------------

A simple way to re-create this --
1. Delete or rename ~/.matplotlib
2. sudo python -c "import matplotlib"
3. python -c "import matplotlib"

This not-improbable real-world scenario would create ~/.matplotlib owned by root --
1) Download app FooBar that has matplotlib as a dependency
2) Install matplotlib
3) Run FooBar's setup.py as sudo. It imports matplotlib, perhaps just to ensure that matplotlib is installed and working.

We ran into a similar situation with our app ('sudo python setup.py install' created desktop icons owned by root) and we resolved it by invoking chown after using a getenv() call to sniff out who we really wanted to own the file.

It looks like the diff below (untested!) applied to lib/matplotlib/__init__.py would prevent this from happening. Does it seems reasonable to add it?

474a475,485

         if not sys.platform.lower().startswith("win"):
             # Ensure that we didn't just create a root-owned directory in the
             # user's HOME directory. That happens if this is being run under
             # sudo. If the SUDO_USER env. var (which contains the user that
             # invoked sudo) then we're running under sudo. If it doesn't
             # exist, we're not running under sudo.
             current_user = os.getenv("SUDO_USER")
             if current_user:
                 subprocess.call(["chown", "-R", current_user, p])

Thanks
Philip

------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

I'm not sure how I feel about this. On one hand, it is a pain to have
this not work under sudo. On the other, I consider the fact that $HOME
is not set to "/root" when running as root to be a bit of a problem.
Personally, the better solution to me would be to make sure $HOME is
one of the variables that gets reset by sudo.

Ryan

···

On Thu, Nov 4, 2010 at 10:49 AM, Philip Semanchuk <philip@...3340...> wrote:

Hi all,
I've run into an aspect of matplotlib's setup that seems awkward. I'm seeing this on Ubuntu, but I imagine it would happen on any *nix platform.

If python is running under sudo the first time matplotlib is imported, then matplotlib creates its config dir (~/.matplotlib) with root as the owner. Subsequent attempts to import matplotlib while running python as a non-privileged user result in this:

-----------------------------------------------------------------
RuntimeError: '/home/philip' is not a writable dir; you must set /home/philip/.matplotlib to be a writable dir. You can also set environment variable MPLCONFIGDIR to any writable directory where you want matplotlib data stored
-----------------------------------------------------------------

A simple way to re-create this --
1. Delete or rename ~/.matplotlib
2. sudo python -c "import matplotlib"
3. python -c "import matplotlib"

This not-improbable real-world scenario would create ~/.matplotlib owned by root --
1) Download app FooBar that has matplotlib as a dependency
2) Install matplotlib
3) Run FooBar's setup.py as sudo. It imports matplotlib, perhaps just to ensure that matplotlib is installed and working.

We ran into a similar situation with our app ('sudo python setup.py install' created desktop icons owned by root) and we resolved it by invoking chown after using a getenv() call to sniff out who we really wanted to own the file.

It looks like the diff below (untested!) applied to lib/matplotlib/__init__.py would prevent this from happening. Does it seems reasonable to add it?

474a475,485

    if not sys\.platform\.lower\(\)\.startswith\(&quot;win&quot;\):
        \# Ensure that we didn&#39;t just create a root\-owned directory in the
        \# user&#39;s HOME directory\. That happens if this is being run under
        \# sudo\. If the SUDO\_USER env\. var \(which contains the user that
        \# invoked sudo\) then we&#39;re running under sudo\. If it doesn&#39;t
        \# exist, we&#39;re not running under sudo\.
        current\_user = os\.getenv\(&quot;SUDO\_USER&quot;\)
        if current\_user:
            subprocess\.call\(\[&quot;chown&quot;, &quot;\-R&quot;, current\_user, p\]\)

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Hi Ryan,
Thanks. I don't know why sudo behaves the way it does with regard to $HOME, but the behavior of sudo is not under my control (nor matplotlib's). Also, I expect that *lots* of software depends on this behavior of sudo so changing it is probably not an option.

@Matthieu --

Merci Matthieu, yours is an elegant solution. In our setup.py we're just importing matplotlib to ensure it exists, so that fits your scenario.

The workaround I used was this --

    MATPLOTLIB_CONFIG_PATH = os.path.join(os.path.expanduser('~'), ".matplotlib")

    if not sys.platform.lower().startswith("win"):
        if not os.path.exists(MATPLOTLIB_CONFIG_PATH):
            check_matplotlib_permissions = True
        
    # Do stuff that triggers an import of matplotlib...

    if check_matplotlib_permissions:
        if os.path.exists(MATPLOTLIB_CONFIG_PATH):
            sudo_user = os.getenv("SUDO_USER")
            if sudo_user:
                subprocess.call(["chown", "-R", sudo_user, MATPLOTLIB_CONFIG_PATH])

I think I like your idea better.

Cheers
Philip

PS - Matthieu, sorry for not quoting you directly but I was unable to subscribe to the list before I received your mail.

···

On Nov 8, 2010, at 9:13 AM, Ryan May wrote:

On Thu, Nov 4, 2010 at 10:49 AM, Philip Semanchuk <philip@...3340...> wrote:

Hi all,
I've run into an aspect of matplotlib's setup that seems awkward. I'm seeing this on Ubuntu, but I imagine it would happen on any *nix platform.

If python is running under sudo the first time matplotlib is imported, then matplotlib creates its config dir (~/.matplotlib) with root as the owner. Subsequent attempts to import matplotlib while running python as a non-privileged user result in this:

-----------------------------------------------------------------
RuntimeError: '/home/philip' is not a writable dir; you must set /home/philip/.matplotlib to be a writable dir. You can also set environment variable MPLCONFIGDIR to any writable directory where you want matplotlib data stored
-----------------------------------------------------------------

A simple way to re-create this --
1. Delete or rename ~/.matplotlib
2. sudo python -c "import matplotlib"
3. python -c "import matplotlib"

This not-improbable real-world scenario would create ~/.matplotlib owned by root --
1) Download app FooBar that has matplotlib as a dependency
2) Install matplotlib
3) Run FooBar's setup.py as sudo. It imports matplotlib, perhaps just to ensure that matplotlib is installed and working.

We ran into a similar situation with our app ('sudo python setup.py install' created desktop icons owned by root) and we resolved it by invoking chown after using a getenv() call to sniff out who we really wanted to own the file.

It looks like the diff below (untested!) applied to lib/matplotlib/__init__.py would prevent this from happening. Does it seems reasonable to add it?

474a475,485

        if not sys.platform.lower().startswith("win"):
            # Ensure that we didn't just create a root-owned directory in the
            # user's HOME directory. That happens if this is being run under
            # sudo. If the SUDO_USER env. var (which contains the user that
            # invoked sudo) then we're running under sudo. If it doesn't
            # exist, we're not running under sudo.
            current_user = os.getenv("SUDO_USER")
            if current_user:
                subprocess.call(["chown", "-R", current_user, p])

I'm not sure how I feel about this. On one hand, it is a pain to have
this not work under sudo. On the other, I consider the fact that $HOME
is not set to "/root" when running as root to be a bit of a problem.
Personally, the better solution to me would be to make sure $HOME is
one of the variables that gets reset by sudo.

Sounds like you've found your solution (which is great), but to set
the record straight, you *can* control the behavior of sudo. In
/etc/sudoers, you can set env_reset to reset the environment, so none
of your variables (like $HOME). You can also just specify certain
variables to be reset. There is also an option always_set_home which
seems to do the right thing. In fact, on my machine, sudo works just
fine:

~> sudo python -c 'import os;print os.environ["HOME"]'
/root

So, so long as you can edit /etc/sudoers, you are *very much* in
control of how sudo works in this regard.

Ryan

···

On Mon, Nov 8, 2010 at 8:34 AM, Philip Semanchuk <philip@...3340...> wrote:

Hi Ryan,
Thanks. I don't know why sudo behaves the way it does with regard to $HOME, but the behavior of sudo is not under my control (nor matplotlib's). Also, I expect that *lots* of software depends on this behavior of sudo so changing it is probably not an option.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Thanks for the education, Ryan.

I checked my Ubuntu 9.04 virtual install where I first saw this problem, and the contents of /etc/sudoers are as described here:
https://help.ubuntu.com/community/Sudoers#The%20Default%20Ubuntu%20Sudoers%20File

Sure enough, $HOME isn't altered by sudo:
~$ sudo python -c 'import os;print os.environ["HOME"]'
/home/philip

I observe the same under OS X, so this configuration of /etc/sudoers might not be ideal, but it's popular.

Thanks
P

···

On Nov 8, 2010, at 9:51 AM, Ryan May wrote:

On Mon, Nov 8, 2010 at 8:34 AM, Philip Semanchuk <philip@...3340...> wrote:

Hi Ryan,
Thanks. I don't know why sudo behaves the way it does with regard to $HOME, but the behavior of sudo is not under my control (nor matplotlib's). Also, I expect that *lots* of software depends on this behavior of sudo so changing it is probably not an option.

Sounds like you've found your solution (which is great), but to set
the record straight, you *can* control the behavior of sudo. In
/etc/sudoers, you can set env_reset to reset the environment, so none
of your variables (like $HOME). You can also just specify certain
variables to be reset. There is also an option always_set_home which
seems to do the right thing. In fact, on my machine, sudo works just
fine:

~> sudo python -c 'import os;print os.environ["HOME"]'
/root

So, so long as you can edit /etc/sudoers, you are *very much* in
control of how sudo works in this regard.