setuid不适用于非root用户

时间:2014-07-05 21:31:53

标签: c linux

来自unistd.h的{​​{3}}函数成功地将真实用户ID(在具有适当权限和所有权的程序中)从普通用户更改为root用户。但是,当在普通用户拥有的程序中使用相同的功能并且具有相同的权限时,函数调用返回0以获得成功,但实际上不能成功地将真实用户ID从一个普通用户更改为另一个普通用户普通用户。

这种行为背后的原因是什么?什么是最好的(最便携,最安全)解决方案?

我尝试了什么

以下是try.c

#include <unistd.h>   /* for the get/set uid functions */
#include <stdio.h>    /* for printf and perror */

int main() {
  int newuid = geteuid(); /* The goal is to set the real UID to this value. */
  printf("Original UID is %d, EUID is %d\n", getuid(), geteuid());

  if (setuid(newuid)) perror("setuid reported failure");
  printf("UID after setuid is %d\n", getuid());

  return 0;
}

我使用gcc进行了编译,并将权限更改为4711,即-rws--x--x。该计划的所有者是用户名bob,UID 32983

当用户alice,UID 1000运行try计划时,她会看到

Original UID is 1000, EUID is 32893
UID after setuid is 1000

换句话说,setuid函数调用报告成功(返回0),但实际的用户ID实际上并没有改变。

如果我将此可执行文件复制到root拥有的目录(例如/usr/local/bin),请将所有权更改为root并将权限保留为4711,然后在{{{}}时按预期工作运行它:

alice

所以它适用于这种情况!

我试过这个并且在Ubuntu和Debian上得到了相同的行为;内核版本3.2.0-4-amd64,3.5.0-36-generic和3.14-1-amd64;和glibc版本2.13,2.15和2.19。

为什么我要这样做

大多数linux程序只使用有效的UID来确定权限,所以这不重要。但有些人,特别是Original UID is 1000, EUID is 0 UID after setuid is 0 ,将忽略有效的UID并恢复到真正的UID。当然有一些setuid,但great reasons for that似乎是标准的解决方法。 (我正在适当地消毒环境并且有充分的理由去做这件事;即我自己的懒惰。)

无论如何,我很好奇为什么这会对setuid工作bash而不是普通用户。

2 个答案:

答案 0 :(得分:2)

Posix定义了[setuid][1]对特权用户和非特权用户的工作方式:

  

如果进程具有适当的权限,setuid()将设置真实   用户ID,有效用户ID以及保存的呼叫的set-user-ID   过程到uid。

     

如果进程没有适当的权限,但uid是相同的   对于真实用户ID或保存的set-user-ID,setuid()应设置   有效的用户ID到uid; 真实用户ID和保存的set-user-ID必须   保持不变。 (重点补充)

我认为这就是你所经历的。

在理由部分,它提供了一些模糊的解释:

  

非特权进程调用时setuid()setgid()函数的各种行为反映了不同历史实现的行为。

并提出建议:

  

为了便于移植,建议新的非特权应用程序使用seteuid()setegid()函数。

(唯一的区别是seteuid的行为对于非特权用户而言并不那么令人惊讶,因为它会按照其名称声明的方式执行。)

理论部分的其余部分是对多年来改变用户ID的各种策略,一些风险和多种解决方案的长期解释,以及(当然)作为理由Posix选择的路径。

答案 1 :(得分:0)

使用非POSIX函数setreuid有效。在上面的try.c示例中,我将行更改为:

if (setreuid(newuid, geteuid())) perror("setreuid reported failure");

,当alice现在运行时,结果符合预期:

Original UID is 1000, EUID is 32893
UID after setreuid is 32893

请注意,虽然setreuid可能比setuid具有更多的权力,因为它可以同时设置真实有效的UID,在这种情况下,我并不是要求更改有效的UID。 / p>

如果有人能解释为什么setreuid有效且setuid没有,那我肯定会接受另一个答案!