茶网站建设需要多少钱,怎么打广告吸引客户,泉州有哪些做网站的,主题资源网站建设作业在讨论这个setuid函数之前#xff0c;我们首先要了解的一个东西就是内核为每个进程维护的三个UID值。这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user-ID)。首先说这个实际用户ID#xff0c;就是我们当前以哪个用户登录了…在讨论这个setuid函数之前我们首先要了解的一个东西就是内核为每个进程维护的三个UID值。这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user-ID)。首先说这个实际用户ID就是我们当前以哪个用户登录了我们运行的程序的实际用户ID就是这个用户的ID。有效用户ID就是当前进程是以哪个用户ID来运行的一般情况下是实际用户ID如果可执行文件具有了SUID权限那么它的有效用户ID就是可执行文件的拥有者。保存的设置用户ID就是有效用户ID的一个副本与SUID权限有关。关于那个SUID最经典的例子莫过于passwd命令。passwd这个可执行文件的所有者是root但是其他用户对于它也有执行权限并且它自身具有SUID权限。那么当其他用户来执行passwd这个可执行文件的时候产生的进程的就是以root用户的ID来运行的。如下图所示这个passwd的所有者是root并且在权限那一栏中s代表的是SUID权限。我以普通用户michael来运行这个命令产生的进程如下大家可以看到倒数第二行这个进程其命令是passwd但是其USER却是root。这就是SUID权限。接下来我们开始扯正题setuid函数。这是setuid函数的声明和返回值如果成功返回0如果失败返回-1并将errno设置为合适的值。关于这个函数的功能APUE(《UNIX环境高级编程》下面的APUE为相同的意思不再赘述)上面是这样写的这样光讲概念可能有点干巴巴了下面我来举几个分别说明一下开始讲之前我先验证一下我的电脑是支持保存的设置用户ID这个功能的在电脑上运行以下代码1 #include2 #include3 #include4 #include5 #include6 #include7 #define BUFSIZE 5128 void err_exit(char *fmt,...);9 int main(int argc,char *argv[])10 {11 if(sysconf(_SC_SAVED_IDS) 0)12 printf(_POSIX_SAVED_IDS effective!\n);1314 return 0;15 }程序的运行结果如下首先说一下我用到的用户一共使用了三个用户root(UID0)michael(UID500)xiaojie(UID501)如下图所示先讲第一点如果进程具有超级用户特权那么这三个UID都被设置成了uid(setuid函数的参数)的值。比如下面这段代码1 #include2 #include3 #include4 int main(int argc,char *argv[])5 {6 uid_t ruid,euid,suid;7 //这三个uid分别是实际用户ID有效用户ID保存的设置用户ID89 setuid(500);10 getresuid(ruid,euid,suid);11 printf(real:%d\teffective:%d\tset-user-id:%d\n,ruid,euid,suid);1213 return 0;14 }我用root用户来运行这个程序那么刚开始这个进程的有效用户ID为0然后这个进程中调用setuid(500),这三个UID的值都会被设置成500(在程序中通过getresuid函数来获取进程的三个UID的值)运行结果如下图接下来我们再来讨论第二种情况如果函数的参数uid等于进程的实际用户ID或者保存的设置用户ID那么就将有效用户ID设置为uid其他的两个(实际用户ID和保存的设置用户ID)保持不变。比如下面这个程序1 #include2 #include3 #include4 void err_exit(char *fmt,...);5 int main(int argc,char *argv[])6 {7 uid_t ruid,euid,suid;89 printf(Before:\n);10 if(-1 getresuid(ruid,euid,suid))11 err_exit([getresuid]:);12 printf(real:%d\teffective:%d\tset-user:%d\n,ruid,euid,suid);13 setuid(500);14 printf(After:\n);15 if(-1 getresuid(ruid,euid,suid))16 err_exit([getresuid]:);17 printf(real:%d\teffective:%d\tset-user:%d\n,ruid,euid,suid);1819 return 0;20 }关于这段代码生成的可执行文件我让它的拥有者变成了xiaojie(UID501)并且给它加上了SUID权限如下图所示然后我用michael用户(UID500)来运行这个程序那么这个程序的实际用户ID500而有效用户ID和保存的设置用户ID都为501。接着在这个程序中调用setuid函数传入的参数为500大家可以猜想到最终应该只有有效用户ID受到影响而保存的设置用户ID保持不变。运行结果如下图所示这就符合了我们的预期仅仅只有有效用户ID受到了影响而实际用户ID和保存的设置用户ID并没有改变。(这里我仅仅是验证了保存的设置用户ID不受影响大家也可以自己写一个程序来验证实际用户ID并不受影响。)最后一点如果setuid函数的参数的uid的值即不等于实际用户ID也不等于保存的设置用户ID而且这个进程的有效用户ID也不是0(非特权进程)。那么这个程序就会出错并将errno设置为EPERM。比如下面这个程序1 #include2 #include3 #include4 #include5 #include6 int main(int argc,char *argv[])7 {8 uid_t ruid,euid,suid;910 getresuid(ruid,euid,suid);11 printf(real:%d\teffective:%d\tset-user:%d\n,ruid,euid,suid);1213 if(-1 setuid(500))14 {15 printf(%s\n,strerror(errno));16 if(errno EPERM)17 {18 printf(Error number is EPERM!\n);19 }20 }21 else22 {23 getresuid(ruid,euid,suid);24 printf(real:%d\teffective:%d\tset-user:%d\n,ruid,euid,suid);25 }2627 return 0;28 }我以xiaojie用户(UID501)来运行这个程序那么这个程序的三个用户ID都为501然后在这个程序中调用setuid(500)。于是程序就会报错并将errno设置为EPERM如下图所示OK这就是APUE上关于setuid函数的解释讲了这么多综合成一句话就是root是神想怎么干就怎么干没人管得了。而普通用户呢只能管自己分内的事(把进程的有效ID改成自己的ID)不能胡乱来。OKthat‘s all。希望这篇文章对大家能够有帮助。