ふり返る暇なんて無いね

日々のメモ書きをつらつらと

sudo -Hと環境変数($PATH)ではまった話

当たり前の話ではありますが、何を勘違いしてたか、今までsudo -Hすれば、$PATHをはじめとした環境変数がスイッチ後のユーザの物が使われると思っていました。
sudo -H してるのに$PATHが実行ユーザのもの引き継いだままで何故だーとはまっていました。

実際は-Hオプションは$HOMEを書き換えてくれるだけのオプションです。

% man sudo

... 前略

       -H          The -H (HOME) option requests that the security policy set the HOME
                   environment variable to the home directory of the target user (root
                   by default) as specified by the password database.  Depending on the
                   policy, this may be the default behavior.

ちなみに/etc/sudoersにalways_set_homeを指定しておけば、デフォルトで-Hの挙動です。

再現

環境

一般的なubuntu 12.04です。

% lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 12.04.5 LTS
Release:        12.04
Codename:       precise
% uname -a
Linux lab 3.2.0-60-generic #91-Ubuntu SMP Wed Feb 19 03:54:44 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
% sudo -V
Sudo version 1.8.3p1
Sudoers policy plugin version 1.8.3p1
Sudoers file grammar version 40
Sudoers I/O plugin version 1.8.3p1

準備

$PATHと$HOMEをechoするだけのシェルスクリプトを用意しておきます。

% cat << '...' > /tmp/tmp.sh
#!/bin/bash
echo $PATH
echo $HOME
id
...
% chmod +x /tmp/tmp.sh

ユーザのPATHの確認

% /tmp/tmp.sh
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/masasuzu/bin
/home/masasuzu
uid=1000(masasuzu) gid=1000(masasuzu) groups=1000(masasuzu),4(adm),20(dialout),24(cdrom),46(plugdev),107(lpadmin),108(sambashare),109(admin)

sudoしてみる

sudo してもユーザの$PATHも$HOMEを引き継いだまま。

% sudo /tmp/tmp.sh
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/masasuzu/bin
/home/masasuzu
uid=0(root) gid=0(root) groups=0(root)

$HOMEはスイッチ後のユーザのものですが、$PATHはそのまま。

% sudo -H /tmp/tmp.sh
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/masasuzu/bin
/root

ちょっとしたからくり

これたぶん、これを読んでる人が同じ手順を手元で追試してみるとこういう結果にはならないと思います。

Ubuntu 12.04だと/etc/sudoersに下記の記述があるため、sudoしたときにPATHは書き換わってくれるからです。

Defaults   secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

セットアップスクリプトの不備でsudoersを書き換える際にsecure_pathをごそっと消してしまったため、前述のように実行ユーザの$PATHが引き継がれておかしなことになっていた次第です。


ちなみにexempt_groupでグループ指定しておけば、secure_pathが指定されず、$PATHを引き継いで使えるようです

% man sudoers

... 前略

       secure_path Path used for every command run from sudo.  If you don't trust the
                   people running sudo to have a sane PATH environment variable you may
                   want to use this.  Another use is if you want to have the "root
                   path" be separate from the "user path."  Users in the group
                   specified by the exempt_group option are not affected by
                   secure_path.  This option is not set by default.

蛇足1

rootでsudo -Vすると削除される環境変数、引き継ぐ環境変数の一覧を見ることができます。

% sudo sudo -V

... 前略

Environment variables to check for sanity:
        TERM
        LINGUAS
        LC_*
        LANGUAGE
        LANG
        COLORTERM
Environment variables to remove:
        RUBYOPT
        RUBYLIB
        PYTHONUSERBASE
        PYTHONINSPECT
        PYTHONPATH
        PYTHONHOME
        TMPPREFIX
        ZDOTDIR
        READNULLCMD
        NULLCMD
        FPATH
        PERL5DB
        PERL5OPT
        PERL5LIB
        PERLLIB
        PERLIO_DEBUG
        JAVA_TOOL_OPTIONS
        SHELLOPTS
        GLOBIGNORE
        PS4
        BASH_ENV
        ENV
        TERMCAP
        TERMPATH
        TERMINFO_DIRS
        TERMINFO
        _RLD*
        LD_*
        PATH_LOCALE
        NLSPATH
        HOSTALIASES
        RES_OPTIONS
        LOCALDOMAIN
        CDPATH
        IFS
Environment variables to preserve:
        XAUTHORIZATION
        XAUTHORITY
        TZ
        PS2
        PS1
        PATH
        LS_COLORS
        KRB5CCNAME
        HOSTNAME
        HOME
        DISPLAY
        COLORS

蛇足2

secure_pathがデフォルトの状態でも実行の仕方によって挙動の違いがでます。sudoなかなか味わい深い。調べる時間があったらまた書くかも。

% sudo /tmp/tmp.sh
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/home/masasuzu
uid=0(root) gid=0(root) groups=0(root)

% sudo -i /tmp/tmp.sh
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/root
uid=0(root) gid=0(root) groups=0(root)

% sudo -s /tmp/tmp.sh
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/masasuzu/bin
/home/masasuzu
uid=0(root) gid=0(root) groups=0(root)

% sudo su -c /tmp/tmp.sh
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
/root
uid=0(root) gid=0(root) groups=0(root)

% sudo su - -c /tmp/tmp.sh
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/root
uid=0(root) gid=0(root) groups=0(root)