siginfo中的数据值得信赖吗? [英] Is the data in siginfo trustworthy?

查看:107
本文介绍了siginfo中的数据值得信赖吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现在Linux上,通过对rt_sigqueue syscall进行自己的调用,我可以将所需的内容放在si_uidsi_pid字段中,并且调用成功并愉快地传递了错误的值.自然,对信号发送的uid限制为这种欺骗提供了一定的保护,但是我担心依靠此信息可能会很危险.关于我可以阅读的主题,是否有任何好的文档?为什么Linux允许让调用者指定siginfo参数而不是在内核空间中生成它们,这显然是不正确的行为?这似乎是荒谬的,尤其是因为额外的系统 为了获得用户空间中的uid/gid,可能需要进行调用(并因此而降低性能成本).

I've found that on Linux, by making my own call to the rt_sigqueue syscall, I can put whatever I like in the si_uid and si_pid fields and the call succeeds and happily delivers the incorrect values. Naturally the uid restrictions on sending signals provide some protection against this kind of spoofing, but I'm worried it may be dangerous to rely on this information. Is there any good documentation on the topic I could read? Why does Linux allow the obviously-incorrect behavior of letting the caller specify the siginfo parameters rather than generating them in kernelspace? It seems nonsensical, especially since extra sys calls (and thus performance cost) may be required in order to get the uid/gid in userspace.

编辑:基于我对 POSIX (我加强调):

Based on my reading of POSIX (emphasis added by me):

如果si_code是SI_USER或SI_QUEUE,[XSI]或小于或等于0的任何值,则信号是由进程生成的,并且si_pid和si_uid 必须设置为进程ID和真实用户ID发件人的身份.

我相信Linux的这种行为是不符合要求的,并且是一个严重的错误.

I believe this behavior by Linux is non-conformant and a serious bug.

推荐答案

您引用的POSIX页面的这一部分还列出了si-code的含义,这就是含义:

That section of the POSIX page you quote also lists what si-code means, and here's the meaning:

SI_QUEUE
    The signal was sent by the sigqueue() function.

该部分继续说:

如果信号不是由一个人产生的 列出的功能或事件 上面的si_code应设置为 到特定于信号的值之一 在XBD中描述,或 实现定义的值是 不等于定义的任何值 以上.

If the signal was not generated by one of the functions or events listed above, si_code shall be set either to one of the signal-specific values described in XBD , or to an implementation-defined value that is not equal to any of the values defined above.

如果仅sigqueue()函数使用SI_QUEUE,则不会违反任何条件.您的方案涉及使用SI_QUEUEsigqueue()函数以外的代码.问题是POSIX是否构想一个操作系统,以强制只允许使用指定的库函数(而不是不是POSIX定义的库函数的某些函数)进行具有某些特征的系统调用.我相信答案是否".

Nothing is violated if only the sigqueue() function uses SI_QUEUE. Your scenario involves code other than the sigqueue() function using SI_QUEUE The question is whether POSIX envisions an operating system enforcing that only a specified library function (as opposed to some function which is not a POSIX-defined library function) be permitted to make a system call with certain characteristics. I believe the answer is "no".

截至2011年3月26日14:00 PST:

此修改是针对八个小时前 R.的评论,因为该页面无法让我留下足够多的评论:

This edit is in response to R..'s comment from eight hours ago, since the page wouldn't let me leave an adequately voluminous comment:

我认为您基本上是正确的.但是,要么系统兼容POSIX,要么不兼容.如果非库函数执行syscall导致uid,pid和'si_code'的不兼容组合,那么我引用的第二条语句清楚地表明该调用本身不兼容.一个人可以用两种方式解释这一点.一种方法是:如果用户违反此规则,则他会使系统不符合要求."但是你是对的,我认为这很愚蠢.当任何非特权用户都可以使其不合规时,该系统有什么好处?如我所见,此修复程序是通过某种方式让系统知道不是进行系统调用的库"sigqueue()",然后内核本身应将"si_code"设置为"SI_QUEUE"以外的其他值,并保留uid和pid的设置方式.我认为,您应该向核心人员提出这一建议.但是,他们可能有困难.我不知道有什么安全的方法可以让他们检测某个特定库函数是否进行了系统调用,就像该库如何工作一样.几乎按照定义,它们只是围绕syscall的便利包装.那可能就是他们所担任的职务,我知道这将令人失望.

I think you're basically right. But either a system is POSIX compliant or it is not. If a non-library function does a syscall which results in a non-compliant combination of uid, pid, and 'si_code', then the second statement I quoted makes it clear that the call itself is not compliant. One can interpret this in two ways. One ways is: "If a user breaks this rule, then he makes the system non-compliant." But you're right, I think that's silly. What good is a system when any nonprivileged user can make it noncompliant? The fix, as I see it, is somehow to have the system know that it's not the library 'sigqueue()' making the system call, then the kernel itself should set 'si_code' to something other than 'SI_QUEUE', and leave the uid and pid as you set them. In my opinion, you should raise this with the kernel folks. They may have difficulty, however; I don't know of any secure way for them to detect whether a syscall is made by a particular library function, seeing as how the library functions. almost by definition, are merely convenience wrappers around the syscalls. And that may be the position they take, which I know will be a disappointment.

(大量)截至2011年3月26日18:00 PST:

再次由于评论长度的限制.

Again because of limitations on comment length.

这是对 R.大约一个小时前的评论的回应.

This is in response to R..'s comment of about an hour ago.

我对syscall主题还是有点陌生​​,所以请多包涵.

I'm a little new to the syscall subject, so please bear with me.

通过内核sysqueue syscall",您是说`__NR_rt_sigqueueinfo'调用吗?那是我这样做的唯一发现:

By "the kernel sysqueue syscall", do you mean the `__NR_rt_sigqueueinfo' call? That's the only one that I found when I did this:

grep -Ri 'NR.*queue' /usr/include

如果是这样,我想我不明白您的初衷.内核将允许(非超级用户)我将SI-QUEUE与伪造的pid和uid一起使用,而不会出现错误.如果我的发送方是这​​样编码的:

If that's the case, I think I'm not understanding your original point. The kernel will let (non-root) me use SI-QUEUE with a faked pid and uid without error. If I have the sending side coded thus:

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

int main(int    argc,
         char **argv
        )
{
  long john_silver;

  siginfo_t my_siginfo;

  if(argc!=2)
  {
    fprintf(stderr,"missing pid argument\n");

    exit(1);
  }

  john_silver=strtol(argv[1],NULL,0);

  if(kill(john_silver,SIGUSR1))
  {
    fprintf(stderr,"kill() fail\n");

    exit(1);
  }

  sleep(1);

  my_siginfo.si_signo=SIGUSR1;
  my_siginfo.si_code=SI_QUEUE;
  my_siginfo.si_pid=getpid();
  my_siginfo.si_uid=getuid();
  my_siginfo.si_value.sival_int=41;

  if(syscall(__NR_rt_sigqueueinfo,john_silver,SIGUSR1,&my_siginfo))
  {
    perror("syscall()");

    exit(1);
  }

  sleep(1);

  my_siginfo.si_signo=SIGUSR2;
  my_siginfo.si_code=SI_QUEUE;
  my_siginfo.si_pid=getpid()+1;
  my_siginfo.si_uid=getuid()+1;
  my_siginfo.si_value.sival_int=42;

  if(syscall(__NR_rt_sigqueueinfo,john_silver,SIGUSR2,&my_siginfo))
  {
    perror("syscall()");

    exit(1);
  }

  return 0;

} /* main() */

,接收方这样编码:

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

int signaled_flag=0;

siginfo_t received_information;

void
my_handler(int        signal_number,
           siginfo_t *signal_information,
           void      *we_ignore_this
          )
{
  memmove(&received_information,
          signal_information,
          sizeof(received_information)
         );

  signaled_flag=1;

} /* my_handler() */

/*--------------------------------------------------------------------------*/

int
main(void)
{
  pid_t            myself;

  struct sigaction the_action;

  myself=getpid();

  printf("signal receiver is process %d\n",myself);

  the_action.sa_sigaction=my_handler;
  sigemptyset(&the_action.sa_mask);
  the_action.sa_flags=SA_SIGINFO;

  if(sigaction(SIGUSR1,&the_action,NULL))
  {
    fprintf(stderr,"sigaction(SIGUSR1) fail\n");

    exit(1);
  }

  if(sigaction(SIGUSR2,&the_action,NULL))
  {
    fprintf(stderr,"sigaction(SIGUSR2) fail\n");

    exit(1);
  }

  for(;;)
  {
    while(!signaled_flag)
    {
      sleep(1);
    }

    printf("si_signo: %d\n",received_information.si_signo);
    printf("si_pid  : %d\n",received_information.si_pid  );
    printf("si_uid  : %d\n",received_information.si_uid  );

    if(received_information.si_signo==SIGUSR2)
    {
      break;
    }

    signaled_flag=0;
  }

  return 0;

} /* main() */

然后我可以这样运行(非root用户)接收方:

I can then run (non-root) the receiving side thus:

wally:~/tmp/20110326$ receive
signal receiver is process 9023
si_signo: 10
si_pid  : 9055
si_uid  : 4000
si_signo: 10
si_pid  : 9055
si_uid  : 4000
si_signo: 12
si_pid  : 9056
si_uid  : 4001
wally:~/tmp/20110326$ 

在发送端查看此消息(非root用户):

And see this (non-root) on the send end:

wally:~/tmp/20110326$ send 9023
wally:~/tmp/20110326$ 

如您所见,第三个事件欺骗了pid和uid.那不是你最初反对的吗?看不到EINVALEPERM.我想我很困惑.

As you can see, the third event has spoofed pid and uid. Isn't that what you originally objected to? There's no EINVAL or EPERM in sight. I guess I'm confused.

这篇关于siginfo中的数据值得信赖吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆