Skip to content

Commit

Permalink
RDS/IB: Improve RDS protocol version checking
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Grover authored and David S. Miller committed Jul 20, 2009
1 parent 3ba23ad commit 9ddbcfa
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions net/rds/ib_cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
struct ib_qp_attr qp_attr;
int err;

if (event->param.conn.private_data_len) {
if (event->param.conn.private_data_len >= sizeof(*dp)) {
dp = event->param.conn.private_data;

rds_ib_set_protocol(conn,
Expand Down Expand Up @@ -344,19 +344,32 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
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;
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
* original size. The only way to tell the difference is by looking at
* the contents, which are initialized to zero.
* 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.
* We really should have changed this for OFED 1.3 :-( */
if (dp->dp_protocol_major == 0)
* We really should have changed this for OFED 1.3 :-(
*/

/* 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;

common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS;
Expand Down Expand Up @@ -388,7 +401,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
int err, destroy = 1;

/* Check whether the remote protocol version matches ours. */
version = rds_ib_protocol_compatible(dp);
version = rds_ib_protocol_compatible(event);
if (!version)
goto out;

Expand Down

0 comments on commit 9ddbcfa

Please sign in to comment.