gpt4 book ai didi

c - siginfo 中的数据可信吗?

转载 作者:IT王子 更新时间:2023-10-29 00:14:20 26 4
gpt4 key购买 nike

我发现在 Linux 上,通过自己调用 rt_sigqueue 系统调用,我可以将我喜欢的任何内容放入 si_uidsi_pid 字段,调用成功并愉快地传递了不正确的值。自然地,发送信号的 uid 限制提供了一些防止这种欺骗的保护,但我担心依赖这些信息可能是危险的。关于我可以阅读的主题有什么好的文档吗?为什么 Linux 允许调用者指定 siginfo 参数而不是在内核空间中生成它们这一明显不正确的行为?这看起来很荒谬,尤其是因为额外的系统为了在用户空间中获取 uid/gid,可能需要调用(因此需要性能成本)。

编辑:根据我对 POSIX 的阅读(重点是我加的):

If si_code is SI_USER or SI_QUEUE, [XSI] or any value less than or equal to 0, then the signal was generated by a process and si_pid and si_uid shall be set to the process ID and the real user ID of the sender, respectively.

我认为 Linux 的这种行为是不合规的,是一个严重的错误。

最佳答案

您引用的 POSIX 页面的那部分还列出了 si-code 的含义,其含义如下:

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

该部分接着说:

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 定义的库函数)被允许进行具有某些特征的系统调用。我相信答案是否定的。

截至太平洋标准时间 2011 年 3 月 26 日 14:00 的编辑:

此编辑是为了回应八小时前 R.. 的评论,因为该页面不允许我留下足够多的评论:

我认为你基本上是对的。但是系统要么符合 POSIX,要么不符合。如果非库函数执行的系统调用导致 uid、pid 和“si_code”的不合规组合,那么我引用的第二条语句清楚地表明调用本身不合规。人们可以用两种方式来解释这一点。一种方式是:“如果用户违反了这条规则,那么他就会使系统不合规。”但你是对的,我认为那很愚蠢。当任何非特权用户都可以使其不合规时,系统有什么好处?正如我所看到的,修复是以某种方式让系统知道它不是库'sigqueue()'进行系统调用,然后内核本身应该将'si_code'设置为'SI_QUEUE'以外的东西,并离开您设置的 uid 和 pid。在我看来,你应该向内核人员提出这个问题。然而,他们可能有困难;我不知道他们有什么安全的方法来检测系统调用是否由特定的库函数进行,看看库是如何运行的。几乎根据定义,它们只是系统调用的便利包装器。这可能就是他们采取的立场,我知道这会令人失望。

(大量)截至太平洋标准时间 2011 年 3 月 26 日 18:00 的编辑:

同样是因为评论长度的限制。

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

我对系统调用主题有点陌生,所以请多多包涵。

“内核 sysqueue 系统调用”是指 `__NR_rt_sigqueueinfo' 调用吗?这是我在执行此操作时发现的唯一一个:

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

如果是这样,我想我没有理解您原来的观点。内核将允许(非 root)我使用带有伪造的 pid 和 uid 的 SI-QUEUE 而不会出错。如果我这样编码发送方:

#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)接收方:

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$

在发送端看到这个(非根):

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

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

关于c - siginfo 中的数据可信吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5267005/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com