forked from Minki/linux
RDS/IB: Improve RDS protocol version checking
RDS on IB uses privdata to do protocol version negotiation. Apparently the IB stack will return a larger privdata buffer than the struct we were expecting. Just to be extra-sure, this patch adds some checks in this area. Signed-off-by: Andy Grover <andy.grover@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
3ba23ade46
commit
9ddbcfa098
@ -98,7 +98,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
|
|||||||
struct ib_qp_attr qp_attr;
|
struct ib_qp_attr qp_attr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (event->param.conn.private_data_len) {
|
if (event->param.conn.private_data_len >= sizeof(*dp)) {
|
||||||
dp = event->param.conn.private_data;
|
dp = event->param.conn.private_data;
|
||||||
|
|
||||||
rds_ib_set_protocol(conn,
|
rds_ib_set_protocol(conn,
|
||||||
@ -344,19 +344,32 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 rds_ib_protocol_compatible(const struct rds_ib_connect_private *dp)
|
static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event)
|
||||||
{
|
{
|
||||||
|
const struct rds_ib_connect_private *dp = event->param.conn.private_data;
|
||||||
u16 common;
|
u16 common;
|
||||||
u32 version = 0;
|
u32 version = 0;
|
||||||
|
|
||||||
/* rdma_cm private data is odd - when there is any private data in the
|
/*
|
||||||
|
* rdma_cm private data is odd - when there is any private data in the
|
||||||
* request, we will be given a pretty large buffer without telling us the
|
* request, we will be given a pretty large buffer without telling us the
|
||||||
* original size. The only way to tell the difference is by looking at
|
* original size. The only way to tell the difference is by looking at
|
||||||
* the contents, which are initialized to zero.
|
* the contents, which are initialized to zero.
|
||||||
* If the protocol version fields aren't set, this is a connection attempt
|
* If the protocol version fields aren't set, this is a connection attempt
|
||||||
* from an older version. This could could be 3.0 or 2.0 - we can't tell.
|
* from an older version. This could could be 3.0 or 2.0 - we can't tell.
|
||||||
* We really should have changed this for OFED 1.3 :-( */
|
* We really should have changed this for OFED 1.3 :-(
|
||||||
if (dp->dp_protocol_major == 0)
|
*/
|
||||||
|
|
||||||
|
/* Be paranoid. RDS always has privdata */
|
||||||
|
if (!event->param.conn.private_data_len) {
|
||||||
|
printk(KERN_NOTICE "RDS incoming connection has no private data, "
|
||||||
|
"rejecting\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Even if len is crap *now* I still want to check it. -ASG */
|
||||||
|
if (event->param.conn.private_data_len < sizeof (*dp)
|
||||||
|
|| dp->dp_protocol_major == 0)
|
||||||
return RDS_PROTOCOL_3_0;
|
return RDS_PROTOCOL_3_0;
|
||||||
|
|
||||||
common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS;
|
common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS;
|
||||||
@ -388,7 +401,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
|
|||||||
int err, destroy = 1;
|
int err, destroy = 1;
|
||||||
|
|
||||||
/* Check whether the remote protocol version matches ours. */
|
/* Check whether the remote protocol version matches ours. */
|
||||||
version = rds_ib_protocol_compatible(dp);
|
version = rds_ib_protocol_compatible(event);
|
||||||
if (!version)
|
if (!version)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user