2013-02-20 20 views
10

Mi è sempre stato detto (nei libri e nelle esercitazioni) che copiando i dati dallo spazio del kernel allo spazio utente, dovremmo usare copy_to_user() e usare memcpy() causerebbe problemi al sistema. Recentemente per errore ho usato memcpy() e ha funzionato perfettamente senza problemi. Perché che dovremmo usare copy_to_user invece di memcpy()copy_to_user vs memcpy

mio codice di prova (modulo Kernel) è qualcosa di simile:

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

Da user-space app, sto leggendo il mio ingresso /proc e tutto funziona bene

Uno sguardo al codice sorgente di copy_to_user() dice che è anche semplice memcpy() dove stiamo solo cercando di verificare se il puntatore è valido o meno con access_ok e facendo memcpy.

Così mia comprensione attualmente è che, se siamo sicuri circa il puntatore stiamo passando, memcpy() può sempre essere usato al posto di copy_to_user.

Si prega di correggermi se la mia comprensione non è corretta e inoltre, qualsiasi esempio in cui copy_to_user funziona e memcpy() non riesce sarebbe molto utile. Grazie.

+0

È a causa del paging. – Linuxios

+0

@Linuxios Scusa, ma puoi spiegarmi un po 'di più. Non sono in grado di giustificare il fatto che il kernel sia in grado di copiare perfettamente anche io non sono in grado di vedere nulla relativo al paging nel codice sorgente di copy_to_user. Potresti gentilmente elaborare? –

+1

@Sandy: domanda ipotetica: si sta utilizzando un sistema a 32 bit con 16 GB di RAM. La memcpy funzionerà? –

risposta

23

Ci sono un paio di motivi per questo.

Primo, sicurezza. Poiché il kernel può scrivere su qualsiasi indirizzo desiderato, se si utilizza semplicemente un indirizzo dello spazio utente che si ottiene e si utilizza memcpy, un utente malintenzionato potrebbe scrivere sulle pagine di un altro processo, il che rappresenta un enorme problema di sicurezza. copy_to_user controlla che la pagina di destinazione sia scrivibile dal processo corrente.

Ci sono anche alcune considerazioni di architettura. Su x86, ad esempio, le pagine di destinazione devono essere bloccate in memoria. Su alcune architetture, potresti aver bisogno di istruzioni speciali. E così via. L'obiettivo dei kernel Linux di essere molto portabile richiede questo tipo di astrazione.

+6

+1 per sicurezza. Non solo un altro processo. Con una suddivisione di memoria 3G/1G un processo utente può provare a sovrascrivere la memoria del kernel. Questo potrebbe essere particolarmente utile se i tuoi dati sono 'code' per modificare il kernel. Molti 'CPU' hanno modalità utente e supervisore. Anche in MMU-less, 'memcpy()' è cattivo. –

+0

@BillPringlemeir: Esattamente. Grazie per il +1. – Linuxios