2013-02-20 10 views
10

मुझे हमेशा बताया गया है (पुस्तकें और ट्यूटोरियल में) कि कर्नेल स्पेस से डेटा स्थान पर डेटा कॉपी करते समय, हमें copy_to_user() का उपयोग करना चाहिए और memcpy() का उपयोग करना सिस्टम को समस्याएं पैदा करेगा। हाल ही में गलती से मैंने memcpy() का उपयोग किया है और यह किसी भी समस्या के साथ पूरी तरह से ठीक काम किया है। क्यों है कि हम memcpy() के बजाय copy_to_user का उपयोगcopy_to_user बनाम memcpy

मेरे परीक्षण कोड (कर्नेल मॉड्यूल) कुछ इस तरह है चाहिए: उपयोगकर्ता के अंतरिक्ष अनुप्रयोग से

static ssize_t test_read(struct file *file, char __user * buf, 
      size_t len, loff_t * offset) 
{ 
    char ani[100]; 

    if (!*offset) { 
     memset(ani, 'A', 100); 
     if (memcpy(buf, ani, 100)) 
      return -EFAULT; 
     *offset = 100; 
     return *offset; 
    } 

    return 0; 
} 

struct file_operations test_fops = { 
    .owner = THIS_MODULE, 
    .read = test_read, 
}; 

static int __init my_module_init(void) 
{ 
    struct proc_dir_entry *entry; 

    printk("We are testing now!!\n"); 
    entry = create_proc_entry("test", S_IFREG | S_IRUGO, NULL); 
    if (!entry) 
     printk("Failed to creats proc entry test\n"); 

    entry->proc_fops = &test_fops; 
    return 0; 
} 
module_init(my_module_init); 

, मैं अपने /proc प्रविष्टि पढ़ रहा हूँ और सब कुछ ठीक काम करता है।

copy_to_user() के स्रोत कोड पर एक नज़र यह कहता है कि यह भी सरल memcpy() है जहां हम यह जांचने की कोशिश कर रहे हैं कि पॉइंटर मान्य है या access_ok के साथ नहीं है और memcpy कर रहा है।

तो मेरी समझ वर्तमान में है कि, अगर हम सूचक हम गुजर रहे हैं के बारे में निश्चित नहीं हैं, memcpy() हमेशा copy_to_user के स्थान पर इस्तेमाल किया जा सकता है।

अगर मेरी समझ गलत है और कोई उदाहरण है जहां copy_to_user काम करता है और memcpy() विफल रहता है तो बहुत उपयोगी होगा। धन्यवाद।

+0

यह पेजिंग की वजह से है। – Linuxios

+0

@Linuxios क्षमा करें, लेकिन क्या आप एक लिटल को और अधिक समझा सकते हैं। मैं उचित ठहराने में सक्षम नहीं हूं क्योंकि कर्नेल पूरी तरह से ठीक करने में सक्षम है, मैं copy_to_user के स्रोत कोड में पेजिंग से संबंधित कुछ भी नहीं देख पा रहा हूं। क्या आप कृपया विस्तार से बता सकते हैं? –

+1

@ सैंडी: हाइपोटेटिकल प्रश्न: आप 16 जीबी रैम के साथ 32-बिट सिस्टम का उपयोग कर रहे हैं। काम करेगा memcpy? –

उत्तर

23

इसके लिए कुछ कारण हैं।

पहला, सुरक्षा। चूंकि कर्नेल किसी भी पते पर लिख सकता है, यदि आप केवल उपयोगकर्ता-स्थान पते का उपयोग करते हैं और memcpy का उपयोग करते हैं, तो हमलावर किसी अन्य प्रक्रिया के पृष्ठों को लिख सकता है, जो एक बड़ी सुरक्षा समस्या है। copy_to_user जांचता है कि लक्षित पृष्ठ वर्तमान प्रक्रिया द्वारा लिखने योग्य है।

कुछ वास्तुकला विचार भी हैं। X86 पर, उदाहरण के लिए, लक्ष्य पृष्ठों को स्मृति में पिन किया जाना चाहिए। कुछ आर्किटेक्चर पर, आपको विशेष निर्देशों की आवश्यकता हो सकती है। और इसी तरह। बहुत पोर्टेबल होने के लिनक्स कर्नेल लक्ष्य इस तरह के अमूर्तता की आवश्यकता है।

+6

+1 सुरक्षा के लिए 0 -1 से-आप-उपयोग-प्रति-प्रति-उपयोगकर्ता-प्रति-उपयोगकर्ता-से-पहुंच-उपयोगकर्ता-स्थान-से-उपयोग करें। सिर्फ एक और प्रक्रिया नहीं है। एक 3 जी/1 जी मेमोरी विभाजित करने के साथ 'उपयोगकर्ता' प्रक्रिया कर्नेल मेमोरी को ओवर-लिखने का प्रयास कर सकती है। यह विशेष रूप से उपयोगी हो सकता है यदि आपका डेटा कर्नेल को संशोधित करने के लिए 'कोड' है। कई 'सीपीयू के पास उपयोगकर्ता और पर्यवेक्षक मोड होते हैं। एमएमयू-कम में भी, 'memcpy()' खराब है। –

+0

@ बिलप्रिंगलेमेयर: बिल्कुल। +1 के लिए धन्यवाद। – Linuxios

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