來自 32 位用戶代碼的 64 位系統中的 ioctl 命令錯誤 (ioctl command wrong in 64 bit system from 32 bit user code)


問題描述

來自 32 位用戶代碼的 64 位系統中的 ioctl 命令錯誤 (ioctl command wrong in 64 bit system from 32 bit user code)

I'm upgrading a device driver from a 32bit RHEL 2.6.32 to 64bit RHEL 2.6.33.9.

I have a program that talks to that driver using ioctl.  It works perfectly when both the driver and the program are either 64bit or 32bit.  But when the driver is 64bit, and my program is 32 bit, the ioctl command received by the driver (in compat_ioctl) does not match the values defined by the _IOR and _IOW macros.

In my driver's switch statement, the default case prints out the values of all the valid commands, which are 1-12.  The 32bit ioctl command is nowhere near those values.

Can someone tell me what would cause the command from a 32bit user program to be messed up when received in a 64bit driver?

Here's some of the code: I had to type it in; the code is on a secured system without internet access, so please forgive any typos.  It actually does comile and run!

// IOCTL commands from the include file - most omitted
// ...
#define PORTIO_GET_IRQ_CNT_CMD  10
#define PORTIO_CLR_IRQ_CNT_CMD  11
#define PORTIO_GET_IRQ_TIME_CMD 12

#define PORTIO_IOCTL     'k'  // magic number for ioctl

// IOCTL Macros
#define PORTIO_GET_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_CNT_CMD, unsigned long)
#define PORTIO_CLR_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_CLR_IRQ_CNT_CMD, unsigned long)
#define PORTIO_GET_IRQ_TIME_IOCTL   _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_TIME_CMD, unsigned long)

Here's the 32 bit compatible IOCTL routine, from portio.c.  I've confirmed that this is being called only when my program is compiled as 32bit, and the driver is 64bit.

static long portio_compat_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
unsigned char cmd_number;
int cmd_size=0;
//...
cmd_number = _IOC_NR( cmd );
cmd_size = _IOC_SIZE( cmd );

printk( KERN_ALERT "Portio Compat IOCTL number,size = %d,%d, cmd_number, cmd_size );
//... Switch statement and cases, based on cmd_number
}

The output looks like this:

Portio Compat IOTCL number,size = 224,3157

Of course, the code expects IOCTL numbers from 1-12, and sizes around 4 or 8.  That's exactly what comes back when the code and driver are both either 64bit or 32bit.  


參考解法

方法 1:

It seems to me that your function compat_ioctl takes too many parameters. Look at other definitions in the Linux kernel:

long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)

http://lxr.linux.no/#linux+v3.5.3/block/compat_ioctl.c#L654

方法 2:

#define PORTIO_GET_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_CNT_CMD, unsigned long)
#define PORTIO_CLR_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_CLR_IRQ_CNT_CMD, unsigned long)
#define PORTIO_GET_IRQ_TIME_IOCTL   _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_TIME_CMD, unsigned long)

change unsigned long to unit64_t (fixed data type) remove all pointer from ioctl macro arguments, have :

.compat_ioctl
.unlocked_ioctl in kernel pointing to same function.

(by Steve Sibertuser1202136ashish)

參考文件

  1. ioctl command wrong in 64 bit system from 32 bit user code (CC BY-SA 3.0/4.0)

#32-bit #64-bit #linux






相關問題

內聯彙編 - cdecl 和準備堆棧 (Inline assembly - cdecl and preparing the stack)

來自 32 位用戶代碼的 64 位系統中的 ioctl 命令錯誤 (ioctl command wrong in 64 bit system from 32 bit user code)

Baiklah, PR: Bagaimana mungkin X[i] diinterpretasikan sama dengan i[X] di C? (Alright, homework: How can X[i] possibly be interpretted the same as i[X] in C?)

x32 ABI - гэта інструмент, як ім карыстацца (x32 ABI is this a tool ,how to use this)

Biên dịch Visual Studio 2012 32bit trên hệ thống 64bit (Visual Studio 2012 32bit compilation on 64bit system)

如何讓 Netbeans 7.2 使用 32 位 JVM (How get Netbeans 7.2 to use 32 Bit JVM)

反彙編代碼中的數組聲明 (Declaration of an array in disassembled code)

用C編寫跨平台應用程序 (Writing cross-platform apps in C)

為什麼 BinaryReader.ReadUInt32() 反轉位模式? (Why does BinaryReader.ReadUInt32() reverse the bit pattern?)

32 位 RHEL 機器上的內存使用 (Memory use on 32 bit RHEL machine)

將 32 位應用程序安裝到 C:\Program Files\ 而不是 C:\Program Files(x86)\ 會有什麼負面影響? (What would be the negative effects of installing a 32bit app into the C:\Program Files\ instead of the C:\Program Files(x86)\?)

Arduino 將浮點數轉換為十六進制 IEEE754 單精度 32 位 (Arduino convert float to hex IEEE754 Single precision 32-bit)







留言討論