由于Internet已经成为了现代计算的中心,因此安全就成了一个备受关注的问题。安全从一开始就应该是设计的一部分,而且必须利用手头可用的所有工具。在Linux里,你能使用的一个工具可以让你强制程序只使用运行所需要的最小权限。
一般来说,一个进程要在具有发起这个进程的用户具有安全信任书的情况下才能运行。例如,一个由根用户发起的进程拥有超级用户帐号的所有权限。这显然是个很大的安全风险,因为有人能够远程地或者在本地利用你程序里的安全漏洞,然后获得超级用户的权限来访问系统。
不幸的是,很多程序都需要具有超级用户的权限才能够完成其任务的一部分。在这样的情况下,你会希望在程序具有超级用户权限的时候将安全缺口的机会降到最低。这样做的一个常见方法是使用setuid系统调用。
Setuid允许你将进程的安全信任书降级。例如,你可以用根用户的权限来启动你的程序,这样的话它就能够进行需要根用户访问权限才能够进行的初始化过程,然后使用setuid把你程序的安全信任书降为最小的访问权限,从而以更加安全的方式完成其任务。
你可以用所希望的用户ID来调用函数setuid,如果成功,这个函数就会返回0,如果出现错误,就会返回-1。你可以检查errno来了解具体的错误。下面就是使用setuid的一个例子。
intmakesafeuser(){
structpasswd *user;
intrcode = 0;
user = NULL;
user = getpwnam("nobody");
assert(user);
if (!user){
return -1;
}
rcode = setuid(user->pw_uid);
return rcode;
}
在大多数Linux系统上,nobody这个用户是被指定给低权限用户,供其使用守护程序的。这个用户事实上可以是除了根用户之外的任何用户。Passwd结构是用来描述用户的结构。而getpwnam函数是一个允许我们通过名字查询用户的系统调用。有一些类似的函数能够允许你通过诸如用户ID这样的其他方法来查询用户信息。
在设计你的应用程序的时候,安全应该是一个主要的目标,即使你需要牺牲某些特性。在安全上节省开支或者精力可能会有短期的回报,但是它会在更长的未来给你带来恶果,因为这样做之后,有效地实现安全几乎是不可能的。Setuid只是你火药库里用来实现你复杂安全规划的一个可用工具。
文本作者Mike Owens是一名Allscripts Healthcare解决方案的软件工程师,他从事软件行业已逾八年。