diff options
author | Andy Grover <andy.grover@oracle.com> | 2009-07-17 09:13:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-20 11:03:02 -0400 |
commit | 9ddbcfa098bae757d3760dd1dbf2847a0bd5a525 (patch) | |
tree | 256e6839ab22cdb0570f1f44d84631b898e0cfde /net/rds | |
parent | 3ba23ade464cca7c4a7ba5628c613339d3f2e161 (diff) |
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>
Diffstat (limited to 'net/rds')
-rw-r--r-- | net/rds/ib_cm.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 605c032ed5d5..0964ac533ec8 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -98,7 +98,7 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
98 | struct ib_qp_attr qp_attr; | 98 | struct ib_qp_attr qp_attr; |
99 | int err; | 99 | int err; |
100 | 100 | ||
101 | if (event->param.conn.private_data_len) { | 101 | if (event->param.conn.private_data_len >= sizeof(*dp)) { |
102 | dp = event->param.conn.private_data; | 102 | dp = event->param.conn.private_data; |
103 | 103 | ||
104 | rds_ib_set_protocol(conn, | 104 | rds_ib_set_protocol(conn, |
@@ -344,19 +344,32 @@ out: | |||
344 | return ret; | 344 | return ret; |
345 | } | 345 | } |
346 | 346 | ||
347 | static u32 rds_ib_protocol_compatible(const struct rds_ib_connect_private *dp) | 347 | static u32 rds_ib_protocol_compatible(struct rdma_cm_event *event) |
348 | { | 348 | { |
349 | const struct rds_ib_connect_private *dp = event->param.conn.private_data; | ||
349 | u16 common; | 350 | u16 common; |
350 | u32 version = 0; | 351 | u32 version = 0; |
351 | 352 | ||
352 | /* rdma_cm private data is odd - when there is any private data in the | 353 | /* |
354 | * rdma_cm private data is odd - when there is any private data in the | ||
353 | * request, we will be given a pretty large buffer without telling us the | 355 | * request, we will be given a pretty large buffer without telling us the |
354 | * original size. The only way to tell the difference is by looking at | 356 | * original size. The only way to tell the difference is by looking at |
355 | * the contents, which are initialized to zero. | 357 | * the contents, which are initialized to zero. |
356 | * If the protocol version fields aren't set, this is a connection attempt | 358 | * If the protocol version fields aren't set, this is a connection attempt |
357 | * from an older version. This could could be 3.0 or 2.0 - we can't tell. | 359 | * from an older version. This could could be 3.0 or 2.0 - we can't tell. |
358 | * We really should have changed this for OFED 1.3 :-( */ | 360 | * We really should have changed this for OFED 1.3 :-( |
359 | if (dp->dp_protocol_major == 0) | 361 | */ |
362 | |||
363 | /* Be paranoid. RDS always has privdata */ | ||
364 | if (!event->param.conn.private_data_len) { | ||
365 | printk(KERN_NOTICE "RDS incoming connection has no private data, " | ||
366 | "rejecting\n"); | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /* Even if len is crap *now* I still want to check it. -ASG */ | ||
371 | if (event->param.conn.private_data_len < sizeof (*dp) | ||
372 | || dp->dp_protocol_major == 0) | ||
360 | return RDS_PROTOCOL_3_0; | 373 | return RDS_PROTOCOL_3_0; |
361 | 374 | ||
362 | common = be16_to_cpu(dp->dp_protocol_minor_mask) & RDS_IB_SUPPORTED_PROTOCOLS; | 375 | 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, | |||
388 | int err, destroy = 1; | 401 | int err, destroy = 1; |
389 | 402 | ||
390 | /* Check whether the remote protocol version matches ours. */ | 403 | /* Check whether the remote protocol version matches ours. */ |
391 | version = rds_ib_protocol_compatible(dp); | 404 | version = rds_ib_protocol_compatible(event); |
392 | if (!version) | 405 | if (!version) |
393 | goto out; | 406 | goto out; |
394 | 407 | ||