2012-04-09 16 views
11

Sto sviluppando un modulo del kernel che utilizza unlocked_ioctl. L'ho provato con la versione del kernel 2.6.24-23-generic e funziona perfettamente. Ora l'ho provato con la versione 3.3.1-1-ARCH del kernel e succede qualcosa di strano: la funzione ioctl non viene eseguita quando il valore della richiesta (cmd) è 2. Restituisce 0, ma la funzione non viene eseguita. Al fine di verificare che non viene eseguito ho fatto la seguente:ioctl non viene chiamato se cmd = 2

static long midriver_ioctl(struct file *file, 
    unsigned int cmd, unsigned long arg) { 

printk("Called with cmd = %d\n", cmd); 

ho scritto un programma di test che chiama ioctl per questo dispositivo 0-4096, e posso vedere nel dmesg il messaggio "Chiamati con cmd = n "per tutti quei valori, tranne" 2 ", l'unico che non viene mostrato.

Eventuali indizi su ciò che sto facendo male?

Grazie in anticipo,

+0

Alcuni codice nella catena sta intercettando == cmd 2 e la manipolazione? – zvrba

risposta

9

dare uno sguardo su this:

546 int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, 
547    unsigned long arg) 
548 { 
549  int error = 0; 
550  int __user *argp = (int __user *)arg; 
551  struct inode *inode = filp->f_path.dentry->d_inode; 
552 
553  switch (cmd) { 
554  case FIOCLEX: 
555    set_close_on_exec(fd, 1); 
556    break; 
557 
558  case FIONCLEX: 
559    set_close_on_exec(fd, 0); 
560    break; 
561 
562  case FIONBIO: 
563    error = ioctl_fionbio(filp, argp); 
564    break; 
565 
566  case FIOASYNC: 
567    error = ioctl_fioasync(fd, filp, argp); 
568    break; 
569 
570  case FIOQSIZE: 
571    if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || 
572     S_ISLNK(inode->i_mode)) { 
573      loff_t res = inode_get_bytes(inode); 
574      error = copy_to_user(argp, &res, sizeof(res)) ? 
575          -EFAULT : 0; 
576    } else 
577      error = -ENOTTY; 
578    break; 
579 
580  case FIFREEZE: 
581    error = ioctl_fsfreeze(filp); 
582    break; 
583 
584  case FITHAW: 
585    error = ioctl_fsthaw(filp); 
586    break; 
587 
588  case FS_IOC_FIEMAP: 
589    return ioctl_fiemap(filp, arg); 
590 
591  case FIGETBSZ: 
592    return put_user(inode->i_sb->s_blocksize, argp); 
593 
594  default: 
595    if (S_ISREG(inode->i_mode)) 
596      error = file_ioctl(filp, cmd, arg); 
597    else 
598      error = vfs_ioctl(filp, cmd, arg); 
599    break; 
600  } 
601  return error; 
602 

Come si può vedere, c'è qualche dello switch-casi prima vfs_ioctl o file_ioctl chiamata.

+0

Non riesco a vedere la pertinenza, nessuno di questi casi si applica – Hasturkun

+1

Sono corretto, il valore di 'FIGETBSZ' è in effetti 2, +1 – Hasturkun

3

Come indicato da @Ilya, si sta verificando un caso generico (FIGETBSZ in questo caso).

In generale, si desidera comporre i comandi ioctl utilizzando _IO family of macros, con un tipo unico, per evitare collisioni.

vi suggerisco di leggere ioctl-number.txt dalla documentazione del kernel per ulteriori informazioni, compreso un elenco della maggior parte dei tipi utilizzati

+0

Ecco un esempio di' ioctl' minimo usando '_IOx': https: // stackoverflow .com/a/44613896/895245 –