Sudo 更改 PATH,但执行相同的二进制文件

Pio*_*ost 7 sudo path

安装了两个 Python 解释器:

[user@localhost ~]$ /usr/bin/python -V && /usr/local/bin/python -V
Python 2.4.3
Python 2.7.6
Run Code Online (Sandbox Code Playgroud)

Sudo 在执行时更改 PATH:

[user@localhost ~]$ env | grep PATH && sudo env | grep PATH
PATH=/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/user/bin
PATH=/usr/bin:/bin
Run Code Online (Sandbox Code Playgroud)

然而,通过 sudo 运行 Python 与直接运行是一样的:

[user@localhost ~]$ sudo python -V && python -V
Python 2.7.6
Python 2.7.6
Run Code Online (Sandbox Code Playgroud)

我希望sudo python运行/usr/bin/python这是修改后的PATH. 为什么它会运行/usr/local/bin/python

我在 sudo-users 邮件列表上问了这个问题,但在与 sudo 维护者 Todd C. Miller 的讨论中我们找不到这种行为的原因。

以供参考:

[user@localhost ~]$ sudo -l
Matching Defaults entries for user on this host:
    requiretty, !visiblepw, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS
    LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE
    LINGUAS _XKB_CHARSET XAUTHORITY"

Runas and Command-specific defaults for user:


User user may run the following commands on this host:
    (ALL) NOPASSWD: ALL


[user@localhost ~]$ sudo sudo -V
Sudo version 1.7.2p1

Sudoers path: /etc/sudoers
nsswitch path: /etc/nsswitch.conf
ldap.conf path: /etc/ldap.conf
ldap.secret path: /etc/ldap.secret
Authentication methods: 'pam'
Syslog facility if syslog is being used for logging: authpriv
Syslog priority to use when user authenticates successfully: notice
Syslog priority to use when user authenticates unsuccessfully: alert
Ignore '.' in $PATH
Send mail if the user is not in sudoers
Use a separate timestamp for each user/tty combo
Lecture user the first time they run sudo
Require users to authenticate by default
Root may run sudo
Allow some information gathering to give useful error messages
Visudo will honor the EDITOR environment variable
Set the LOGNAME and USER environment variables
Length at which to wrap log file lines (0 for no wrap): 80
Authentication timestamp timeout: 5 minutes
Password prompt timeout: 5 minutes
Number of tries to enter a password: 3
Umask to use or 0777 to use user's: 022
Path to mail program: /usr/sbin/sendmail
Flags for mail program: -t
Address to send mail to: root
Subject line for mail messages: *** SECURITY information for %h ***
Incorrect password message: Sorry, try again.
Path to authentication timestamp dir: /var/run/sudo
Default password prompt: [sudo] password for %p: 
Default user to run commands as: root
Path to the editor for use by visudo: /bin/vi
When to require a password for 'list' pseudocommand: any
When to require a password for 'verify' pseudocommand: all
File containing dummy exec functions: /usr/libexec/sudo_noexec.so
File descriptors >= 3 will be closed before executing a command
Reset the environment to a default set of variables
Environment variables to check for sanity:
        TERM
        LINGUAS
        LC_*
        LANGUAGE
        LANG
        COLORTERM
Environment variables to remove:
        RUBYOPT
        RUBYLIB
        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
        MAIL
        LS_COLORS
        KRB5CCNAME
        HOSTNAME
        HOME
        DISPLAY
        COLORS
Locale to use while parsing sudoers: C
Local IP address and netmask pairs:
        10.0.2.15 / 255.255.255.0
        fe80::a00:27ff:febb:56ce / ffff:ffff:ffff:ffff::


[user@localhost ~]$ sudo cat /etc/sudoers | grep -v -E '^#|^$'
Defaults    requiretty
Defaults   !visiblepw
Defaults    env_reset
Defaults    env_keep = "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR \
                        LS_COLORS MAIL PS1 PS2 QTDIR USERNAME \
                        LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION \
                        LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC \
                        LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS \
                        _XKB_CHARSET XAUTHORITY"
root    ALL=(ALL)       ALL
user    ALL=(ALL)       NOPASSWD: ALL


[user@localhost ~]$ which sudo && command -V sudo
/usr/bin/sudo
sudo is hashed (/usr/bin/sudo)

[user@localhost ~]$ cat /etc/redhat-release 
Red Hat Enterprise Linux Server release 5.10 (Tikanga)
Run Code Online (Sandbox Code Playgroud)

Gra*_*eme 6

您会PATH在实际sudo执行环境中的PATH哪个和sudo它运行的程序环境中的哪个设置之间感到困惑。从sudo手册:

当sudo运行一个命令时,它会调用fork(2),如上所述设置执行环境,并在子进程中调用execve系统调用。

随着execve你指定你想要的子进程有环境,也就是说,它可以从父进程不同。

通常secure_path会设置在/etc/sudoers

安全路径

用于从 sudo 运行的每个命令的路径。如果你不相信运行 sudo 的人有一个健全的 PATH 环境变量,你可能想要使用它。另一个用途是如果您想让“根路径”与“用户路径”分开。由exempt_group 选项指定的组中的用户不受secure_path 的影响。默认情况下未设置此选项。

如果设置了此项,sudo将在此中搜索命令PATH并在它运行的命令的环境中设置此项。它还将显示在输出中sudo sudo -V,如下所示:

Value to override user's $PATH with: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Run Code Online (Sandbox Code Playgroud)

但是,在您的情况下,这未设置,因此sudoPATH在其自己的执行环境中使用(在这种情况下,它是从父 shell 继承的)。尽管它已配置为忽略当前目录,如果已将其放入PATH

Ignore '.' in $PATH
Run Code Online (Sandbox Code Playgroud)

由于env_reset is在您的/etc/sudoers(而PATH不是在env_keep字符串中),它调用的命令PATHsudo设置的that将由PAM或 by定义,/etc/environment因此与PATH sudo用于搜索其位置的用途不同:

默认情况下,启用 env_reset 选项。这会导致在新的最小环境中执行命令。在 AIX(和没有 PAM 的 Linux 系统)上,环境是用 /etc/environment 文件的内容初始化的。除了 env_check 和 env_keep 选项允许的调用过程中的变量之外,新环境还包含 TERM、PATH、HOME、MAIL、SHELL、LOGNAME、USER、USERNAME 和 SUDO_* 变量。

pythonPATHset by 中运行sudo,您应该执行以下操作:

sudo env python -V
Run Code Online (Sandbox Code Playgroud)

这样sudo,搜索命令的不是它自己,而是env设置环境sudoenv在那里搜索命令。