我有内核模块(4.4.32内核),它通过分配它的ioctl处理程序来struct file_operations
的unlocked_ioctl
指针来实现ioctl调用。 所有的工作正常,但我被给予程序(仅用于二进制),编译为2.6或2.4内核,如果我在我的4.4.32上启动这个程序不会使内核注册到我的模块的ioctl调用。 因为这个程序是在较旧的内核上编译的,所以它使用了旧的ioctl接口,即file_operations
结构中的ioctl
指针,而不是unlocked_ioctl
。
较旧的程序创build一个与用户进行视觉交互的控制台,并且必须从根控制台以root身份运行。
我对该程序进行了testing,并检查程序是否接收到第二个ioctl的ENOTTY
,所以我编写了testing程序,使相同的ioctl调用到故障程序所执行的内核模块。
我已经validation了stracelogging的跟踪对于这两个ioctl的两个程序是相同的,也就是说,用相同的参数调用这个跟踪。
我的testing程序的相关部分是:
/*--------------------------- ((( STEP 1 ))) ---------------------------*/ hsdfd1 = open(PCIHSD0, O_RDWR); if (hsdfd1 < 0) { fprintf(stderr, "Error on OPEN, can't open [%s] [%s]", PCIHSD0, strerror(errno)); exit(1); } /*--------------------------- ((( STEP 2 ))) ---------------------------*/ uint8_t xsts; err = ioctl(hsdfd1, HSDGETXSTS, &xsts); if (err < 0) { fprintf(stderr, "Error HSDGETXSTS [%s]", strerror(errno)); close(hsdfd1); exit(2); } /*--------------------------- ((( STEP 3 ))) ---------------------------*/ hsdfd2 = open(PCIHSD0c, O_NDELAY, O_RDONLY); if (hsdfd2 < 0) { fprintf(stderr, "Error on OPEN, can't open [%s] [%s]", PCIHSD0c, strerror(errno)); close(hsdfd1); exit(3); } /*--------------------------- ((( STEP 4 ))) ---------------------------*/ err = ioctl(hsdfd2, PCIHSD_DIAG_SETALLOWDC, 0x1); if (err < 0) { fprintf(stderr, "Error PCIHSD_DIAG_SETALLOWDC [%s]", strerror(errno)); err = 4; goto exit; }
领域:
我的testing程序:
execve("./hsddebug", ["./hsddebug"], [/* 23 vars */]) = 0 brk(0) = 0xb89000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9231c6b000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=105359, ...}) = 0 mmap(NULL, 105359, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9231c51000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\34\2\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=1738176, ...}) = 0 mmap(NULL, 3844640, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f92316a2000 mprotect(0x7f9231843000, 2097152, PROT_NONE) = 0 mmap(0x7f9231a43000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a1000) = 0x7f9231a43000 mmap(0x7f9231a49000, 14880, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f9231a49000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9231c50000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9231c4f000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9231c4e000 arch_prctl(ARCH_SET_FS, 0x7f9231c4f700) = 0 mprotect(0x7f9231a43000, 16384, PROT_READ) = 0 mprotect(0x7f9231c6d000, 4096, PROT_READ) = 0 munmap(0x7f9231c51000, 105359) = 0 rt_sigaction(SIGINT, {0x400826, [INT], SA_RESTORER|SA_RESTART, 0x7f92316d70e0}, {SIG_DFL, [], 0}, 8) = 0 open("/dev/pcihsd0", O_RDWR) = 3 ioctl(3, PHN_GETREG or RTC_PIE_ON, 0x7ffec60e3643) = 0 open("/dev/pcihsd0c", O_RDONLY|O_NONBLOCK) = 4 ioctl(4, 0x70c0, 0x1) = 0 fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9231c6a000 write(1, "\n", 1) = 1 write(1, "OK\n", 3) = 3 close(3) = 0 close(4) = 0 exit_group(0) = ? +++ exited with 0 +++
故障程序:
execve("./pcihsd", ["./pcihsd"], [/* 18 vars */]) = 0 uname({sys="Linux", node="debian", ...}) = 0 brk(0) = 0x83bb000 brk(0x83dc000) = 0x83dc000 rt_sigaction(SIGINT, {0x804848f, [INT], SA_RESTORER|SA_RESTART, 0x806ab28}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGQUIT, {0x804842b, [QUIT], SA_RESTORER|SA_RESTART, 0x806ab28}, {SIG_DFL, [], 0}, 8) = 0 open("PCIHSD.hlp", O_RDONLY) = 3 old_mmap(NULL, 266240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff76d7000 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 access("/root/.terminfo/l/linux-fk", R_OK) = -1 ENOENT (No such file or directory) access("/usr/share/terminfo/l/linux-fk", R_OK) = 0 open("/usr/share/terminfo/l/linux-fk", O_RDONLY) = 4 read(4, "\32\1/\0\35\0\20\0}\1a\3", 12) = 12 read(4, "linux-fk|linux console with sF9 "..., 47) = 47 read(4, "\0\1\0\0\1\1\0\0\0\0\0\0\0\1\1\0\0\0\0\0\1\0\0\0\0\0\0\1\1", 29) = 29 read(4, "\377\377\10\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\10\0@\0\22\0", 32) = 32 read(4, "\377\377\0\0\2\0\4\0\25\0\32\0!\0%\0)\0\377\3774\0E\0G\0K\0W\0\377\377"..., 762) = 762 read(4, "\7\0\r\0\33[%i%p1%d;%p2%dr\0\33[3g\0\33[H\33[J"..., 865) = 865 read(4, "", 1) = 0 read(4, "", 10) = 0 close(4) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(1, TIOCGWINSZ, {ws_row=64, ws_col=160, ws_xpixel=0, ws_ypixel=0}) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 brk(0x83fd000) = 0x83fd000 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 ioctl(1, SNDCTL_TMR_STOP or SNDRV_TIMER_IOCTL_GINFO or TCSETSW, {B38400 opost isig -icanon echo ...}) = 0 ioctl(1, SNDCTL_TMR_STOP or SNDRV_TIMER_IOCTL_GINFO or TCSETSW, {B38400 opost isig -icanon -echo ...}) = 0 rt_sigaction(SIGTSTP, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTSTP, {0x805d130, [], SA_RESTORER|SA_RESTART, 0x806ab28}, NULL, 8) = 0 rt_sigaction(SIGINT, NULL, {0x804848f, [INT], SA_RESTORER|SA_RESTART, 0x806ab28}, 8) = 0 rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTERM, {0x805d310, [], SA_RESTORER|SA_RESTART, 0x806ab28}, NULL, 8) = 0 rt_sigaction(SIGWINCH, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGWINCH, {0x805d410, [], SA_RESTORER, 0x806ab28}, NULL, 8) = 0 ioctl(1, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0 ioctl(1, SNDCTL_TMR_STOP or SNDRV_TIMER_IOCTL_GINFO or TCSETSW, {B38400 opost isig -icanon -echo ...}) = 0 write(1, "\33[1;64r\33[0;10m\33[4l\33[?7h\33[?25h\33[?"..., 34) = 34 rt_sigaction(SIGTSTP, {SIG_IGN, [], SA_RESTORER|SA_RESTART, 0x806ab28}, {0x805d130, [], SA_RESTORER|SA_RESTART, 0x806ab28}, 8) = 0 write(1, "\33[H\33[J\33[24d", 11) = 11 rt_sigaction(SIGTSTP, {0x805d130, [], SA_RESTORER|SA_RESTART, 0x806ab28}, NULL, 8) = 0 write(1, "\33[?25l\33[?1c", 11) = 11 open("PCIHSD.dft", O_RDONLY) = -1 ENOENT (No such file or directory) open("/dev/pcihsd0", O_RDWR) = 4 ioctl(4, PHN_GETREG or RTC_PIE_ON, 0x80cd480) = 0 rt_sigaction(SIGALRM, {0x804950f, [], SA_RESTORER|SA_INTERRUPT|SA_NODEFER|SA_RESETHAND, 0x806ab28}, {SIG_DFL, [], 0}, 8) = 0 open("/dev/pcihsd0c", O_RDONLY|O_NONBLOCK) = 5 ioctl(5, 0x70c0, 0x1) = -1 ENOTTY (Inappropriate ioctl for device) close(4) = 0 close(5) = 0
正如你所看到的,在这两种情况下,相关的ioctl调用是相同的,即:
open("/dev/pcihsd0", O_RDWR) = descriptor1 ioctl(descriptor1, PHN_GETREG or RTC_PIE_ON, 0x7ffec60e3643) = 0 open("/dev/pcihsd0c", O_RDONLY|O_NONBLOCK) = descriptor2 ioctl(descriptor2, 0x70c0, 0x1) = 0/ENOTTY ???
问题1:
什么可以是第二次调用ioctl(cmd 0x70c0)没有得到内核的sys_ioctl / vfs_ioctl函数被(旧)故障程序执行时调用(我在运行内核时设置了一个断点 – 调用即使对第一个ioctl的调用被正确logging,并且这两个程序的命中断点都不被内核logging)?
问题2:
在哪里插入断点来debugging呢? 为什么我在故障程序案例中根本看不到sys_ioctl
?
编辑:
感谢Wumpus Q.对于Question1的回答,不胜感激。
问题2的答案是:
当compat_ioctl
由驱动程序实现时,则调用compat_ioctl
而不是compat_ioctl
。 它是从do_syscall32_irqs_on
调用的do_syscall32_irqs_on
/ do_syscall_32_irqs_off
调用的。 对于struct file_operation
的read
处理程序,也从entry_INT80_compat
调用sys32_pread
/ SyS_pread64
。
从strace
结果中的不同指针值可以看出,工作的是64位程序,给出ENOTTY
是32位程序。
您需要定义compat_ioctl
以使您的驱动程序支持32位程序。