* Re: [PATCH] Add 32-bit ioctl translations for 64-bit platforms
2005-05-20 4:33 ` Stephen Rothwell
@ 2005-05-20 13:57 ` Corey Minyard
2005-05-20 21:22 ` Corey Minyard
1 sibling, 0 replies; 4+ messages in thread
From: Corey Minyard @ 2005-05-20 13:57 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: akpm, linux-kernel, jordan_hargrave
[-- Attachment #1: Type: text/plain, Size: 545 bytes --]
Stephen Rothwell wrote:
>Hi Cory,
>
>On Thu, 19 May 2005 18:33:21 -0500 Corey Minyard <minyard@acm.org> wrote:
>
>
>>+struct ipmi_msg32
>>+{
>>+ uint8_t netfn;
>>+ uint8_t cmd;
>>+ uint16_t data_len;
>>+ compat_uptr_t data;
>>+};
>>
>>
>
>Why are you using unint8_t etc when we have perfectly good kernel types u8
>etc?
>
>
I would say "Why does the kernel have its own types when there are
perfectly good types from the C standard?" However, it's no big deal to
me, here's a version with the kernel types.
-Corey
[-- Attachment #2: ipmi-32-bit-compat.patch --]
[-- Type: text/x-patch, Size: 5422 bytes --]
This contains the patch for supporting 32-bit compatible
ioctls on x86_64 systems. The current x86_64 driver
will not work with 32-bit applications.
Signed-off-by: Jordan Hargave <jordan_hargrave@dell.com>
Signed-off-by: Corey Minyard <minyard@acm.org>
Index: linux-2.6.12-rc4/drivers/char/ipmi/ipmi_devintf.c
===================================================================
--- linux-2.6.12-rc4.orig/drivers/char/ipmi/ipmi_devintf.c
+++ linux-2.6.12-rc4/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
#include <asm/semaphore.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/compat.h>
#define IPMI_DEVINTF_VERSION "v33"
@@ -500,10 +501,184 @@
return rv;
}
+#ifdef CONFIG_COMPAT
+/*
+ * The following code contains code for supporting 32-bit compatible
+ * ioctls on 64-bit kernels. This allows running 32-bit apps on the
+ * 64-bit kernel
+ */
+#define IPMICTL_SEND_COMMAND32 _IOR(IPMI_IOC_MAGIC, 13, struct ipmi_req32)
+#define IPMICTL_SEND_COMMAND_SETTIME32 _IOR(IPMI_IOC_MAGIC, 21, struct ipmi_req_settime32)
+#define IPMICTL_RECEIVE_MSG32 _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv32)
+#define IPMICTL_RECEIVE_MSG_TRUNC32 _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv32)
+
+struct ipmi_msg32
+{
+ u8 netfn;
+ u8 cmd;
+ u16 data_len;
+ compat_uptr_t data;
+};
+
+struct ipmi_req32
+{
+ compat_uptr_t addr;
+ u32 addr_len;
+ s32 msgid;
+
+ struct ipmi_msg32 msg;
+};
+
+struct ipmi_recv32
+{
+ s32 recv_type;
+ compat_uptr_t addr;
+ u32 addr_len;
+ u32 msgid;
+
+ struct ipmi_msg32 msg;
+};
+
+struct ipmi_req_settime32
+{
+ struct ipmi_req32 req;
+ s32 retries;
+ u32 retry_time_ms;
+};
+
+/*
+ * Define some helper functions for copying IPMI data
+ */
+static void ipmi_copymsg64(struct ipmi_msg *p64, struct ipmi_msg32 *p32)
+{
+ p64->netfn = p32->netfn;
+ p64->cmd = p32->cmd;
+ p64->data_len = p32->data_len;
+ p64->data = (char __user *)(u64)p32->data;
+}
+static void ipmi_copymsg32(struct ipmi_msg32 *p32, struct ipmi_msg *p64)
+{
+ p32->netfn = p64->netfn;
+ p32->cmd = p64->cmd;
+ p32->data_len = p64->data_len;
+}
+static void ipmi_copyreq64(struct ipmi_req *p64, struct ipmi_req32 *p32)
+{
+ p64->addr = (char __user *)(u64)p32->addr;
+ p64->addr_len = p32->addr_len;
+ p64->msgid = p32->msgid;
+ ipmi_copymsg64(&p64->msg, &p32->msg);
+}
+static void ipmi_copyrecv64(struct ipmi_recv *p64, struct ipmi_recv32 *p32)
+{
+ p64->recv_type = p32->recv_type;
+ p64->addr = (char __user *)(u64)p32->addr;
+ p64->addr_len = p32->addr_len;
+ p64->msgid = p32->msgid;
+ ipmi_copymsg64(&p64->msg, &p32->msg);
+}
+static void ipmi_copyrecv32(struct ipmi_recv32 *p32, struct ipmi_recv *p64)
+{
+ p32->recv_type = p64->recv_type;
+ p32->addr_len = p64->addr_len;
+ p32->msgid = p64->msgid;
+ ipmi_copymsg32(&p32->msg, &p64->msg);
+}
+
+/*
+ * Handle 32-bit ioctls on 64-bit kernel
+ */
+static long ipmi_ioctl32(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc;
+
+ switch(cmd) {
+ case IPMICTL_SEND_COMMAND32:
+ {
+ struct ipmi_req *preq64, req64;
+ struct ipmi_req32 req32;
+
+ /*
+ * Copy in the 32-bit ioctl structure from userspace,
+ * move fields to 64-bit ioctl structure, copy back to
+ * userspace and issue 64-bit ioctl
+ */
+ if (copy_from_user(&req32, compat_ptr(arg), sizeof(req32)))
+ return -EFAULT;
+
+ ipmi_copyreq64(&req64, &req32);
+
+ preq64 = compat_alloc_user_space(sizeof(req64));
+ if (copy_to_user(preq64, &req64, sizeof(req64)))
+ return -EFAULT;
+
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ IPMICTL_SEND_COMMAND, (long) preq64);
+ }
+ case IPMICTL_SEND_COMMAND_SETTIME32:
+ {
+ struct ipmi_req_settime *preq64, req64;
+ struct ipmi_req_settime32 req32;
+
+ if (copy_from_user(&req32, compat_ptr(arg), sizeof(req32)))
+ return -EFAULT;
+
+ ipmi_copyreq64(&req64.req, &req32.req);
+ req64.retries = req32.retries;
+ req64.retry_time_ms = req32.retry_time_ms;
+
+ preq64 = compat_alloc_user_space(sizeof(req64));
+ if (copy_to_user(preq64, &req64, sizeof(req64)))
+ return -EFAULT;
+
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ IPMICTL_SEND_COMMAND_SETTIME, (long) preq64);
+ }
+ case IPMICTL_RECEIVE_MSG32:
+ case IPMICTL_RECEIVE_MSG_TRUNC32:
+ {
+ struct ipmi_recv *precv64, recv64;
+ struct ipmi_recv32 recv32;
+
+ if (copy_from_user(&recv32, compat_ptr(arg), sizeof(recv32)))
+ return -EFAULT;
+
+ ipmi_copyrecv64(&recv64, &recv32);
+
+ precv64 = compat_alloc_user_space(sizeof(recv64));
+ if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+ return -EFAULT;
+
+ rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ ((cmd == IPMICTL_RECEIVE_MSG32)
+ ? IPMICTL_RECEIVE_MSG
+ : IPMICTL_RECEIVE_MSG_TRUNC),
+ (long) precv64);
+ if (rc != 0)
+ return rc;
+
+ if (copy_from_user(&recv64, precv64, sizeof(recv64)))
+ return -EFAULT;
+
+ ipmi_copyrecv32(&recv32, &recv64);
+ if (copy_to_user(compat_ptr(arg), &recv32, sizeof(recv32)))
+ return -EFAULT;
+
+ return rc;
+ }
+ default:
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+ }
+}
+#endif
static struct file_operations ipmi_fops = {
.owner = THIS_MODULE,
.ioctl = ipmi_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ipmi_ioctl32,
+#endif
.open = ipmi_open,
.release = ipmi_release,
.fasync = ipmi_fasync,
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] Add 32-bit ioctl translations for 64-bit platforms
2005-05-20 4:33 ` Stephen Rothwell
2005-05-20 13:57 ` Corey Minyard
@ 2005-05-20 21:22 ` Corey Minyard
1 sibling, 0 replies; 4+ messages in thread
From: Corey Minyard @ 2005-05-20 21:22 UTC (permalink / raw)
To: Stephen Rothwell, akpm; +Cc: linux-kernel, jordan_hargrave
[-- Attachment #1: Type: text/plain, Size: 467 bytes --]
Stephen suggested a lot of other changes, and I have tested the attached
patch. It seems to work fine.
-Corey
Stephen Rothwell wrote:
>Hi Cory,
>
>On Thu, 19 May 2005 18:33:21 -0500 Corey Minyard <minyard@acm.org> wrote:
>
>
>>+struct ipmi_msg32
>>+{
>>+ uint8_t netfn;
>>+ uint8_t cmd;
>>+ uint16_t data_len;
>>+ compat_uptr_t data;
>>+};
>>
>>
>
>Why are you using unint8_t etc when we have perfectly good kernel types u8
>etc?
>
>
>
[-- Attachment #2: ipmi-32-bit-compat.patch --]
[-- Type: text/x-patch, Size: 5984 bytes --]
This contains the patch for supporting 32-bit compatible
ioctls on x86_64 systems. The current x86_64 driver
will not work with 32-bit applications.
Signed-off-by: Jordan Hargave <jordan_hargrave@dell.com>
Signed-off-by: Corey Minyard <minyard@acm.org>
Index: linux-2.6.12-rc4/drivers/char/ipmi/ipmi_devintf.c
===================================================================
--- linux-2.6.12-rc4.orig/drivers/char/ipmi/ipmi_devintf.c
+++ linux-2.6.12-rc4/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
#include <asm/semaphore.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/compat.h>
#define IPMI_DEVINTF_VERSION "v33"
@@ -500,10 +501,205 @@
return rv;
}
+#ifdef CONFIG_COMPAT
+
+/*
+ * The following code contains code for supporting 32-bit compatible
+ * ioctls on 64-bit kernels. This allows running 32-bit apps on the
+ * 64-bit kernel
+ */
+#define COMPAT_IPMICTL_SEND_COMMAND \
+ _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
+#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
+ _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
+#define COMPAT_IPMICTL_RECEIVE_MSG \
+ _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
+#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
+ _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
+
+struct compat_ipmi_msg {
+ u8 netfn;
+ u8 cmd;
+ u16 data_len;
+ compat_uptr_t data;
+};
+
+struct compat_ipmi_req {
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_recv {
+ compat_int_t recv_type;
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_req_settime {
+ struct compat_ipmi_req req;
+ compat_int_t retries;
+ compat_uint_t retry_time_ms;
+};
+
+/*
+ * Define some helper functions for copying IPMI data
+ */
+static long get_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->netfn, &p32->netfn) ||
+ __get_user(p64->cmd, &p32->cmd) ||
+ __get_user(p64->data_len, &p32->data_len) ||
+ __get_user(tmp, &p32->data))
+ return -EFAULT;
+ p64->data = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->netfn, &p32->netfn) ||
+ __put_user(p64->cmd, &p32->cmd) ||
+ __put_user(p64->data_len, &p32->data_len))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_req(struct ipmi_req *p64,
+ struct compat_ipmi_req __user *p32)
+{
+
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
+ struct compat_ipmi_req_settime __user *p32)
+{
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ get_compat_ipmi_req(&p64->req, &p32->req) ||
+ __get_user(p64->retries, &p32->retries) ||
+ __get_user(p64->retry_time_ms, &p32->retry_time_ms))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->recv_type, &p32->recv_type) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->recv_type, &p32->recv_type) ||
+ __put_user(p64->addr_len, &p32->addr_len) ||
+ __put_user(p64->msgid, &p32->msgid) ||
+ put_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * Handle compatibility ioctls
+ */
+static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc;
+ struct ipmi_file_private *priv = filep->private_data;
+
+ switch(cmd) {
+ case COMPAT_IPMICTL_SEND_COMMAND:
+ {
+ struct ipmi_req rp;
+
+ if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &rp,
+ priv->default_retries,
+ priv->default_retry_time_ms);
+ }
+ case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
+ {
+ struct ipmi_req_settime sp;
+
+ if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &sp.req,
+ sp.retries, sp.retry_time_ms);
+ }
+ case COMPAT_IPMICTL_RECEIVE_MSG:
+ case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
+ {
+ struct ipmi_recv *precv64, recv64;
+
+ if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ precv64 = compat_alloc_user_space(sizeof(recv64));
+ if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+ return -EFAULT;
+
+ rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
+ ? IPMICTL_RECEIVE_MSG
+ : IPMICTL_RECEIVE_MSG_TRUNC),
+ (long) precv64);
+ if (rc != 0)
+ return rc;
+
+ if (copy_from_user(&recv64, precv64, sizeof(recv64)))
+ return -EFAULT;
+
+ if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ return rc;
+ }
+ default:
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+ }
+}
+#endif
static struct file_operations ipmi_fops = {
.owner = THIS_MODULE,
.ioctl = ipmi_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_ipmi_ioctl,
+#endif
.open = ipmi_open,
.release = ipmi_release,
.fasync = ipmi_fasync,
^ permalink raw reply [flat|nested] 4+ messages in thread