如何使非根父进程在MacOS / X下生成根子进程?

问题描述 投票:1回答:1

我有一个常规的旧MacOS / X GUI进程,由用户双击图标启动,因此正在以该用户的特权运行。

我想做的是让这个GUI进程产生一个子进程,并通过其stdin / stdout与该子进程进行通信。这都是可行的并且可行。

诀窍是我希望子进程以root身份运行,因为子进程将需要做一些需要root访问的事情。

我希望这将需要打开一个对话框,要求用户输入管理员密码,这种情况是可以的。

一种方法是让父进程运行这样的shell命令:

/usr/bin/osascript -e 'do shell script "/bin/bash ./my_script.sh" with administrator privileges'

...,让my_script.sh运行代表子进程的程序,我认为这可以工作,但是有一种更优雅的方法来实现此目的(即,不需要将shell脚本写到磁盘上的某个位置) ,并且生成了一个比密码更神秘的用户,而不是一个神秘的说“ osascript想要更改”的密码请求?)]

c++ macos root privilege-elevation
1个回答
0
投票

通过研究n.m.提到的source code to cocoasudo,我终于能够使它工作。

棘手的部分是意识到AuthorizationExecuteWithPrivileges为子进程提供了0 / root的euid(“有效用户ID”),因此它可以do需要root访问权限的东西,但不会改变子进程的uid(“真实用户ID”);仍设置为父进程的用户ID,因此系统其余部分不会将它视为根进程。该细节导致以这种方式启动时,我的shell脚本中的许多内容无法正常工作;一方面,当使用/bin/bash执行脚本时,即使whoami指示它是作为root用户执行的,要求root访问权限的操作(例如将文件复制到只能写根的目录中)仍然会失败。奇怪的是,/bin/sh似乎没有受到该问题的困扰。

[另一个主要障碍是,我的脚本需要调用launchctl load -w com.mycompany.myproduct.plist来启动系统LaunchDaemon,但是launchctl的决定基于是否将服务安装为特定于用户的还是基于真实用户的系统范围的服务ID,因此我的服务将始终作为特定于用户的服务(没有root访问权限运行,并且仅在当前用户登录时启动)安装,而不是作为root用户运行的系统范围服务。

[经过大量的猜测和四处搜寻之后,我被带到Apple Tech Note TN2083底部的“提示和技巧”部分,其中指出:

重要:为使此正常工作,您必须以root用户身份运行launchctl(其EUID和RUID都必须为0)。这样可以确保launchctl与launchd的主要实例进行通信。

...并且由于没有(AFAIK)没有系统提供的命令行工具来为我调用setuid(0),因此我不得不在C中编写自己的小脚本启动工具:

int main(int argc, char ** argv) { if (argc >= 2) { if (setuid(0) == 0) // make us really root, not just "effectively root" { system(argv[1]); // then run the specified script file return 0; } else perror("setuid"); } else printf("Usage: setuid_script_launcher <path_to_script>\n"); return 10; }

这比我认为应该弄清楚的工作要多得多,但是现在都在工作。我在这里描述它是为了减轻下一个人的痛苦。
© www.soinside.com 2019 - 2024. All rights reserved.