使 Homebrew 在 root 权限下工作

Homebrew 是一个新型的,Ruby 编写的 macOS 包管理器。但是 Homebrew 的一些设计哲学使得它难以在多用户的情况下共同使用,并且存在诸多安全隐患。比如,Homebrew 会将 /usr/local 下的许多目录的所有者设定为当前执行用户,并禁止用户使用 root 权限安装包。这些设计哲学,使得 Homebrew 难以成为一个系统级的包管理器。但 MacPorts 和 Fink 相对难以令人满意,因此我们需要让 Homebrew 像其它包管理器一样,使用 root 安装包并不破坏原有的系统权限。

Homebrew 代码研读

通过监控进程我们可以发现,判定是否 root 权限的代码并不在 Ruby 中。而在 Shell 脚本里。 在 /usr/local/Homebrew/Library/Homebrew/brew.sh 中,我们发现了相关代码:

check-run-command-as-root() {
  [[ "$(id -u)" = 0 ]] || return

  # Homebrew Services may need `sudo` for system-wide daemons.
  [[ "$HOMEBREW_COMMAND" = "services" ]] && return

  # It's fine to run this as root as it's not changing anything.
  [[ "$HOMEBREW_COMMAND" = "--prefix" ]] && return

  odie <<EOS
Running Homebrew as root is extremely dangerous and no longer supported.
As Homebrew does not drop privileges on installation you would be giving all
build scripts full access to your system.
EOS
}
check-run-command-as-root

我们当然可以直接修改这个文件,但是这样做并不优雅。因此我们选择另一种方式来实现。

思路

我们知道,/usr/local/bin/brew 这个文件事实上是一个拥有执行权限和 Unix shebang 的 Shell 脚本,它起到一个入口的作用,并调用上文中提到的 brew.sh。因此,只要我们的脚本能起到和 brew 相同的作用,那就可以偷梁换柱了哒~ 为了方便,我们可以直接拷贝 brew 的代码加以修改。 我们可以从上面的文件中发现,check-run-command-as-root 函数是通过 id -u 这个命令来判断你是不是 root 用户的。因此在我们的脚本中,我们可以构建一个叫做 id 的函数,并且其永远不输出 0。 当然我们也可以做一些其它的修改,比如自动 sudo 等……这里不多说了。

实现

窝把这个项目叫做 sudobrew,代码已经根据 GPL-3.0 开源在 GitHub 上,qwqVictor/sudobrew

3 Replies to “使 Homebrew 在 root 权限下工作”

  1. 大佬牛逼,思路真棒,试用了一下直接去改sh文件果然解决。
    虽然不优雅,但简单粗暴的解决了问题。

回复 南木白 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注