go 建议:运行时:不要在Windows上启用进程范围的长路径支持,

bxgwgixi  于 6个月前  发布在  Go
关注(0)|答案(8)|浏览(63)

建议详情

上下文

Go runtimeos 包目前在Windows上实现了两级长路径(超过260个字符)支持:

  • 通过设置一个未记录的PEB位(来源)来欺骗Windows,使其在不遵循官方方法的情况下启用进程范围内的长路径支持(在这里记录)。
  • 如果前一个hack不起作用,因为Windows版本低于1607,那么 os 包会进行一些路径操作(来源),以便在扩展路径前缀之前添加扩展路径前缀,这是使Windows API支持长路径的一种已记录的方法。请注意,当前实现并不完整,因为它不支持相对路径。

这些是与Windows上的长路径相关的问题:#41734#21782#36375
我最近给了一些CL邮件,以改进路径操作方法:CL 570995CL 574695

建议

我们(位于@microsoft的Go团队)建议删除这个未记录的PEB hack。
主要的担忧是长路径支持可能会被内部重新实现,不再使用Go运行时使用的PEB位,在这种情况下,该位可以被用于其他目的。如果发生这种情况,那么Go破坏PEB的可能性就很高。
这将是一个破坏性的行为改变。即使我们设法正确地支持 os 中的所有长路径情况,这个修复也不会应用于与os包之外的Windows API的交互,即使用 syscall 或cgo。受影响的用户必须按照官方方式启用长路径支持。
鉴于使用未记录的Windows API可能存在安全影响,我建议不要添加一个 GODEBUG 设置以获得旧行为。
此外,使用未记录的Windows API违反了微软的政策,而 Microsoft Go fork 已经被标记为执行PEB长路径支持hack。我们已经采取行动将其从我们的分支中删除,无论本建议的结果如何。另一方面,我们正在与Windows团队合作定义和记录API,以便更容易地实现长路径支持。
@golang/windows

b4qexyjb

b4qexyjb1#

感谢@rsc的澄清。让我们把这件事搁置到今年九月我休陪产假回来后再处理。

x759pob2

x759pob22#

已挂起

— rsc提案审查组

hlswsv35

hlswsv353#

我们(微软的Go团队)建议移除这个未记录的PEB技巧。
我反对你的提议。你的提议只会破坏现有的代码,而且你的更改没有任何好处。
主要的担忧是长路径支持可能会被内部重新实现,不再使用Go运行时使用的PEB位,在这种情况下,该位可以被用于其他目的。如果发生这种情况,那么Go损坏PEB的可能性就很高。
微软一直非常擅长支持现有的用户代码。我怀疑他们会支持Go技巧,直到有比Windows用户在注册表中捣乱更好的解决方案。如果我错了,我们可以在它破坏的时候移除这个技巧。
...我们正在与Windows团队合作,定义和记录API,这将使长路径支持更容易实现。
那将很好。谢谢。
Alex

ygya80vv

ygya80vv4#

我反对你的提议。你的提议只会破坏现有的代码,而且你的改变没有带来任何好处。
感谢你的反馈。我不认为它没有好处。只使用经过记录、审查和良好支持的功能是一个主要的好处,尤其是在这些天里,一切都容易被恶意行为者利用来获得立足点的情况下。
微软一直非常擅长支持现有的用户代码。我怀疑他们会支持Go hack,直到有比Windows用户在注册表上折腾更好的解决方案。如果我错了,我们可以在它出问题时移除这个hack。
这可能或可能不会发生。这是微软的一个成本效益权衡。一个数据点:据我所知,Go是唯一重要的运行时/框架,它使用PEB技巧来实现进程范围内的长路径支持。
如果我错了,我们可以在它出问题时移除这个hack。
公平的说法,尽管我还是更倾向于做正确的事情,以便未来能够预见。

w8f9ii69

w8f9ii695#

Go有一个确保正确事物工作的历史。有时这意味着查看未记录的API,直到记录的API出现。在Windows上,有没有官方的方法来启用每个进程的长路径?你链接的“官方方法”是一个影响所有进程的全局注册表键,而不仅仅是当前进程。为当前进程启用是有意义的,因为当前进程可以在不为机器上的其他内容做出声明的情况下声明“我知道如何处理这些长路径”。
此外,旧的Go二进制文件改变这个位存在,无法从世界上删除。考虑到Windows对向后兼容性的强调(我仍然可以运行1990年代编译的x86二进制文件),似乎无论如何在未来都不可能重新利用这个位。
看起来正确的前进方向是让Windows添加一个每个进程的官方方法。然后Go可以在运行在较新的Windows上时使用它。在此之前,让Go程序在当前和较旧的Windows上运行并处理长路径似乎不会有什么害处。

dzjeubhm

dzjeubhm6#

此建议已添加到建议项目中的活动列,并将在每周的建议审查会议上进行审查。
— rsc 建议审查组

yftpprvb

yftpprvb7#

在Windows上,是否有官方的方法来为每个进程启用长路径?你链接的“官方方法”是一个影响所有进程的全局注册表键,而不仅仅是当前进程。
全局注册表键不足以使所有进程支持长路径,但它是一个必需的设置。当设置了该注册表键时,只有包含longPathAware设置的应用程序清单的进程才会支持长路径(所有这些设置都在这里记录)。
看起来正确的前进方向是让Windows添加一个针对每个进程的官方方法。
已经有了一个针对每个进程的官方方法:注册表键+应用程序清单。我怀疑Win32永远不会提供一个API来从用户代码启用长路径支持,因为它将是一个不完整的解决方案,即使它在可执行入口点之前运行,也不会适用于该调用的代码。这包括:

  • Windows加载器无法加载其路径长度超过MAX_PATH的静态导入DLL。
  • 在可执行入口点之前加载的DLLs中的DLLMain代码无法使用长路径。

这就是为什么Windows团队决定通过应用程序清单来实现此功能的原因。
然后Go可以在运行较新的Windows时使用它。在此之前,保持Go程序在当前和较旧的Windows上运行并使用长路径似乎不会有什么害处。
好的观点。我们应该重新审视#17835,它提议向Go二进制文件添加一个默认的硬编码应用程序清单。

o2rvlv0m

o2rvlv0m8#

我们希望Go二进制文件在未修改的Windows系统上能够直接使用长路径。你是说使用应用程序清单可以实现这一点吗?
如果Go二进制文件向应用程序清单添加注解,是否会覆盖注册表键?它是否能在默认系统中正常工作,即注册表键没有被修改,与Windows安装过程中设置的键值相同?
如果可以使用某些经过微软批准的方法,安排Go二进制文件在用户(或系统管理员)无需其他配置的情况下直接支持长路径,那是可以的:我们可以切换到这种方法。但它需要像当前的位翻转(意味着在所有今天起作用的位翻转情况下)一样有效。

相关问题