Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67131
b: refs/heads/master
c: a394f83
h: refs/heads/master
i:
  67129: 4bcc213
  67127: 40adb05
v: v3
  • Loading branch information
Roland Dreier committed Oct 10, 2007
1 parent 35b1e5b commit f4a32c3
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2be8e3ee8efd6f99ce454115c29d09750915021a
refs/heads/master: a394f83bdfec10b09d8cb111e622556b2e6fd0de
49 changes: 40 additions & 9 deletions trunk/drivers/infiniband/core/user_mad.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <linux/poll.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
#include <linux/compat.h>

#include <asm/uaccess.h>
#include <asm/semaphore.h>
Expand Down Expand Up @@ -607,7 +608,8 @@ static unsigned int ib_umad_poll(struct file *filp, struct poll_table_struct *wa
return mask;
}

static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
int compat_method_mask)
{
struct ib_user_mad_reg_req ureq;
struct ib_mad_reg_req req;
Expand All @@ -622,7 +624,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
goto out;
}

if (copy_from_user(&ureq, (void __user *) arg, sizeof ureq)) {
if (copy_from_user(&ureq, arg, sizeof ureq)) {
ret = -EFAULT;
goto out;
}
Expand All @@ -643,8 +645,18 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
if (ureq.mgmt_class) {
req.mgmt_class = ureq.mgmt_class;
req.mgmt_class_version = ureq.mgmt_class_version;
memcpy(req.method_mask, ureq.method_mask, sizeof req.method_mask);
memcpy(req.oui, ureq.oui, sizeof req.oui);
memcpy(req.oui, ureq.oui, sizeof req.oui);

if (compat_method_mask) {
u32 *umm = (u32 *) ureq.method_mask;
int i;

for (i = 0; i < BITS_TO_LONGS(IB_MGMT_MAX_METHODS); ++i)
req.method_mask[i] =
umm[i * 2] | ((u64) umm[i * 2 + 1] << 32);
} else
memcpy(req.method_mask, ureq.method_mask,
sizeof req.method_mask);
}

agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num,
Expand Down Expand Up @@ -682,13 +694,13 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
return ret;
}

static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
{
struct ib_mad_agent *agent = NULL;
u32 id;
int ret = 0;

if (get_user(id, (u32 __user *) arg))
if (get_user(id, arg))
return -EFAULT;

down_write(&file->port->mutex);
Expand Down Expand Up @@ -729,16 +741,33 @@ static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
{
switch (cmd) {
case IB_USER_MAD_REGISTER_AGENT:
return ib_umad_reg_agent(filp->private_data, arg);
return ib_umad_reg_agent(filp->private_data, (void __user *) arg, 0);
case IB_USER_MAD_UNREGISTER_AGENT:
return ib_umad_unreg_agent(filp->private_data, arg);
return ib_umad_unreg_agent(filp->private_data, (__u32 __user *) arg);
case IB_USER_MAD_ENABLE_PKEY:
return ib_umad_enable_pkey(filp->private_data);
default:
return -ENOIOCTLCMD;
}
}

#ifdef CONFIG_COMPAT
static long ib_umad_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
case IB_USER_MAD_REGISTER_AGENT:
return ib_umad_reg_agent(filp->private_data, compat_ptr(arg), 1);
case IB_USER_MAD_UNREGISTER_AGENT:
return ib_umad_unreg_agent(filp->private_data, compat_ptr(arg));
case IB_USER_MAD_ENABLE_PKEY:
return ib_umad_enable_pkey(filp->private_data);
default:
return -ENOIOCTLCMD;
}
}
#endif

static int ib_umad_open(struct inode *inode, struct file *filp)
{
struct ib_umad_port *port;
Expand Down Expand Up @@ -826,7 +855,9 @@ static const struct file_operations umad_fops = {
.write = ib_umad_write,
.poll = ib_umad_poll,
.unlocked_ioctl = ib_umad_ioctl,
.compat_ioctl = ib_umad_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ib_umad_compat_ioctl,
#endif
.open = ib_umad_open,
.release = ib_umad_close
};
Expand Down
22 changes: 21 additions & 1 deletion trunk/include/rdma/ib_user_mad.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,26 @@ struct ib_user_mad {
__u64 data[0];
};

/*
* Earlier versions of this interface definition declared the
* method_mask[] member as an array of __u32 but treated it as a
* bitmap made up of longs in the kernel. This ambiguity meant that
* 32-bit big-endian applications that can run on both 32-bit and
* 64-bit kernels had no consistent ABI to rely on, and 64-bit
* big-endian applications that treated method_mask as being made up
* of 32-bit words would have their bitmap misinterpreted.
*
* To clear up this confusion, we change the declaration of
* method_mask[] to use unsigned long and handle the conversion from
* 32-bit userspace to 64-bit kernel for big-endian systems in the
* compat_ioctl method. Unfortunately, to keep the structure layout
* the same, we need the method_mask[] array to be aligned only to 4
* bytes even when long is 64 bits, which forces us into this ugly
* typedef.
*/
typedef unsigned long __attribute__((aligned(4))) packed_ulong;
#define IB_USER_MAD_LONGS_PER_METHOD_MASK (128 / (8 * sizeof (long)))

/**
* ib_user_mad_reg_req - MAD registration request
* @id - Set by the kernel; used to identify agent in future requests.
Expand All @@ -165,7 +185,7 @@ struct ib_user_mad {
*/
struct ib_user_mad_reg_req {
__u32 id;
__u32 method_mask[4];
packed_ulong method_mask[IB_USER_MAD_LONGS_PER_METHOD_MASK];
__u8 qpn;
__u8 mgmt_class;
__u8 mgmt_class_version;
Expand Down

0 comments on commit f4a32c3

Please sign in to comment.