首先申明,sudo命令虽然很常用,不过以前使用的时候从来都不带任何参数,后面直接跟着想要得到root权限的命令。知道最近研究了下sudo源码后才知道sudo居然也有这么多参数。当时看源码时也被它处理各种参数以及各种情况的代码所困扰,本文尽量避开这些枯燥的代码,清晰明白地分析sudo是如何提升程序的权限的。
首先看一下main函数主要做了些什么事:
int
main(int argc, char *argv[], char *envp[])
{
/* Reset signal mask and save signal state. */
(void) sigemptyset(&mask);
(void) sigprocmask(SIG_SETMASK, &mask, NULL);
save_signals();
// do something check and prepare
init_signals();
/* Become full root (not just setuid) so user cannot kill us. */
setuid(ROOT_UID);
exitcode = run_command(&command_details);
exit(exitcode);
}
经过我的删减,sudo的main函数已经变得十分简单,然而事实并非如此,在save_signals和init_signals之间还做了很多事,包括插件的加载和policy的开启等等。run_command也只是其中一个分支,但是我们大部分情况都是进入这个分支运行,因此下面我们直接看run_command的实现:
int
run_command(struct command_details *details)
{
struct command_status cstat;
int exitcode = 1;
debug_decl(run_command, SUDO_DEBUG_EXEC)
cstat.type = CMD_INVALID;
cstat.val = 0;
sudo_execute(details, &cstat);
switch (cstat.type) {
case CMD_ERRNO:
/* exec_setup() or execve() returned an error. */
exitcode = 1;
break;
case CMD_WSTATUS:
/* Command ran, exited or was killed. */
if (WIFEXITED(cstat.val))
exitcode = WEXITSTATUS(cstat.val);
else if (WIFSIGNALED(cstat.val))
exitcode = WTERMSIG(cstat.val) | 128;
break;
default:
sudo_wa