diff options
Diffstat (limited to 'drivers/infiniband/core/ucma.c')
-rw-r--r-- | drivers/infiniband/core/ucma.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index f015f1bf88c9..e5a1e7d81326 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -132,7 +132,7 @@ static inline struct ucma_context *_ucma_find_context(int id, | |||
132 | ctx = idr_find(&ctx_idr, id); | 132 | ctx = idr_find(&ctx_idr, id); |
133 | if (!ctx) | 133 | if (!ctx) |
134 | ctx = ERR_PTR(-ENOENT); | 134 | ctx = ERR_PTR(-ENOENT); |
135 | else if (ctx->file != file) | 135 | else if (ctx->file != file || !ctx->cm_id) |
136 | ctx = ERR_PTR(-EINVAL); | 136 | ctx = ERR_PTR(-EINVAL); |
137 | return ctx; | 137 | return ctx; |
138 | } | 138 | } |
@@ -456,6 +456,7 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, | |||
456 | struct rdma_ucm_create_id cmd; | 456 | struct rdma_ucm_create_id cmd; |
457 | struct rdma_ucm_create_id_resp resp; | 457 | struct rdma_ucm_create_id_resp resp; |
458 | struct ucma_context *ctx; | 458 | struct ucma_context *ctx; |
459 | struct rdma_cm_id *cm_id; | ||
459 | enum ib_qp_type qp_type; | 460 | enum ib_qp_type qp_type; |
460 | int ret; | 461 | int ret; |
461 | 462 | ||
@@ -476,10 +477,10 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, | |||
476 | return -ENOMEM; | 477 | return -ENOMEM; |
477 | 478 | ||
478 | ctx->uid = cmd.uid; | 479 | ctx->uid = cmd.uid; |
479 | ctx->cm_id = rdma_create_id(current->nsproxy->net_ns, | 480 | cm_id = rdma_create_id(current->nsproxy->net_ns, |
480 | ucma_event_handler, ctx, cmd.ps, qp_type); | 481 | ucma_event_handler, ctx, cmd.ps, qp_type); |
481 | if (IS_ERR(ctx->cm_id)) { | 482 | if (IS_ERR(cm_id)) { |
482 | ret = PTR_ERR(ctx->cm_id); | 483 | ret = PTR_ERR(cm_id); |
483 | goto err1; | 484 | goto err1; |
484 | } | 485 | } |
485 | 486 | ||
@@ -489,14 +490,19 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, | |||
489 | ret = -EFAULT; | 490 | ret = -EFAULT; |
490 | goto err2; | 491 | goto err2; |
491 | } | 492 | } |
493 | |||
494 | ctx->cm_id = cm_id; | ||
492 | return 0; | 495 | return 0; |
493 | 496 | ||
494 | err2: | 497 | err2: |
495 | rdma_destroy_id(ctx->cm_id); | 498 | rdma_destroy_id(cm_id); |
496 | err1: | 499 | err1: |
497 | mutex_lock(&mut); | 500 | mutex_lock(&mut); |
498 | idr_remove(&ctx_idr, ctx->id); | 501 | idr_remove(&ctx_idr, ctx->id); |
499 | mutex_unlock(&mut); | 502 | mutex_unlock(&mut); |
503 | mutex_lock(&file->mut); | ||
504 | list_del(&ctx->list); | ||
505 | mutex_unlock(&file->mut); | ||
500 | kfree(ctx); | 506 | kfree(ctx); |
501 | return ret; | 507 | return ret; |
502 | } | 508 | } |
@@ -664,19 +670,23 @@ static ssize_t ucma_resolve_ip(struct ucma_file *file, | |||
664 | int in_len, int out_len) | 670 | int in_len, int out_len) |
665 | { | 671 | { |
666 | struct rdma_ucm_resolve_ip cmd; | 672 | struct rdma_ucm_resolve_ip cmd; |
673 | struct sockaddr *src, *dst; | ||
667 | struct ucma_context *ctx; | 674 | struct ucma_context *ctx; |
668 | int ret; | 675 | int ret; |
669 | 676 | ||
670 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 677 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
671 | return -EFAULT; | 678 | return -EFAULT; |
672 | 679 | ||
680 | src = (struct sockaddr *) &cmd.src_addr; | ||
681 | dst = (struct sockaddr *) &cmd.dst_addr; | ||
682 | if (!rdma_addr_size(src) || !rdma_addr_size(dst)) | ||
683 | return -EINVAL; | ||
684 | |||
673 | ctx = ucma_get_ctx(file, cmd.id); | 685 | ctx = ucma_get_ctx(file, cmd.id); |
674 | if (IS_ERR(ctx)) | 686 | if (IS_ERR(ctx)) |
675 | return PTR_ERR(ctx); | 687 | return PTR_ERR(ctx); |
676 | 688 | ||
677 | ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr, | 689 | ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms); |
678 | (struct sockaddr *) &cmd.dst_addr, | ||
679 | cmd.timeout_ms); | ||
680 | ucma_put_ctx(ctx); | 690 | ucma_put_ctx(ctx); |
681 | return ret; | 691 | return ret; |
682 | } | 692 | } |
@@ -1149,6 +1159,9 @@ static ssize_t ucma_init_qp_attr(struct ucma_file *file, | |||
1149 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 1159 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
1150 | return -EFAULT; | 1160 | return -EFAULT; |
1151 | 1161 | ||
1162 | if (cmd.qp_state > IB_QPS_ERR) | ||
1163 | return -EINVAL; | ||
1164 | |||
1152 | ctx = ucma_get_ctx(file, cmd.id); | 1165 | ctx = ucma_get_ctx(file, cmd.id); |
1153 | if (IS_ERR(ctx)) | 1166 | if (IS_ERR(ctx)) |
1154 | return PTR_ERR(ctx); | 1167 | return PTR_ERR(ctx); |
@@ -1294,6 +1307,9 @@ static ssize_t ucma_set_option(struct ucma_file *file, const char __user *inbuf, | |||
1294 | if (IS_ERR(ctx)) | 1307 | if (IS_ERR(ctx)) |
1295 | return PTR_ERR(ctx); | 1308 | return PTR_ERR(ctx); |
1296 | 1309 | ||
1310 | if (unlikely(cmd.optval > KMALLOC_MAX_SIZE)) | ||
1311 | return -EINVAL; | ||
1312 | |||
1297 | optval = memdup_user((void __user *) (unsigned long) cmd.optval, | 1313 | optval = memdup_user((void __user *) (unsigned long) cmd.optval, |
1298 | cmd.optlen); | 1314 | cmd.optlen); |
1299 | if (IS_ERR(optval)) { | 1315 | if (IS_ERR(optval)) { |
@@ -1343,7 +1359,7 @@ static ssize_t ucma_process_join(struct ucma_file *file, | |||
1343 | return -ENOSPC; | 1359 | return -ENOSPC; |
1344 | 1360 | ||
1345 | addr = (struct sockaddr *) &cmd->addr; | 1361 | addr = (struct sockaddr *) &cmd->addr; |
1346 | if (!cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr))) | 1362 | if (cmd->addr_size != rdma_addr_size(addr)) |
1347 | return -EINVAL; | 1363 | return -EINVAL; |
1348 | 1364 | ||
1349 | if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER) | 1365 | if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER) |
@@ -1411,6 +1427,9 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file, | |||
1411 | join_cmd.uid = cmd.uid; | 1427 | join_cmd.uid = cmd.uid; |
1412 | join_cmd.id = cmd.id; | 1428 | join_cmd.id = cmd.id; |
1413 | join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); | 1429 | join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); |
1430 | if (!join_cmd.addr_size) | ||
1431 | return -EINVAL; | ||
1432 | |||
1414 | join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER; | 1433 | join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER; |
1415 | memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size); | 1434 | memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size); |
1416 | 1435 | ||
@@ -1426,6 +1445,9 @@ static ssize_t ucma_join_multicast(struct ucma_file *file, | |||
1426 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 1445 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
1427 | return -EFAULT; | 1446 | return -EFAULT; |
1428 | 1447 | ||
1448 | if (!rdma_addr_size((struct sockaddr *)&cmd.addr)) | ||
1449 | return -EINVAL; | ||
1450 | |||
1429 | return ucma_process_join(file, &cmd, out_len); | 1451 | return ucma_process_join(file, &cmd, out_len); |
1430 | } | 1452 | } |
1431 | 1453 | ||