我有一个内核模块(4.4.32内核),它通过将ioctl处理程序分配给< code > struct file _ operations 的< code>unlocked_ioctl指针来实现ioctl调用。一切正常,但是我得到的程序(只有二进制)是为2.6或者2.4内核编译的,如果我在4.4.32上启动这个程序,它不会让内核为我的模块注册一个对ioctl的调用。因为此程序是在旧内核上编译的,所以它使用旧的ioctl接口,即< code>file_operations结构中的< code>ioctl指针,而不是< code>unlocked_ioctl。
较旧的程序创建一个控制台,用于与用户进行可视化交互,并且必须从根控制台以 root 身份运行。
我仔细检查了该程序,并检查该程序是否接收到第二个ioctl的ENOTTY
,因此我编写了一个测试程序,它对内核模块进行与故障程序相同的ioctl调用。
我已经验证了对于这些ioctl,由strace记录的trace对于两个程序是相同的,也就是说,它们以相同的顺序用相同的参数调用。
我的测试程序的相关部分是:
/*--------------------------- ((( 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;
}
斯特拉斯:
我的测试程序:
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 的调用并且两个程序都命中了断点),这是什么原因?
问题2:
在哪里插入断点来调试这个?为什么我看不到sys_ioctl
在故障程序案例中被调用?
编辑:
感谢Wumpus Q. Wumbley对问题1的回答。
问题2的答案是:
当驱动程序实现compat_ioctl
时,将调用compat_SyS_ioctl
,而不是compat_ioctl
。它从do_syscall32_irqs_on
/do_syscall_32_irqs_off
调用,从entry_INT80_compat
调用。此外,还会
从结构file_operation
的读取
处理程序的entry_INT80_compat
调用sys32_pread/SyS_pread64
。
从 strace
结果中的不同指针值中,我可以看到有效的指针值是 64 位程序,而给出 ENOTTY 的程序
是 32 位程序。
您需要定义一个compat_ioctl
来使您的驱动程序支持32位程序。
问题内容: 在猫鼬文档中,它经常列出某些查询运算符(如)的可选回调,但是,它没有提及回调采用的参数(参数)。他们是什么,我怎么知道? 另外,如果,等都是可选的,我想在结束时指定一个回调,我必须在传递值,或空物体或我可以只指定回调- 和软管做猫鼬知道吗? 问题答案: 对于几乎所有的猫鼬查询,所提供的函数将在文档中所述的节点回调模式 中用两个参数调用: 在Mongoose中将回调传递给查询的任何地方,
我已经建立了一个asp.netmvc网页。我的所有操作,如:创建、编辑等...有自己的视图,除了删除,因为我正试图在Bootstrap的帮助下弹出一个模态。我通过jQuery/JavaScript向modal传递一个id,并将asp-action作为表单的属性,理论上它应该可以工作,但事实并非如此。 索引视图: 删除控制器中的操作: Javascript: 输入获取id作为名称的值: 调试时,它不
问题内容: 为什么经常被称为 代替 ? W3,MDN和MSDN都声明它是可选的。此外,ActiveX控件似乎不需要参数: 这种做法至少可以追溯到2005年的Google Maps中 ,但被缩小了,没有任何解释: 问题答案: 如果您看一下XMLHttpRequest的旧规范,似乎W3C似乎并不需要在某一点上将该参数设为可选,这可能导致人们提供了一个明确的null值,以防万一。 (搜索“应支持发送”)
问题内容: 什么是@id? 在$ resource doc页面上,有人在下面说了这一点,但是我还是不明白。 如果参数值以@开头,则从数据对象中提取该参数的值(对非GET操作有用)。“这里的数据对象是指使用非GET” class“操作的对象,或者如果使用非GET实例操作,则为实例本身。 问题答案: 如果我正确理解了这一点,而我可能没有理解,则该参数说明了向url变量提供数据的另一种方式。 给定此方法
本文向大家介绍为什么Java中只有值传递?相关面试题,主要包含被问及为什么Java中只有值传递?时的应答技巧和注意事项,需要的朋友参考一下 首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对
问题内容: 我当时在Swinject上工作,但问题困扰着我。我已经整整一天都被困在那里。我怀疑这是由于Swift是一种静态类型的语言,但我不确定。 我在这个操场上总结了我的问题 我尝试了不同的解决方案,例如test.self或type(of:test),但它们都不起作用。 所以我想我不能用提供为变量的通用参数来调用函数? 问题答案: 与 协议元类型有两种。对于某些协议和符合类型: A 描述协议本身