В этом разделе страницы 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:
Это изменение является ответом на комментарий R .. от восьми часов назад, поскольку страница не позволила мне оставить достаточно объемный комментарий:
Я думаю, ты в принципе прав. Но либо система совместима с POSIX, либо нет. Если небиблиотечная функция выполняет системный вызов, что приводит к несовместимой комбинации uid, pid и 'si_code', то второе приведенное мной утверждение проясняет, что сам вызов не соответствует. Можно интерпретировать это двумя способами. Один из способов заключается в следующем: «Если пользователь нарушает это правило, он делает систему несовместимой». Но ты прав, я думаю, что это глупо. Что хорошего в системе, когда любой непривилегированный пользователь может сделать ее несовместимой? Как я понимаю, исправление состоит в том, чтобы система знала, что это не библиотека 'sigqueue ()', выполняющая системный вызов, тогда само ядро должно установить для 'si_code' значение, отличное от 'SI_QUEUE', и оставить UID и PID, как вы установите их. На мой взгляд, вы должны поднять это с ребятами из ядра. Однако у них могут возникнуть трудности; Я не знаю какого-либо безопасного способа для них определить, был ли выполнен системный вызов определенной библиотечной функцией, видя, как функционирует библиотека. почти по определению, это просто удобные обертки вокруг системных вызовов. И это может быть позиция, которую они занимают, что, я знаю, будет разочарованием.
(объем) РЕДАКТИРОВАТЬ на 2011-03-26, 18:00 PST:
Снова из-за ограничений на длину комментария.
Это ответ на комментарий R .. около часа назад.
Я немного новичок в теме системного вызова, поэтому, пожалуйста, потерпите меня.
Под "ядром sysqueue
syscall" вы подразумеваете вызов `__NR_rt_sigqueueinfo '? Это единственное, что я нашел, когда сделал это:
grep -Ri 'NR.*queue' /usr/include
Если это так, я думаю, я не понимаю вашу первоначальную мысль. Ядро позволит (без полномочий root) использовать 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() */
Затем я могу запустить (без полномочий 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$
И посмотрите это (не root) на конце отправки:
wally:~/tmp/20110326$ send 9023
wally:~/tmp/20110326$
Как видите, третье событие имеет поддельные pid и uid. Разве это не то, против чего вы изначально возражали? Там нет EINVAL
или EPERM
в поле зрения. Я думаю, я в замешательстве.