让程序在 OS X 中始终以 root 身份运行

让程序在 OS X 中始终以 root 身份运行

我正在尝试让一个 C 程序始终以 root 身份运行,无论谁调用它。基本上,我希望它调用“mkdir /test”作为示例。因此我创建了如下 C 程序:

#include <stdio.h>

int main()
{
system("mkdir /test");
printf("bye...\n");
return 0;
}

现在,我刚刚编译了它:gcc test.c -o test

现在我尝试设置权限:

chmod +s test

但是以普通用户身份运行它时,我收到权限被拒绝的错误。因此,它执行该文件但不具有 root 权限。我还尝试将权限设置为:

chmod a+s test
chmod o+s test

但我总是遇到同样的问题。

有人能帮我吗?顺便说一下,文件 test.c 是由 root 创建的,并且也是以 root 身份编译的。

bash-3.2# ls -al | grep test 
-rwxr-xr-x   1 root   staff       8796  5 Ago 19:07 test
bash-3.2# chmod +s test
bash-3.2# ls -al | grep test 
-rwsr-sr-x   1 root   staff       8796  5 Ago 19:07 test
bash-3.2# whoami
root
bash-3.2#

提前致谢!干杯!

答案1

这里有两件事需要了解:

  • 粘着位,它可以用于文件和目录,但不会执行您想要的操作。从sticky(8)粘滞位对可执行文件没有影响

  • setuid标志,允许程序以其所有者权限运行。OS X 中似乎有一个限制,但显然没有记录,即可执行文件上的 setuid 位只有在可执行文件位于 root 拥有的目录中(并且不向其他人开放写入)时才有效,直到 root 目录。否则,出于安全原因,它将被忽略。

无论如何,你可以修改 sudoers 文件,这样它就不需要密码来执行某个命令了。记住,你用来visudo编辑它。如果你在编辑文件时语法错误,你将无法再运行sudo

sudo visudo

然后按I,并在底部插入:

username    ALL= NOPASSWD: /path/to/command

在这里,您显然需要将username运行命令而无需输入密码的用户更改为。此外,更改可执行文件的路径。请注意,此时,可执行文件也可以由 拥有,root并且仅对 具有执行权限root

Esc,然后 写入:wq,然后Enter

现在,用户username可以运行该命令,sudo /path/to/command而不需要输入密码。

答案2

我在 Linux 下工作,但由于 OSX 只是 BSD,我认为它遵循与任何其他 Unix 相同的(一般)规则。

在您的程序中,您需要调用 setuid (UID),成功时返回 0,以使其以该 UID 运行,并且您希望以 root 身份运行。Root 的 UID 是大概0,但如果您特别偏执,请使用 getpwnam (const char *szUserName) 来获取 UID。

因此,是这样的:

#include <stdio.h> // needed for printf

#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>

void change_to_user (const char *szUserName)
{
  struct passwd *pw;

  pw = getpwnam(szUserName);
  if (pw != NULL)
  {
    uid_t uid = pw->pw_uid; // we now have the UID of the username
    
    printf ("UID of user %s is %d\n", szUserName, (int)uid);
    if (setuid (uid) != 0)
    {
      perror ("setuid");
    }
    else
    {
      // this will fail if you try to change to root without the SUID
      // bit set.  This executive needs to be owned by root (probably
      // group owned by root as well), and set the SUID bit with:
      //   suid a+s {executable}
      printf ("UID is now %d\n", (int)uid);
    }
  }
  else
  {
    perror ("getpwnam");
  }
}


int main (int argc, char **argv)
{
  int iIter;
  
  if (argc == 1)
  {
    printf ("Give me a user name\n");
    return 1;
  }

  for (iIter = 1 ; iIter < argc ; iIter++)
  {
    change_to_user (argv[iIter]);
  }
  return 0;
}

您可以将 UID 设置为任何用户名,因此也许您正在运行 cgi 脚本,并且想要在自己的帐户上以用户名运行,而不是“www-data”或其他任何名称 - 您可以在那里使用它。我就是这样做的,这就是我可以详细回答您的问题的原因。

相关内容