2011-01-08 10 views
0

Ich entwickle einen Gerätetreiber und muss IOCTL verwenden. Leider kann ich keine Struktur aus dem Benutzerbereich kopieren. Hier ist der Code (vereinfacht, Fehlerbehandlung entfernt):Warum schlägt das Kopieren einer Struktur aus Benutzerbereich in einem ioctl-Befehl fehl?

Struktur

struct secvault_createoptions { 
    int secvaultId; 
    long dataSize; 
    char key[SECVAULT_KEYSIZE]; 
}; 

Anwendung

void createSecvault(int secvaultId) 
{ 
    struct secvault_createoptions creationOptions; 
    /* fill with data */ 
    sendIoctlCommand(SECVAULT_IOCTL_CREATE, &creationOptions); 
} 

void sendIoctlCommand(int command, void *arg) 
{ 
    FILE *stream; 
    int fd, err; 

    stream = fopen(SECVAULT_DEV_CONTROL, "r"); 
    fd = fileno(stream); 
    ioctl(fd, command, arg); 
    fclose(stream); 
} 

Kernel Module

int control_device_ioctl(struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg) 
{ 
    struct secvault_createoptions creationOptions; 
    int returnCode; 

    switch (cmd) 
    { 
     case SECVAULT_IOCTL_CREATE: 
      if (copy_from_user(&creationOptions, (void*)arg, sizeof(struct secvault_createoptions)) != sizeof(struct secvault_createoptions)) 
      { 
       /* Always this branch gets executed */ 
       printk(KERN_ALERT "Copying secure vault creation options from user space failed.\n"); 
       returnCode = -EFAULT; 
       break; 
      } 
      printk(KERN_ALERT "2 IOCTL create request on control device received: secvaultId = %d, dataSize = %ld.\n", 
       creationOptions.secvaultId, creationOptions.dataSize); 

      returnCode = createDataDevice(&creationOptions); 
      break; 
    } 
    return returnCode; 
} 

Mit besten Grüßen,
Oliver Hanappi

Antwort

4

Ihr copy_from_user Aufruf ist falsch. Es gibt nicht die Anzahl der kopierten Bytes zurück, sondern die Anzahl der Bytes, die nicht kopiert wurden. Was Sie wollen, ist

if (copy_from_user(...) != 0) 
     return -EFAULT; 

(Sie können die Zuordnung zu ret in Ihrem Snippet überspringen.)

+0

Das übliche Idiom ist, wenn (copy_from_user (...)) - FERTIG zurückgeben; – mpe

+1

Ihr Punkt ist? Es ist genau dasselbe. – user562374

2

copy_from_user() die Anzahl der Bytes zurück, die konnte nicht kopiert werden. Sie sollten also 0 für Erfolg erwarten, anstatt sizeof(struct secvault_createoptions).

0

Sie sollten die Erklärung wie

if (copy_from_user(&creationOptions, (void*)arg, sizeof(struct secvault_createoptions)) != 0) 
      { 
       /* Always this branch gets executed */ 
       printk(KERN_ALERT "Copying secure vault creation options from user space failed.\n"); 
       returnCode = -EFAULT; 
       break; 
      } 

Da copy_from_user immer 0 zurück, nach dem erfolgreichen Abschluss ändern.

Weitere Informationen finden Sie unter to this.