就是模拟setuid seteuid setreuid setresuid,感觉代码比书上大段的文字好记,就写成代码形式了。
// setuid.cc: 模拟中的设置用户ID的方法的作用#include #include int real = 0; // 实际用户IDint effective = 0; // 有效用户IDint saved = 0; // 保存的设置用户IDvoid showid(); // 打印所有IDinline bool hasPrivilege() { return effective == 0; }#define EINVAL_RETURN { errno = EINVAL; return -1; }#define EPERM_RETURN { errno = EPERM; return -1; }int setuid(int uid) // 修改所有用户ID{ if (uid < 0) EINVAL_RETURN; if (!hasPrivilege() && uid != real && uid != saved) EPERM_RETURN; if (hasPrivilege()) real = effective = saved = uid; else effective = uid; return 0;}int seteuid(int euid) // 修改有效用户ID{ if (euid < 0) EINVAL_RETURN; if (!hasPrivilege() && euid != real && euid != saved) EPERM_RETURN; effective = euid; return 0;}int setreuid(int ruid, int euid) // 修改实际/有效用户ID{ if (ruid < -1 || euid < -1) EINVAL_RETURN; if (!hasPrivilege()) { if (ruid != -1 && ruid != real && ruid != effective) EPERM_RETURN; if (euid != -1 && euid != real && euid != effective && euid != saved) EPERM_RETURN; } real = (ruid != -1) ? ruid : real; effective = (euid != -1) ? euid : effective; if (ruid != -1 || effective != real) saved = effective; return 0;}// 非SUSv3规范, 其他UNIX实现对其也鲜有支持int setresuid(int ruid, int euid, int suid) // 修改实际/有效/保存用户ID{ if (ruid < -1 || euid < -1 || suid < -1) EINVAL_RETURN; if (!hasPrivilege()) { if (ruid != -1 && ruid != real && ruid != effective && ruid != saved) EPERM_RETURN; if (euid != -1 && euid != real && euid != effective && euid != saved) EPERM_RETURN; if (suid != -1 && suid != real && suid != effective && suid != saved) EPERM_RETURN; } real = (ruid != -1) ? ruid : real; effective = (euid != -1) ? euid : effective; saved = (suid != -1) ? suid : saved; return 0;}int main(){ real = 1000; // 下面4句只能执行其中1句// setuid(2000); setreuid(-1, 2000);// seteuid(2000);// setresuid(-1, 2000, 3000); showid(); return 0;}void showid(){ printf("实际用户ID: %4d\n", real); printf("有效用户ID: %4d\n", effective); printf("保存的设置用户ID: %4d\n", saved);}
main函数是TLPI第9章习题第1道的运行结果,然后模拟了一遍功能,后面几道也很简单就能做出来了。以后忘记的话看遍代码就能很快记起来了。