我有內核模塊(4.4.32內核),它通過將指針的ioctl處理程序分配給struct file_operations
的unlocked_ioctl
指針來實現ioctl調用。所有工作正常,但我被給予程序(僅用於二進制),編譯爲2.6或2.4內核,如果我在我的4.4.32上啓動該程序,不會使內核註冊到我的模塊的ioctl調用。 由於該程序是在較早的內核上編譯的,因此它使用較舊的ioctl接口,即結構中的ioctl
指針,而不是unlocked_ioctl
。爲什麼ioctl調用不會傳遞給sys_ioctl?
較舊的程序會創建一個控制檯,以便與用戶進行可視化交互,並且必須以root用戶身份從根控制檯運行。
我對該程序進行了測試,並檢查了第二個ioctl的程序收到了ENOTTY
,所以我編寫了測試程序,它對故障程序所在的內核模塊執行相同的ioctl調用。
我已驗證strace記錄的跟蹤對於這兩個ioctl的兩個程序都是相同的,即相同序列中調用了相同的參數。
我的測試程序的相關部分是:
/*--------------------------- (((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;
}
的straces:
我的測試程序:
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\[email protected]\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
調用。 sys32_pread
/SyS_pread64
從entry_INT80_compat
調用struct file_operation
的read
處理程序。
'unlocked_ioctl'是爲內核驅動程序兼容性而創建的,即I.e.以避免打破不支持重入ioctl的潛水員。我不相信用戶空間需要知道使用哪個。 – TrentP