Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 3055
b: refs/heads/master
c: 6a94f92
h: refs/heads/master
i:
  3053: be9b49a
  3051: 808c0f1
  3047: fdc005e
  3039: 0490899
v: v3
  • Loading branch information
Andrew Morton authored and Linus Torvalds committed Jun 24, 2005
1 parent 3213398 commit 43204a2
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 77cf3973f22c7e7158f5e2c3c3d6809125b77e4b
refs/heads/master: 6a94f9209762a6eb286f668e1346ad87985cc765
196 changes: 196 additions & 0 deletions trunk/drivers/char/ipmi/ipmi_devintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
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,
Expand Down

0 comments on commit 43204a2

Please sign in to comment.