2011-03-10 16 views
8

मैंने पाया लिनक्स पर, rt_sigqueue syscall को अपना स्वयं का कॉल करके, मैं रख सकते हैं कि जो कुछ भी मैं si_uid और si_pid क्षेत्रों में पसंद है और कॉल सफल होता है और खुशी से गलत मान देता है। स्वाभाविक रूप से सिग्नल भेजने पर यूआईडी प्रतिबंध इस तरह के स्पूफिंग के खिलाफ कुछ सुरक्षा प्रदान करते हैं, लेकिन मुझे चिंता है कि इस जानकारी पर भरोसा करना खतरनाक हो सकता है। क्या मैं पढ़ सकता हूं विषय पर कोई अच्छा दस्तावेज है? लिनक्स कॉलर को कर्नेलस्पेस में उत्पन्न करने के बजाय siginfo पैरामीटर निर्दिष्ट करने के स्पष्ट रूप से गलत व्यवहार की अनुमति क्यों देता है? यह गैरकानूनी लगता है, खासकर जब अतिरिक्त sys कॉल (और इस प्रकार प्रदर्शन लागत) की आवश्यकता हो सकती है ताकि उपयोगकर्ता स्थान में यूआईडी/ग्रिड प्राप्त हो सके।क्या siginfo भरोसेमंद डेटा है?

संपादित करें:POSIX की मेरी पढ़ने (जोर मेरे द्वारा जोड़ा) के आधार पर:

तो si_code SI_USER या SI_QUEUE, [XSI] या किसी मान 0 के बराबर या उससे कम है, तो संकेत है एक प्रक्रिया द्वारा उत्पन्न किया गया था और si_pid और si_uid क्रमशः प्रेषक की प्रक्रिया आईडी और वास्तविक उपयोगकर्ता आईडी पर सेट किया जाएगा।

मेरा मानना ​​है कि लिनक्स द्वारा यह व्यवहार गैर-अनुरूप और गंभीर बग है।

+0

ऐसा लगता है कि आप एसओ स्टंप हो गए हैं। हो सकता है कि आपको लिनक्स कर्नेल मेलिंग सूची का प्रयास करना चाहिए: http://www.kernel.org/pub/linux/docs/lkml/ –

उत्तर

5

POSIX पेज आप भी बोली की धारा को सूचीबद्ध करता है क्या si-code मतलब यह है कि, और यहाँ अर्थ है:

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

अनुभाग आगे कहते हैं कि:

संकेत द्वारा उत्पन्न नहीं किया गया था कार्य या घटनाओं में से एक सूचीबद्ध ऊपर, si_code संकेत-विशिष्ट मान XBD में वर्णित से एक के लिए या तो स्थापित किया जाएगा, या एककोकार्यान्वयन-परिभाषित मान ऊपर परिभाषित मानों के बराबर नहीं है। केवल sigqueue() समारोह SI_QUEUE का उपयोग करता है, तो

कुछ भी नहीं का उल्लंघन किया है। का उपयोग करते हुए आपके परिदृश्य में sigqueue() फ़ंक्शन के अलावा कोड शामिल है प्रश्न यह है कि क्या POSIX एक ऑपरेटिंग सिस्टम को लागू करता है जो केवल एक निर्दिष्ट लाइब्रेरी फ़ंक्शन को लागू करता है (जैसा कि कुछ फ़ंक्शन के विपरीत है जो POSIX- परिभाषित लाइब्रेरी फ़ंक्शन नहीं है) को सिस्टम कॉल करने की अनुमति दी जाती है कुछ विशेषताओं के साथ। मेरा मानना ​​है कि जवाब "नहीं" है।

2011-03-26 के रूप में संपादित करें, 14:00 पीएसटी:

यह संपादन, आर .. के आठ घंटे पहले से टिप्पणी के जवाब में है के बाद से पेज नहीं जाने देंगे मैं एक पर्याप्त रूप से विशाल टिप्पणी छोड़ देता हूं:

मुझे लगता है कि आप मूल रूप से सही हैं। लेकिन या तो एक प्रणाली POSIX अनुपालन है या यह नहीं है। यदि गैर-लाइब्रेरी फ़ंक्शन एक सिस्कल करता है जिसके परिणामस्वरूप यूआईडी, पिड और 'si_code' के गैर-अनुपालन संयोजन होते हैं, तो मैंने उद्धृत दूसरा कथन यह स्पष्ट कर दिया है कि कॉल स्वयं अनुपालन नहीं करता है। कोई इसे दो तरीकों से समझ सकता है। एक तरीका यह है: "यदि कोई उपयोगकर्ता इस नियम को तोड़ता है, तो वह सिस्टम को अनुपालन करता है।" लेकिन आप सही हैं, मुझे लगता है कि मूर्खतापूर्ण है। एक प्रणाली कितनी अच्छी है जब कोई गैर-वंचित उपयोगकर्ता इसे अपरंपरागत बना सकता है?ठीक है, जैसा कि मैंने इसे देखा है, किसी भी तरह से सिस्टम को यह पता होना है कि यह लाइब्रेरी सिग्कुयू() 'सिस्टम कॉल करने वाला नहीं है, तो कर्नेल को' SI_QUEUE 'के अलावा किसी अन्य चीज़ पर' si_code 'सेट करना चाहिए, और छोड़ दें यूआईडी और पिड जब आप उन्हें सेट करते हैं। मेरी राय में, आपको कर्नेल लोगों के साथ इसे उठाना चाहिए। हालांकि, उन्हें कठिनाई हो सकती है; मुझे यह पता लगाने के लिए किसी भी सुरक्षित तरीके से पता नहीं है कि एक विशेष लाइब्रेरी फ़ंक्शन द्वारा सिस्कोल बनाया गया है, यह देखते हुए कि पुस्तकालय कैसे कार्य करता है। लगभग परिभाषा के अनुसार, सिस्को के आस-पास केवल सुविधा रैपर हैं। और यह वह स्थिति हो सकती है जो वे लेते हैं, जो मुझे पता है निराशा होगी।

(मोटा) 2011-03-26, 18:00 पीएसटी के रूप में संपादित करें:

टिप्पणी लंबाई पर फिर क्योंकि की सीमाओं।

यह आर के जवाब में है .. की एक घंटे पहले की टिप्पणी।

मैं syscall विषय के लिए थोड़ा नया हूं, इसलिए कृपया मेरे साथ भालू।

"कर्नेल sysqueue syscall" से, क्या आपका मतलब `__NR_rt_sigqueueinfo 'कॉल है? यही कारण है कि केवल एक ही है कि मैंने पाया जब मैं इस किया है: अगर ऐसी बात है

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

, मुझे लगता है मैं अपने मूल बिंदु को समझने नहीं कर रहा हूँ लगता है। कर्नेल (गैर-रूट) मुझे 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() */ 

मैं तो (गैर रूट) इस प्रकार प्राप्त की ओर चला सकते हैं:

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$ 

जैसा कि आप देख सकते हैं, तीसरे कार्यक्रम ने पिड और यूआईडी को धोखा दिया है। क्या आपने मूल रूप से उस पर विरोध नहीं किया है? दृष्टि में EINVAL या EPERM नहीं है। मुझे लगता है मैं उलझन में हूँ।

+0

मुझे नहीं लगता कि यह मेरे द्वारा उद्धृत अनुच्छेद का विरोध कैसे करता है और इसकी आवश्यकताएं जो यूआईडी और पिड हो मान्य है जब 'si_code' एक प्रक्रिया-जेनरेट सिग्नल को इंगित करने वाले मानों के सेट में से एक पर ले जाता है। मैं उद्धृत पाठ में "होगा" की व्याख्या करता हूं, यह दर्शाता है कि सिग्नल हैंडलर को बुलाए जाने पर इंटरफ़ेस की परवाह किए बिना, चाहे वह सिग्नल भेजने के लिए उपयोग किया जाता है और चाहे वह मानक हो या नहीं, तब भी बाधा पर भरोसा कर सकते हैं। –

+0

मैं अपनी पूरी टिप्पणी यहां नहीं छोड़ सका; पेज ने कहा कि मेरे पास पर्याप्त पात्र नहीं थे। कृपया उपरोक्त मेरे उत्तर का संपादन देखें। –

+0

मुझे लगता है कि यह अनुरूप है या नहीं, इस बात पर निर्भर करता है कि जब भी 'si_code'' SI_QUEUE' है या अन्य विशेष मानों में से एक है, तो सिस्टम के सिग्नल * डिलीवरी * तंत्र की आवश्यकता है या ' sigqueue' समारोह। जहां तक ​​मैं कह सकता हूं, यह पूर्व नहीं है। किसी भी मामले में मैं उलझन में हूं कि क्यों कर्नेल इसे एप्लिकेशन (और इसे भरोसा कर रहा है) को विशेषाधिकार-प्रतिबंधित फ़ील्ड में भरने के लिए क्यों छोड़ रहा है ... –

0

मैं मानता हूं कि si_uid और si_pid भरोसेमंद होना चाहिए, और यदि वे नहीं हैं तो यह एक बग है। हालांकि, यह केवल तभी आवश्यक है जब सिग्नल SIGCHLD एक बच्चे की प्रक्रिया के राज्य परिवर्तन से उत्पन्न होता है, या si_codeSI_USER या SI_QUEUE है, या यदि सिस्टम XSI विकल्प और si_code <= 0 का समर्थन करता है। लिनक्स/ग्लिबैक अन्य मामलों में si_uid और si_pid मूल्य भी पास करता है; ये अक्सर भरोसेमंद नहीं होते हैं लेकिन यह एक पॉज़िक्स अनुरूपता मुद्दा नहीं है।

बेशक, kill() के लिए सिग्नल को कतारबद्ध नहीं किया जा सकता है, siginfo_t कोई अतिरिक्त जानकारी प्रदान नहीं करता है।

कारण यह है कि rt_sigqueueinfo अधिक की अनुमति देता है की तुलना में सिर्फ SI_QUEUE न्यूनतम कर्नेल समर्थन के साथ POSIX अतुल्यकालिक मैं/हे, संदेश कतार और प्रति प्रक्रिया टाइमर को लागू करने की अनुमति के लिए शायद है। उपयोगकर्तालैंड में इन्हें कार्यान्वित करने के लिए क्रमश: SI_ASYNCIO, SI_MESGQ और SI_TIMER के साथ सिग्नल भेजने की क्षमता की आवश्यकता होती है।मुझे नहीं पता कि glibc पहले से सिग्नल को कतार में संसाधनों को आवंटित करता है; मेरे लिए ऐसा लगता है कि यह नहीं है और बस उम्मीद है कि rt_sigqueueinfo विफल नहीं है। POSIX स्पष्ट रूप से एक टाइमर समाप्ति (async I/O पूरा होने, संदेश कतार पर संदेश आगमन) अधिसूचना को छोड़ने से मना करता है क्योंकि समाप्ति के समय बहुत सारे सिग्नल कतारबद्ध होते हैं; अगर अपर्याप्त संसाधन थे तो कार्यान्वयन ने निर्माण या पंजीकरण को खारिज कर दिया होगा। वस्तुओं को ध्यान से परिभाषित किया गया है कि प्रत्येक I/O अनुरोध, संदेश कतार या टाइमर एक समय में उड़ान में सबसे अधिक सिग्नल पर हो सकता है।

+0

लेकिन 'rt_sigqueueinfo'' si_code <= 0' को लागू करता है, जिस स्थिति में यूआईडी और पिड को वैध होना आवश्यक है, है ना? –

+0

हां, यदि 'si_code <= 0' और सिस्टम XSI विकल्प का समर्थन करता है, तो यूआईडी और पिड मान्य होना चाहिए। हालांकि, ऐसी कोई आवश्यकता नहीं है कि 'SI_QUEUE' या' SI_TIMER' जैसे कोड नकारात्मक या शून्य हों। भ्रम में जोड़कर, फ्रीबीएसडी एक्सएसआई विकल्प के इस हिस्से का समर्थन नहीं करता है: यदि कोई अतिरिक्त जानकारी उपलब्ध नहीं है तो यह 'si_code = 0' (उर्फ' SI_NOINFO') सेट करता है; यूआईडी और पिड इस मामले में मान्य नहीं हैं। – jilles

+0

लेकिन लिनक्स पर ये मान नकारात्मक हैं। –

संबंधित मुद्दे