go 建议:os/exec: 当参数为相对路径时,从LookPath返回ErrDot,

bkkx9g8r  于 4个月前  发布在  Go
关注(0)|答案(5)|浏览(72)

os/exec 包的文档以及 LookPath 函数的文档详细说明了 LookPath 的安全属性,这些属性旨在减少在当前目录中查找二进制文件的问题。它们还表示,如果没有返回 ErrDot,LookPath 将无法解析一个使用相对于当前目录的隐式或显式路径条目的程序。然而,这目前并不完全正确。

假设你在一个包含子目录 bin 的目录中,bin 本身包含一个可执行文件 prog,然后你调用 exec.LookPath("bin/prog"),它将返回 "bin/prog", nil。从表面上看,这似乎是合理的,因为你请求的是相对于当前目录的路径,而它给了你。问题在于,鉴于 LookPath 的安全属性,这一点并不明显,因此在不成立的情况下对其属性进行假设可能会带来一定的危险。

根据几位开发者的非正式调查,没有人正确猜出上面描述的例子的结果,大多数人都认为结果应该是 "bin/prog", ErrDot,我认为这是一个合理的假设。

我建议我们要么让 LookPath 在返回的路径不是绝对路径时总是返回 ErrDot(我相信这是符合当前文档的),或者更新文档以明确表示,如果你明确传递了一个相对路径,它将不会返回 ErrDot(我对前者有较强的偏好,但也可以说服其他人采用后者)。

j8yoct9x

j8yoct9x1#

如果执行一个包含斜杠的命令,那么根据定义,PATH环境变量不会被咨询。因此,不会出现任何“路径查找”。因此,返回exec.ErrDot将违反其文档。
ErrDot表示由于路径中包含'.'(隐式或显式),导致路径查找解析为当前目录中的可执行文件。
由于这在技术上实际上是一个破坏性更改,我认为我们需要对提议的更改有很高的要求。今天是否存在具体的安全问题?
总之,是否有实际用例需要将包含斜杠的名称传递给exec.LookPath?似乎有点无意义。

qgelzfjb

qgelzfjb2#

如果执行一个包含斜杠的命令,那么根据定义,PATH环境变量不会被查询。因此,不会出现任何“路径查找”。因此,返回exec.ErrDot将违反其文档。
是的,LookPath文档指出这一点:
如果文件包含斜杠,它将直接尝试,而不考虑PATH。
但在第二段中又与之相矛盾:
在Go较旧的版本中,LookPath可以返回相对于当前目录的路径。从Go 1.19开始,LookPath将返回该路径以及一个满足errors.Is(err, ErrDot)的错误。有关更多详细信息,请参阅包文档。
然后,包文档通过以下内容使情况更加混乱:
[...] 从Go 1.19开始,此包将不会解析使用相对于当前目录的隐式或显式路径条目的程序。
这使得函数的操作变得非常令人困惑。如果你传递一个相对路径,它将被直接尝试,但是它会被返回带有ErrDot,还是不带?我认为我们可以修复这里的文档,但我个人认为API的操作与其(看似)预期的功能相悖。
实际上,似乎大多数人都认为LookPath要么只咨询PATH,要么直接尝试绝对路径,而不会咨询相对于当前目录的路径。我们已经多次看到LookPath的输入没有像开发者期望的那样进行适当的清理,导致安全问题,其中工具可能基于其所执行的目录结构来执行任意程序(这至少在一定程度上要对#62198负责)。

xe55xuns

xe55xuns3#

@rolandshoemaker 包的文档是正确的。它并不是“相对于当前目录使用隐式或显式路径条目”,因为它根本不使用路径条目(即,PATH环境变量)。严格来说,是exec.LookPath的文档关于exec.ErrDot应该意味着什么做出了不一致的声明。
我还要指出,即使你做了这个改变,开发者仍然需要知道如何使用exec.LookPath。如果你直接使用exec.Command,你将不会得到任何错误,而改变这一点绝对是一个更大的破坏性改变。在这一点上偏离exec.LookPathexec.Command似乎可能导致更大的困惑。
关于链接的问题,我质疑甚至允许绝对路径是否真的有意为之。为此,似乎真正的问题并不在于对exec.ErrDot的需求,而更像是“你要求进行路径查找,但输入不需要”。因此,也许为了澄清这一点,可以添加一个专门针对这种情况的新错误情况会更好?

dzhpxtsq

dzhpxtsq4#

@rolandshoemaker 包文档的描述是正确的。它并不是“相对于当前目录使用隐式或显式路径条目”,因为它根本不使用路径条目(即,PATH环境变量)。

我认为这种解释给读者带来了很大的负担,要求他们正确理解“此包不会解析程序”中的“解析”一词指的是使用PATH查找算法,而不仅仅是指它根本不会返回相对路径。

我还要指出,即使你做了这个改变,开发者仍然需要知道如何使用exec.LookPath。如果你直接使用exec.Command,你将不会得到任何错误,而改变这一点绝对是一个更大的破坏性改变。在这一点上,将exec.LookPath和exec.Command分开似乎可能导致更大的困惑。

这种情况是如何导致分歧的?因为只有在“名称不包含路径分隔符”时,Command才会使用LookPath,也就是说,只有当它传递一个裸露的程序名时。

我认为对我的提案最强有力的反对意见是,这与大多数Linux shell实现和Windows命令提示符的语义相悖离。

关于链接的问题,我质疑即使允许绝对路径是否真的有意为之。在这方面,真正的问题似乎不是exec.ErrDot的需求,而是“你请求了一个路径查找,但输入并不需要一个”。因此,也许为了更清楚地说明这一点,可以添加一个新的错误情况?

这看起来像一个更严重的破坏性改变,不是吗?

yzuktlbb

yzuktlbb5#

我认为这种解释给读者带来了很大的负担,让他们正确理解“这个包不会解决程序”中的“解决”一词指的是PATH查找算法的使用,而不仅仅是它根本不会返回相对路径。
接下来的两句话进一步解释了这个问题。
也就是说,如果你运行exec.LookPath("go"),无论路径如何配置,它都不会在Unix上成功返回./go,也不会在Windows上返回.\go.exe。相反,如果通常的路径算法会导致这样的答案,这些函数将返回一个满足errors.Is(err, ErrDot)的错误。
稍后它明确提到相对路径不是一个错误。
总是想从当前目录运行程序的代码可以重写为说“./prog”而不是“prog”。
所以我觉得现有的文档很清楚。但它可能应该说“$PATH条目”而不是“路径条目”,以强调它的意义。
这怎么会导致分歧呢?命令只在“名称不包含路径分隔符”时使用LookPath,即只传递一个裸程序名称。
因为如果我现在向exec.LookPath传递一个像“./go”这样的命令名,我得到的是exec.ErrDot,但如果我向exec.Command传递相同的名称,我却得不到。这很令人困惑,也使得exec.ErrDot的意义不一致。
这似乎是一个更严重的破坏性更改,不是吗?
你已经会让所有向exec.LookPath传递相对路径的人感到困惑。而且现在如果我得到exec.ErrDot,它可能意味着我的PATH包含一个点,或者它可能意味着可执行文件名是一个相对路径。唯一能区分它们的方法就是查看可执行文件名,而那时返回exec.ErrDot就没有什么意义了。

相关问题