引用するPOSIXページのそのセクションには、意味もリストされていますsi-code
。その意味は次のとおりです。
SI_QUEUE
The signal was sent by the sigqueue() function.
そのセクションはさらに次のように述べています。
信号が上記の機能またはイベントのいずれかによって生成されなかった場合はsi_code
、XBDで説明されている信号固有の値のいずれかに設定するか、上記で定義された値のいずれにも等しくない実装定義の値に設定する必要があります。 。
sigqueue()
関数のみがを使用する場合、違反はありませんSI_QUEUE
。シナリオには、sigqueue()
を使用する関数以外のコードが含まれますSI_QUEUE
。問題は、POSIXが、特定のライブラリ関数(POSIXで定義されたライブラリ関数ではない関数ではなく)のみが特定のシステムコールを実行できるようにするオペレーティングシステムを想定しているかどうかです。特性。答えは「ノー」だと思います。
2011-03-26、14:00 PST現在の編集:
この編集は、 8時間前のR ..のコメントに対応しています。このページでは、十分な量のコメントを残すことができなかったためです。
基本的に正しいと思います。ただし、システムがPOSIXに準拠しているか、準拠していないかのどちらかです。非ライブラリ関数がsyscallを実行し、その結果uid、pid、および'si_code'の組み合わせが非準拠になる場合、引用した2番目のステートメントは、呼び出し自体が準拠していないことを明確にします。これは2つの方法で解釈できます。1つの方法は、「ユーザーがこのルールに違反した場合、システムを非準拠にする」というものです。しかし、あなたは正しいです、私はそれがばかげていると思います。非特権ユーザーがシステムを非準拠にすることができる場合、システムはどのように役立ちますか?私が見ているように、修正は、システムコールを行うライブラリ「sigqueue()」ではないことをシステムに認識させることです。カーネル自体は、「si_code」を「SI_QUEUE」以外に設定し、 uidとpidを設定します。私の意見では、あなたはカーネルの人々とこれを上げる必要があります。ただし、問題が発生する可能性があります。ライブラリがどのように機能するかを見て、特定のライブラリ関数によってシステムコールが行われたかどうかを検出するための安全な方法を私は知りません。ほとんど定義上、システムコールの単なる便利なラッパーです。そしてそれは彼らがとる立場かもしれません、それは私が失望することを知っています。
(膨大な)2011年3月26日、18:00 PST現在の編集:
コメントの長さに制限があるためです。
これは、約1時間前のR..のコメントへの応答です。
私はsyscallの件名に少し慣れていないので、ご容赦ください。
「カーネルsysqueue
システムコール」とは、「__ NR_rt_sigqueueinfo」呼び出しを意味しますか?これを行ったときに見つけたのはこれだけです。
grep -Ri 'NR.*queue' /usr/include
そうだとすれば、私はあなたの本来のポイントを理解していないと思います。カーネルは、(ルート以外の)SI-QUEUE
偽のpidとuidをエラーなしで使用できるようにします。送信側をこのようにコーディングした場合:
#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() */
次に、受信側を(ルートではなく)実行できます。
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$
ご覧のとおり、3番目のイベントはpidとuidを偽装しています。それはあなたが最初に反対したことではありませんか?ないEINVAL
かEPERM
、見えない。私は混乱していると思います。