Perché la copia di una struttura dallo spazio utente non riesce in un comando ioctl?
-
08-10-2019 - |
Domanda
sto sviluppando un driver di periferica e necessità di fare uso di IOCTL. Purtroppo non posso copiare una struct dallo spazio utente. Ecco il codice (semplificato, la gestione degli errori rimosso):
Struttura
struct secvault_createoptions {
int secvaultId;
long dataSize;
char key[SECVAULT_KEYSIZE];
};
Applicazioni
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;
}
Con i migliori saluti,
Oliver Hanappi
Soluzione
La chiamata copy_from_user
è sbagliato. Non restituisce la quantità di byte copiati, ma il numero di byte che non sono state copiate. Quello che vuoi è
if (copy_from_user(...) != 0)
return -EFAULT;
(È possibile saltare il compito di ret
nello snippet.)
Altri suggerimenti
copy_from_user()
restituisce il numero di byte che potrebbe non essere copiati. Quindi si dovrebbe aspettare 0
per il successo, piuttosto che sizeof(struct secvault_createoptions)
.
Si dovrebbe modificare l'istruzione come,
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;
}
A causa copy_from_user
restituisce sempre 0 dopo il completamento con successo.
Si prega di fare riferimento href="http://man7.org/linux/man-pages/man2/ioctl.2.html" a questo per ulteriori dettagli.