Linux – Get all ioctl code and which module they map

ioctlkernel-moduleslinux

By doc. , ioctl signature is int ioctl(int fd, int request, ...) . request is the code of ioctl.

Is there any way to know what are all the possible ioctl request code that available in my linux? And maybe to know for each code , to which kernel module is mapped?

Best Answer

It is possible to find all ioctl definitions by using the kernel source, vim and ctags program. I just use the tools from my toolbox, you can use others - maybe IDE like Netbeans or Eclipse. The essence is the same.

Demonstration: (you can download this .gif file and open it by GIMP for example. Then all frames will be available without time limit) enter image description here

Explanation:

1) I think, we are not have other ways, except digging into the kernel source. The different manuals exists, check apropos ioctl, but they are either incomplete or outdated. So, the most reliable way is looking at the source (if you don't have documentation from the module creator). The user process uses ioctl system call to send different commands to the kernel module. The module has definition and comments for each ioctl command. Our task is to find them.

Note start

You should use the same kernel source version as the glibc uses, not current kernel on your system, because glibc headers are used in the compilation of user programs. Thus, if you will use the last kernel source (or other, different from the glibc's), the result could be wrong.

To find the glibc headers version on Ubuntu do:

dpkg -l linux-libc-dev*

Result:

ii  linux-libc-dev:amd64  4.15.0-50.54    amd64           Linux Kernel Headers for development

Download the kernel source code with Ubuntu patches from repository into the current directory (on Ubuntu):

apt-get source linux-source-4.15.0

Note end

2) ioctl commands are defined in the module header file - some_name.h. They are just numbers, which can be calculated by special macro:

#define "ioctl name" __IOX("major number","command number","argument type")

From documentation:

If you are adding new ioctl's to the kernel, you should use the _IO macros defined in linux/ioctl.h:

_IO    an ioctl with no parameters
_IOW   an ioctl with write parameters (copy_from_user)
_IOR   an ioctl with read parameters  (copy_to_user)
_IOWR  an ioctl with both write and read parameters.

But some ioctl definitions are not following this prescription and are not different from usual macros, like in the case of tty driver:

#define TCGETS      0x5401

so, we can't just grep header files.

3) The defined ioctl commands are used in the module source code file - some_name.c. There are special function - handler, which is called on each ioctl request. It takes the ioctl number as argument and switches the program execution to the corresponding branch, like:

switch(ioctl_cmd){
    case IOCTL_ONE:
        processing;
        break;
    case IOCTL_TWO:
        processing;
        break;
    case IOCTL_THREE:
        processing;
        break;
}

4) This ioctl handler is stored in the .unlocked_ioctl field of the file_operations struct:

static const struct file_operations sonypi_misc_fops = {
    ...      
    .unlocked_ioctl = sonypi_misc_ioctl,

Therefore, we can find this assignment in the source code, jump to the handler function definition by ctags program and look at ioctl branches in the switch construction. Then jump further, to the specific command in the header file and look at the definition and comments.

Related Question