2013-02-20 15 views
10

Kernel uzayından kullanıcı alanına veri kopyalarken, copy_to_user() yöntemini kullanmalı ve memcpy() kullanarak sistemde sorunlara neden olabilecek her zaman söylendi (Kitaplarda ve öğreticilerde). Geçenlerde yanlışlıkla memcpy() kullandım ve herhangi bir sorunla mükemmel bir şekilde çalıştı. Nedencopy_to_user vs memcpy

Testim kodu (Kernel modülü) böyle bir şeydir yerine memcpy() ait copy_to_user kullanmak gerektiğidir:

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); 

kullanıcı uzay uygulamasından, benim /proc girişi okuyorum ve her şey iyi çalışıyor.

copy_to_user() kaynak koduna bir bakış, bunun da basit bir şekilde memcpy() olduğunu belirtir; burada yalnızca işaretçinin geçerli olup olmadığını, access_ok ve memcpy ile çalışıp çalışmadığını kontrol etmeye çalışırız.

Yani benim anlayış anda biz geçiyoruz pointer hakkında eminseniz , memcpy() her zaman copy_to_user yerine kullanılabilecek olmasıdır.

Anlayışım yanlışsa ve ayrıca, , copy_to_user öğesinin çalıştığı ve memcpy() 'nin başarısız olduğu herhangi bir örnek, çok yararlı olabilir. Teşekkürler.

+0

Sayfalama nedeniyle. – Linuxios

+0

@Linuxios Üzgünüm Ama bir littl daha açıklayabilir misiniz. Çekirdeğin mükemmel bir şekilde kopyalayabildiğini doğrulayamıyorum, ayrıca copy_to_user kaynak kodundaki sayfalama ile ilgili hiçbir şey göremiyorum. Nazikçe detay verebilir misiniz? –

+1

@Sandy: Varsayımsal soru: 16 GB RAM ile 32 bit bir sistem kullanıyorsunuz. Memcpy çalışacak mı? –

cevap

23

Bunun için birkaç neden var.

İlk önce, güvenlik. Çekirdek istediği herhangi bir adrese yazabildiğinden, sadece bir kullanıcı-alan adresi kullanıp memcpy kullanıyorsa, bir saldırgan başka bir işlemin sayfalarına yazabilir, bu da büyük bir güvenlik problemidir. copy_to_user, hedef sayfanın geçerli işlem tarafından yazılabilir olduğunu denetler.

Bazı mimari hususlar da vardır. Örneğin x86'da, hedef sayfaların belleğe sabitlenmesi gerekir. Bazı mimarilerde özel talimatlara ihtiyacınız olabilir. Ve bunun gibi. Linux çekirdeklerinin çok portatif olma hedefleri bu türden bir soyutlamayı gerektirir.

+6

+1 Güvenlik için. Sadece başka bir süreç değil. Bir 3G/1G bellek bölünmesiyle bir 'kullanıcı' işlemi çekirdek belleğinin üzerine yazmayı deneyebilir. Bu, verileriniz çekirdeği değiştirmek için "kod" ise, özellikle yararlı olabilir. Birçok 'CPU'nun kullanıcı ve yönetici modları var. MMU'suzda bile, memcpy() 'kötü. –

+0

@BillPringlemeir: Tam olarak. +1 için teşekkürler. – Linuxios