2011-01-08 1 views
0

Je développe un pilote de périphérique et j'ai besoin d'utiliser IOCTL. Malheureusement, je ne peux pas copier une structure de l'espace utilisateur. Voici le code (simplifié, gestion des erreurs supprimé):Pourquoi la copie d'une structure à partir de l'espace utilisateur échoue-t-elle dans une commande ioctl?

Structure

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

application

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

noyau 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; 
} 

Cordialement,
Oliver Hanappi

Répondre

4

Votre appel copy_from_user est faux. Il ne renvoie pas la quantité d'octets copiés, mais le nombre d'octets qui n'ont pas été copiés. Ce que vous voulez est

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

(Vous pouvez ignorer l'affectation à ret dans votre extrait.)

+0

L'idiome habituel est if (copy_from_user (...)) renvoie -EFAULT; – mpe

+1

Votre point étant? C'est exactement pareil. – user562374

2

copy_from_user() renvoie le nombre d'octets qui pourrait pas copier. Donc, vous devriez vous attendre 0 pour le succès, plutôt que sizeof(struct secvault_createoptions).

0

Vous devez modifier la déclaration,

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

Parce que copy_from_user retourne toujours 0 après la réussite.

Veuillez consulter to this pour plus de détails.

Questions connexes