Setuid与GTK+;

Setuid与GTK+;,gtk,setuid,Gtk,Setuid,我正在尝试编写一个程序,并将其与使用Gtk+构建的gui集成。但是,gui调用的exe设置了setuid位。但是,gtk不允许按照gtk社区的指定运行此exe。然而,他们说我们必须编写单独的助手程序和所有。我真的不明白那是什么意思。有谁能解释一下如何克服这个问题吗?我真的需要立即解决问题。第一个问题:为什么您的程序设置为UID?编写setuid程序不是一个应该由自称的Linux新手玩的游戏。他们很危险。它们很有用——别误会我的意思。但它们很危险,很难安全地书写 GTK+项目在“”处非常直截了当地

我正在尝试编写一个程序,并将其与使用Gtk+构建的gui集成。但是,gui调用的exe设置了setuid位。但是,gtk不允许按照gtk社区的指定运行此exe。然而,他们说我们必须编写单独的助手程序和所有。我真的不明白那是什么意思。有谁能解释一下如何克服这个问题吗?我真的需要立即解决问题。

第一个问题:为什么您的程序设置为UID?编写setuid程序不是一个应该由自称的Linux新手玩的游戏。他们很危险。它们很有用——别误会我的意思。但它们很危险,很难安全地书写

GTK+项目在“”处非常直截了当地陈述了他们对setuid程序的看法。他们给出了自己的理由——好的理由。它们指出了如何避免问题:

GTK+团队认为,编写具有图形用户界面的setuid程序的唯一正确方法是使用setuid后端,该后端通过管道等机制与非setuid图形用户界面通信,并认为其接收的输入不可信

既然你应该写一个助手程序,你有没有找过例子?他们很可能是被给予的。您的程序本身是GUI应用程序吗


我需要root权限[…]来打开一些外围设备,读取其内存中的可用数据,然后关闭它们…如果没有root perms,这是无法完成的…而且读取的数据使用GTK同时处理和显示

因此,这正是GTK+团队描述的场景。您需要一个由GUI启动的小型setuid root程序,该程序通过管道或Unix域套接字或类似技术连接到它

当您需要来自外围设备的数据时,主应用程序会将请求写入守护程序/帮助程序,然后等待包含数据的响应

在大纲中,您的GUI中将包含以下代码:

  • LaunchDaemon():这将创建管道(管道或套接字)、fork,子进程将在启动守护进程之前对文件描述符进行排序(关闭不需要的文件描述符)
  • RequestDaemon():这将向守护程序/帮助程序打包一个请求,将信息写入守护程序,并读回响应
  • TerminateDaemon():这将关闭与守护程序/帮助程序的连接;它将知道它没有更多的工作要做,并将退出
同时,您的守护进程/帮助程序将:

  • 进入一个舒适的循环:
    • 从标准输入读取请求
    • 检查它的有效性
    • 执行请求
    • 格式化响应(错误或正常)
    • 将其写回主GUI
    • 重复
  • 当它从输入中获得EOF时,它终止
  • 如果可能的话,它将打开设备一次,然后删除根权限。
    • 这样可以最大限度地减少受到攻击的风险
    • 如果程序不再以root用户身份运行,则不能滥用它来执行只有root用户才能执行的操作
    • 文件打开后,将不再检查权限(因此以root身份运行的守护进程可以打开该文件,如果不重新打开该文件,则放弃其root权限)

您仍应查看外设上的权限是否正确,或者为什么需要从只有root用户才能读取的内容中读取数据。

通常,最好将系统设置为非root用户可以打开设备文件,然后让正常的非根进程与它们对话。

我认为,当GTK+团队警告不要在setuid程序中使用GTK+时,他们的想法是正确的。但我有两个观察结果和一个解决方法

首先,对这种做法提出警告是一回事,让这种做法看起来不可能完全是另一回事。一想到设计师说“用户做XXX没有正当理由”,然后千方百计让XXX变得不可能,我就很恼火。警告风险,让用户承担风险

其次,GTK+团队将“setuid”与“setuid root”混淆。这里有一个例子,说明了区分的重要性。在本例中,我不想使用GTK+扩展程序的权限,而是想减少它们。在某些情况下,我希望能够运行Firefox(好吧,iceweasel,但它基本上是一样的),这样它就可以只查看本地文件,而不需要网络功能。因此,我在Linux系统中设置了iptables,以便特定(人工创建的)用户无法访问外部世界。我希望能够以那个用户的身份运行Firefox,不管我是哪个用户。假设受限用户的uid和gid为1234,下面的一般思路将起作用。将其构建为setuid root。希望这有帮助

编辑2014-02-22 15:13 UTC

我忘了提一下,你可以用0代替1234,这样你就得到了根。有人可能会说这是一个非常糟糕的主意,我想我能理解这一点

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int    ar_argc,
     char **ar_argv
    )
{
  setenv("HOME","/u/wally",1);

  /* Set other environment variables as appropriate. */

  if(setgid(1234))
  {
    fprintf(stderr,"setgid() fail\n");
    exit(1);
  };
  if(setuid(1234))
  {
    fprintf(stderr,"setuid() fail\n");
    exit(1);
  };

  /* Use execl() and friends, or system(), to do what you want here. */

  return 0;
}
#包括
#包括
#包括
#包括
int
主管道(内部管道),
字符**ar_argv
)
{
setenv(“HOME”和“/u/wally”,1);
/*根据需要设置其他环境变量*/
if(setgid(1234))
{
fprintf(stderr,“setgid()失败\n”);
出口(1);
};
if(setuid(1234))
{
fprintf(stderr,“setuid()失败\n”);
出口(1);
};
/*使用execl()和friends,或system(),在此处执行您想要的操作*/
返回0;
}
1)是的……没错,我是个新手……但我知道我的程序在做什么……它在没有suid的情况下无法运行,因为它需要根权限才能运行……2)我在网上寻找示例……有些人说我们必须使用套接字……我仍在寻找一个好的示例……3)是的……需要调用的另一个程序