0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/completion.h>
0034 #include <linux/file.h>
0035 #include <linux/mutex.h>
0036 #include <linux/poll.h>
0037 #include <linux/sched.h>
0038 #include <linux/idr.h>
0039 #include <linux/in.h>
0040 #include <linux/in6.h>
0041 #include <linux/miscdevice.h>
0042 #include <linux/slab.h>
0043 #include <linux/sysctl.h>
0044 #include <linux/module.h>
0045 #include <linux/nsproxy.h>
0046
0047 #include <linux/nospec.h>
0048
0049 #include <rdma/rdma_user_cm.h>
0050 #include <rdma/ib_marshall.h>
0051 #include <rdma/rdma_cm.h>
0052 #include <rdma/rdma_cm_ib.h>
0053 #include <rdma/ib_addr.h>
0054 #include <rdma/ib.h>
0055 #include <rdma/ib_cm.h>
0056 #include <rdma/rdma_netlink.h>
0057 #include "core_priv.h"
0058
0059 MODULE_AUTHOR("Sean Hefty");
0060 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
0061 MODULE_LICENSE("Dual BSD/GPL");
0062
0063 static unsigned int max_backlog = 1024;
0064
0065 static struct ctl_table_header *ucma_ctl_table_hdr;
0066 static struct ctl_table ucma_ctl_table[] = {
0067 {
0068 .procname = "max_backlog",
0069 .data = &max_backlog,
0070 .maxlen = sizeof max_backlog,
0071 .mode = 0644,
0072 .proc_handler = proc_dointvec,
0073 },
0074 { }
0075 };
0076
0077 struct ucma_file {
0078 struct mutex mut;
0079 struct file *filp;
0080 struct list_head ctx_list;
0081 struct list_head event_list;
0082 wait_queue_head_t poll_wait;
0083 };
0084
0085 struct ucma_context {
0086 u32 id;
0087 struct completion comp;
0088 refcount_t ref;
0089 int events_reported;
0090 atomic_t backlog;
0091
0092 struct ucma_file *file;
0093 struct rdma_cm_id *cm_id;
0094 struct mutex mutex;
0095 u64 uid;
0096
0097 struct list_head list;
0098 struct list_head mc_list;
0099 struct work_struct close_work;
0100 };
0101
0102 struct ucma_multicast {
0103 struct ucma_context *ctx;
0104 u32 id;
0105 int events_reported;
0106
0107 u64 uid;
0108 u8 join_state;
0109 struct list_head list;
0110 struct sockaddr_storage addr;
0111 };
0112
0113 struct ucma_event {
0114 struct ucma_context *ctx;
0115 struct ucma_context *conn_req_ctx;
0116 struct ucma_multicast *mc;
0117 struct list_head list;
0118 struct rdma_ucm_event_resp resp;
0119 };
0120
0121 static DEFINE_XARRAY_ALLOC(ctx_table);
0122 static DEFINE_XARRAY_ALLOC(multicast_table);
0123
0124 static const struct file_operations ucma_fops;
0125 static int ucma_destroy_private_ctx(struct ucma_context *ctx);
0126
0127 static inline struct ucma_context *_ucma_find_context(int id,
0128 struct ucma_file *file)
0129 {
0130 struct ucma_context *ctx;
0131
0132 ctx = xa_load(&ctx_table, id);
0133 if (!ctx)
0134 ctx = ERR_PTR(-ENOENT);
0135 else if (ctx->file != file)
0136 ctx = ERR_PTR(-EINVAL);
0137 return ctx;
0138 }
0139
0140 static struct ucma_context *ucma_get_ctx(struct ucma_file *file, int id)
0141 {
0142 struct ucma_context *ctx;
0143
0144 xa_lock(&ctx_table);
0145 ctx = _ucma_find_context(id, file);
0146 if (!IS_ERR(ctx))
0147 if (!refcount_inc_not_zero(&ctx->ref))
0148 ctx = ERR_PTR(-ENXIO);
0149 xa_unlock(&ctx_table);
0150 return ctx;
0151 }
0152
0153 static void ucma_put_ctx(struct ucma_context *ctx)
0154 {
0155 if (refcount_dec_and_test(&ctx->ref))
0156 complete(&ctx->comp);
0157 }
0158
0159
0160
0161
0162
0163 static struct ucma_context *ucma_get_ctx_dev(struct ucma_file *file, int id)
0164 {
0165 struct ucma_context *ctx = ucma_get_ctx(file, id);
0166
0167 if (IS_ERR(ctx))
0168 return ctx;
0169 if (!ctx->cm_id->device) {
0170 ucma_put_ctx(ctx);
0171 return ERR_PTR(-EINVAL);
0172 }
0173 return ctx;
0174 }
0175
0176 static void ucma_close_id(struct work_struct *work)
0177 {
0178 struct ucma_context *ctx = container_of(work, struct ucma_context, close_work);
0179
0180
0181
0182
0183
0184 ucma_put_ctx(ctx);
0185 wait_for_completion(&ctx->comp);
0186
0187 rdma_destroy_id(ctx->cm_id);
0188
0189
0190 ctx->cm_id = NULL;
0191 }
0192
0193 static struct ucma_context *ucma_alloc_ctx(struct ucma_file *file)
0194 {
0195 struct ucma_context *ctx;
0196
0197 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
0198 if (!ctx)
0199 return NULL;
0200
0201 INIT_WORK(&ctx->close_work, ucma_close_id);
0202 init_completion(&ctx->comp);
0203 INIT_LIST_HEAD(&ctx->mc_list);
0204
0205 INIT_LIST_HEAD(&ctx->list);
0206 ctx->file = file;
0207 mutex_init(&ctx->mutex);
0208
0209 if (xa_alloc(&ctx_table, &ctx->id, NULL, xa_limit_32b, GFP_KERNEL)) {
0210 kfree(ctx);
0211 return NULL;
0212 }
0213 return ctx;
0214 }
0215
0216 static void ucma_set_ctx_cm_id(struct ucma_context *ctx,
0217 struct rdma_cm_id *cm_id)
0218 {
0219 refcount_set(&ctx->ref, 1);
0220 ctx->cm_id = cm_id;
0221 }
0222
0223 static void ucma_finish_ctx(struct ucma_context *ctx)
0224 {
0225 lockdep_assert_held(&ctx->file->mut);
0226 list_add_tail(&ctx->list, &ctx->file->ctx_list);
0227 xa_store(&ctx_table, ctx->id, ctx, GFP_KERNEL);
0228 }
0229
0230 static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
0231 struct rdma_conn_param *src)
0232 {
0233 if (src->private_data_len)
0234 memcpy(dst->private_data, src->private_data,
0235 src->private_data_len);
0236 dst->private_data_len = src->private_data_len;
0237 dst->responder_resources = src->responder_resources;
0238 dst->initiator_depth = src->initiator_depth;
0239 dst->flow_control = src->flow_control;
0240 dst->retry_count = src->retry_count;
0241 dst->rnr_retry_count = src->rnr_retry_count;
0242 dst->srq = src->srq;
0243 dst->qp_num = src->qp_num;
0244 }
0245
0246 static void ucma_copy_ud_event(struct ib_device *device,
0247 struct rdma_ucm_ud_param *dst,
0248 struct rdma_ud_param *src)
0249 {
0250 if (src->private_data_len)
0251 memcpy(dst->private_data, src->private_data,
0252 src->private_data_len);
0253 dst->private_data_len = src->private_data_len;
0254 ib_copy_ah_attr_to_user(device, &dst->ah_attr, &src->ah_attr);
0255 dst->qp_num = src->qp_num;
0256 dst->qkey = src->qkey;
0257 }
0258
0259 static struct ucma_event *ucma_create_uevent(struct ucma_context *ctx,
0260 struct rdma_cm_event *event)
0261 {
0262 struct ucma_event *uevent;
0263
0264 uevent = kzalloc(sizeof(*uevent), GFP_KERNEL);
0265 if (!uevent)
0266 return NULL;
0267
0268 uevent->ctx = ctx;
0269 switch (event->event) {
0270 case RDMA_CM_EVENT_MULTICAST_JOIN:
0271 case RDMA_CM_EVENT_MULTICAST_ERROR:
0272 uevent->mc = (struct ucma_multicast *)
0273 event->param.ud.private_data;
0274 uevent->resp.uid = uevent->mc->uid;
0275 uevent->resp.id = uevent->mc->id;
0276 break;
0277 default:
0278 uevent->resp.uid = ctx->uid;
0279 uevent->resp.id = ctx->id;
0280 break;
0281 }
0282 uevent->resp.event = event->event;
0283 uevent->resp.status = event->status;
0284 if (ctx->cm_id->qp_type == IB_QPT_UD)
0285 ucma_copy_ud_event(ctx->cm_id->device, &uevent->resp.param.ud,
0286 &event->param.ud);
0287 else
0288 ucma_copy_conn_event(&uevent->resp.param.conn,
0289 &event->param.conn);
0290
0291 uevent->resp.ece.vendor_id = event->ece.vendor_id;
0292 uevent->resp.ece.attr_mod = event->ece.attr_mod;
0293 return uevent;
0294 }
0295
0296 static int ucma_connect_event_handler(struct rdma_cm_id *cm_id,
0297 struct rdma_cm_event *event)
0298 {
0299 struct ucma_context *listen_ctx = cm_id->context;
0300 struct ucma_context *ctx;
0301 struct ucma_event *uevent;
0302
0303 if (!atomic_add_unless(&listen_ctx->backlog, -1, 0))
0304 return -ENOMEM;
0305 ctx = ucma_alloc_ctx(listen_ctx->file);
0306 if (!ctx)
0307 goto err_backlog;
0308 ucma_set_ctx_cm_id(ctx, cm_id);
0309
0310 uevent = ucma_create_uevent(listen_ctx, event);
0311 if (!uevent)
0312 goto err_alloc;
0313 uevent->conn_req_ctx = ctx;
0314 uevent->resp.id = ctx->id;
0315
0316 ctx->cm_id->context = ctx;
0317
0318 mutex_lock(&ctx->file->mut);
0319 ucma_finish_ctx(ctx);
0320 list_add_tail(&uevent->list, &ctx->file->event_list);
0321 mutex_unlock(&ctx->file->mut);
0322 wake_up_interruptible(&ctx->file->poll_wait);
0323 return 0;
0324
0325 err_alloc:
0326 ucma_destroy_private_ctx(ctx);
0327 err_backlog:
0328 atomic_inc(&listen_ctx->backlog);
0329
0330 return -ENOMEM;
0331 }
0332
0333 static int ucma_event_handler(struct rdma_cm_id *cm_id,
0334 struct rdma_cm_event *event)
0335 {
0336 struct ucma_event *uevent;
0337 struct ucma_context *ctx = cm_id->context;
0338
0339 if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)
0340 return ucma_connect_event_handler(cm_id, event);
0341
0342
0343
0344
0345
0346
0347
0348
0349 if (ctx->uid) {
0350 uevent = ucma_create_uevent(ctx, event);
0351 if (!uevent)
0352 return 0;
0353
0354 mutex_lock(&ctx->file->mut);
0355 list_add_tail(&uevent->list, &ctx->file->event_list);
0356 mutex_unlock(&ctx->file->mut);
0357 wake_up_interruptible(&ctx->file->poll_wait);
0358 }
0359
0360 if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL) {
0361 xa_lock(&ctx_table);
0362 if (xa_load(&ctx_table, ctx->id) == ctx)
0363 queue_work(system_unbound_wq, &ctx->close_work);
0364 xa_unlock(&ctx_table);
0365 }
0366 return 0;
0367 }
0368
0369 static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
0370 int in_len, int out_len)
0371 {
0372 struct rdma_ucm_get_event cmd;
0373 struct ucma_event *uevent;
0374
0375
0376
0377
0378
0379 if (out_len < sizeof(uevent->resp) - sizeof(uevent->resp.reserved) -
0380 sizeof(uevent->resp.ece))
0381 return -ENOSPC;
0382
0383 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0384 return -EFAULT;
0385
0386 mutex_lock(&file->mut);
0387 while (list_empty(&file->event_list)) {
0388 mutex_unlock(&file->mut);
0389
0390 if (file->filp->f_flags & O_NONBLOCK)
0391 return -EAGAIN;
0392
0393 if (wait_event_interruptible(file->poll_wait,
0394 !list_empty(&file->event_list)))
0395 return -ERESTARTSYS;
0396
0397 mutex_lock(&file->mut);
0398 }
0399
0400 uevent = list_first_entry(&file->event_list, struct ucma_event, list);
0401
0402 if (copy_to_user(u64_to_user_ptr(cmd.response),
0403 &uevent->resp,
0404 min_t(size_t, out_len, sizeof(uevent->resp)))) {
0405 mutex_unlock(&file->mut);
0406 return -EFAULT;
0407 }
0408
0409 list_del(&uevent->list);
0410 uevent->ctx->events_reported++;
0411 if (uevent->mc)
0412 uevent->mc->events_reported++;
0413 if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST)
0414 atomic_inc(&uevent->ctx->backlog);
0415 mutex_unlock(&file->mut);
0416
0417 kfree(uevent);
0418 return 0;
0419 }
0420
0421 static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_type)
0422 {
0423 switch (cmd->ps) {
0424 case RDMA_PS_TCP:
0425 *qp_type = IB_QPT_RC;
0426 return 0;
0427 case RDMA_PS_UDP:
0428 case RDMA_PS_IPOIB:
0429 *qp_type = IB_QPT_UD;
0430 return 0;
0431 case RDMA_PS_IB:
0432 *qp_type = cmd->qp_type;
0433 return 0;
0434 default:
0435 return -EINVAL;
0436 }
0437 }
0438
0439 static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
0440 int in_len, int out_len)
0441 {
0442 struct rdma_ucm_create_id cmd;
0443 struct rdma_ucm_create_id_resp resp;
0444 struct ucma_context *ctx;
0445 struct rdma_cm_id *cm_id;
0446 enum ib_qp_type qp_type;
0447 int ret;
0448
0449 if (out_len < sizeof(resp))
0450 return -ENOSPC;
0451
0452 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0453 return -EFAULT;
0454
0455 ret = ucma_get_qp_type(&cmd, &qp_type);
0456 if (ret)
0457 return ret;
0458
0459 ctx = ucma_alloc_ctx(file);
0460 if (!ctx)
0461 return -ENOMEM;
0462
0463 ctx->uid = cmd.uid;
0464 cm_id = rdma_create_user_id(ucma_event_handler, ctx, cmd.ps, qp_type);
0465 if (IS_ERR(cm_id)) {
0466 ret = PTR_ERR(cm_id);
0467 goto err1;
0468 }
0469 ucma_set_ctx_cm_id(ctx, cm_id);
0470
0471 resp.id = ctx->id;
0472 if (copy_to_user(u64_to_user_ptr(cmd.response),
0473 &resp, sizeof(resp))) {
0474 ret = -EFAULT;
0475 goto err1;
0476 }
0477
0478 mutex_lock(&file->mut);
0479 ucma_finish_ctx(ctx);
0480 mutex_unlock(&file->mut);
0481 return 0;
0482
0483 err1:
0484 ucma_destroy_private_ctx(ctx);
0485 return ret;
0486 }
0487
0488 static void ucma_cleanup_multicast(struct ucma_context *ctx)
0489 {
0490 struct ucma_multicast *mc, *tmp;
0491
0492 xa_lock(&multicast_table);
0493 list_for_each_entry_safe(mc, tmp, &ctx->mc_list, list) {
0494 list_del(&mc->list);
0495
0496
0497
0498
0499 __xa_erase(&multicast_table, mc->id);
0500 kfree(mc);
0501 }
0502 xa_unlock(&multicast_table);
0503 }
0504
0505 static void ucma_cleanup_mc_events(struct ucma_multicast *mc)
0506 {
0507 struct ucma_event *uevent, *tmp;
0508
0509 rdma_lock_handler(mc->ctx->cm_id);
0510 mutex_lock(&mc->ctx->file->mut);
0511 list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
0512 if (uevent->mc != mc)
0513 continue;
0514
0515 list_del(&uevent->list);
0516 kfree(uevent);
0517 }
0518 mutex_unlock(&mc->ctx->file->mut);
0519 rdma_unlock_handler(mc->ctx->cm_id);
0520 }
0521
0522 static int ucma_cleanup_ctx_events(struct ucma_context *ctx)
0523 {
0524 int events_reported;
0525 struct ucma_event *uevent, *tmp;
0526 LIST_HEAD(list);
0527
0528
0529 mutex_lock(&ctx->file->mut);
0530 list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list) {
0531 if (uevent->ctx != ctx)
0532 continue;
0533
0534 if (uevent->resp.event == RDMA_CM_EVENT_CONNECT_REQUEST &&
0535 xa_cmpxchg(&ctx_table, uevent->conn_req_ctx->id,
0536 uevent->conn_req_ctx, XA_ZERO_ENTRY,
0537 GFP_KERNEL) == uevent->conn_req_ctx) {
0538 list_move_tail(&uevent->list, &list);
0539 continue;
0540 }
0541 list_del(&uevent->list);
0542 kfree(uevent);
0543 }
0544 list_del(&ctx->list);
0545 events_reported = ctx->events_reported;
0546 mutex_unlock(&ctx->file->mut);
0547
0548
0549
0550
0551
0552
0553 list_for_each_entry_safe(uevent, tmp, &list, list) {
0554 ucma_destroy_private_ctx(uevent->conn_req_ctx);
0555 kfree(uevent);
0556 }
0557 return events_reported;
0558 }
0559
0560
0561
0562
0563
0564
0565
0566 static int ucma_destroy_private_ctx(struct ucma_context *ctx)
0567 {
0568 int events_reported;
0569
0570
0571
0572
0573
0574
0575
0576
0577 cancel_work_sync(&ctx->close_work);
0578 if (refcount_read(&ctx->ref))
0579 ucma_close_id(&ctx->close_work);
0580
0581 events_reported = ucma_cleanup_ctx_events(ctx);
0582 ucma_cleanup_multicast(ctx);
0583
0584 WARN_ON(xa_cmpxchg(&ctx_table, ctx->id, XA_ZERO_ENTRY, NULL,
0585 GFP_KERNEL) != NULL);
0586 mutex_destroy(&ctx->mutex);
0587 kfree(ctx);
0588 return events_reported;
0589 }
0590
0591 static ssize_t ucma_destroy_id(struct ucma_file *file, const char __user *inbuf,
0592 int in_len, int out_len)
0593 {
0594 struct rdma_ucm_destroy_id cmd;
0595 struct rdma_ucm_destroy_id_resp resp;
0596 struct ucma_context *ctx;
0597 int ret = 0;
0598
0599 if (out_len < sizeof(resp))
0600 return -ENOSPC;
0601
0602 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0603 return -EFAULT;
0604
0605 xa_lock(&ctx_table);
0606 ctx = _ucma_find_context(cmd.id, file);
0607 if (!IS_ERR(ctx)) {
0608 if (__xa_cmpxchg(&ctx_table, ctx->id, ctx, XA_ZERO_ENTRY,
0609 GFP_KERNEL) != ctx)
0610 ctx = ERR_PTR(-ENOENT);
0611 }
0612 xa_unlock(&ctx_table);
0613
0614 if (IS_ERR(ctx))
0615 return PTR_ERR(ctx);
0616
0617 resp.events_reported = ucma_destroy_private_ctx(ctx);
0618 if (copy_to_user(u64_to_user_ptr(cmd.response),
0619 &resp, sizeof(resp)))
0620 ret = -EFAULT;
0621
0622 return ret;
0623 }
0624
0625 static ssize_t ucma_bind_ip(struct ucma_file *file, const char __user *inbuf,
0626 int in_len, int out_len)
0627 {
0628 struct rdma_ucm_bind_ip cmd;
0629 struct ucma_context *ctx;
0630 int ret;
0631
0632 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0633 return -EFAULT;
0634
0635 if (!rdma_addr_size_in6(&cmd.addr))
0636 return -EINVAL;
0637
0638 ctx = ucma_get_ctx(file, cmd.id);
0639 if (IS_ERR(ctx))
0640 return PTR_ERR(ctx);
0641
0642 mutex_lock(&ctx->mutex);
0643 ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
0644 mutex_unlock(&ctx->mutex);
0645
0646 ucma_put_ctx(ctx);
0647 return ret;
0648 }
0649
0650 static ssize_t ucma_bind(struct ucma_file *file, const char __user *inbuf,
0651 int in_len, int out_len)
0652 {
0653 struct rdma_ucm_bind cmd;
0654 struct ucma_context *ctx;
0655 int ret;
0656
0657 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0658 return -EFAULT;
0659
0660 if (cmd.reserved || !cmd.addr_size ||
0661 cmd.addr_size != rdma_addr_size_kss(&cmd.addr))
0662 return -EINVAL;
0663
0664 ctx = ucma_get_ctx(file, cmd.id);
0665 if (IS_ERR(ctx))
0666 return PTR_ERR(ctx);
0667
0668 mutex_lock(&ctx->mutex);
0669 ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
0670 mutex_unlock(&ctx->mutex);
0671 ucma_put_ctx(ctx);
0672 return ret;
0673 }
0674
0675 static ssize_t ucma_resolve_ip(struct ucma_file *file,
0676 const char __user *inbuf,
0677 int in_len, int out_len)
0678 {
0679 struct rdma_ucm_resolve_ip cmd;
0680 struct ucma_context *ctx;
0681 int ret;
0682
0683 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0684 return -EFAULT;
0685
0686 if ((cmd.src_addr.sin6_family && !rdma_addr_size_in6(&cmd.src_addr)) ||
0687 !rdma_addr_size_in6(&cmd.dst_addr))
0688 return -EINVAL;
0689
0690 ctx = ucma_get_ctx(file, cmd.id);
0691 if (IS_ERR(ctx))
0692 return PTR_ERR(ctx);
0693
0694 mutex_lock(&ctx->mutex);
0695 ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
0696 (struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
0697 mutex_unlock(&ctx->mutex);
0698 ucma_put_ctx(ctx);
0699 return ret;
0700 }
0701
0702 static ssize_t ucma_resolve_addr(struct ucma_file *file,
0703 const char __user *inbuf,
0704 int in_len, int out_len)
0705 {
0706 struct rdma_ucm_resolve_addr cmd;
0707 struct ucma_context *ctx;
0708 int ret;
0709
0710 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0711 return -EFAULT;
0712
0713 if (cmd.reserved ||
0714 (cmd.src_size && (cmd.src_size != rdma_addr_size_kss(&cmd.src_addr))) ||
0715 !cmd.dst_size || (cmd.dst_size != rdma_addr_size_kss(&cmd.dst_addr)))
0716 return -EINVAL;
0717
0718 ctx = ucma_get_ctx(file, cmd.id);
0719 if (IS_ERR(ctx))
0720 return PTR_ERR(ctx);
0721
0722 mutex_lock(&ctx->mutex);
0723 ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
0724 (struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
0725 mutex_unlock(&ctx->mutex);
0726 ucma_put_ctx(ctx);
0727 return ret;
0728 }
0729
0730 static ssize_t ucma_resolve_route(struct ucma_file *file,
0731 const char __user *inbuf,
0732 int in_len, int out_len)
0733 {
0734 struct rdma_ucm_resolve_route cmd;
0735 struct ucma_context *ctx;
0736 int ret;
0737
0738 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0739 return -EFAULT;
0740
0741 ctx = ucma_get_ctx_dev(file, cmd.id);
0742 if (IS_ERR(ctx))
0743 return PTR_ERR(ctx);
0744
0745 mutex_lock(&ctx->mutex);
0746 ret = rdma_resolve_route(ctx->cm_id, cmd.timeout_ms);
0747 mutex_unlock(&ctx->mutex);
0748 ucma_put_ctx(ctx);
0749 return ret;
0750 }
0751
0752 static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
0753 struct rdma_route *route)
0754 {
0755 struct rdma_dev_addr *dev_addr;
0756
0757 resp->num_paths = route->num_paths;
0758 switch (route->num_paths) {
0759 case 0:
0760 dev_addr = &route->addr.dev_addr;
0761 rdma_addr_get_dgid(dev_addr,
0762 (union ib_gid *) &resp->ib_route[0].dgid);
0763 rdma_addr_get_sgid(dev_addr,
0764 (union ib_gid *) &resp->ib_route[0].sgid);
0765 resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
0766 break;
0767 case 2:
0768 ib_copy_path_rec_to_user(&resp->ib_route[1],
0769 &route->path_rec[1]);
0770 fallthrough;
0771 case 1:
0772 ib_copy_path_rec_to_user(&resp->ib_route[0],
0773 &route->path_rec[0]);
0774 break;
0775 default:
0776 break;
0777 }
0778 }
0779
0780 static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
0781 struct rdma_route *route)
0782 {
0783
0784 resp->num_paths = route->num_paths;
0785 switch (route->num_paths) {
0786 case 0:
0787 rdma_ip2gid((struct sockaddr *)&route->addr.dst_addr,
0788 (union ib_gid *)&resp->ib_route[0].dgid);
0789 rdma_ip2gid((struct sockaddr *)&route->addr.src_addr,
0790 (union ib_gid *)&resp->ib_route[0].sgid);
0791 resp->ib_route[0].pkey = cpu_to_be16(0xffff);
0792 break;
0793 case 2:
0794 ib_copy_path_rec_to_user(&resp->ib_route[1],
0795 &route->path_rec[1]);
0796 fallthrough;
0797 case 1:
0798 ib_copy_path_rec_to_user(&resp->ib_route[0],
0799 &route->path_rec[0]);
0800 break;
0801 default:
0802 break;
0803 }
0804 }
0805
0806 static void ucma_copy_iw_route(struct rdma_ucm_query_route_resp *resp,
0807 struct rdma_route *route)
0808 {
0809 struct rdma_dev_addr *dev_addr;
0810
0811 dev_addr = &route->addr.dev_addr;
0812 rdma_addr_get_dgid(dev_addr, (union ib_gid *) &resp->ib_route[0].dgid);
0813 rdma_addr_get_sgid(dev_addr, (union ib_gid *) &resp->ib_route[0].sgid);
0814 }
0815
0816 static ssize_t ucma_query_route(struct ucma_file *file,
0817 const char __user *inbuf,
0818 int in_len, int out_len)
0819 {
0820 struct rdma_ucm_query cmd;
0821 struct rdma_ucm_query_route_resp resp;
0822 struct ucma_context *ctx;
0823 struct sockaddr *addr;
0824 int ret = 0;
0825
0826 if (out_len < offsetof(struct rdma_ucm_query_route_resp, ibdev_index))
0827 return -ENOSPC;
0828
0829 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
0830 return -EFAULT;
0831
0832 ctx = ucma_get_ctx(file, cmd.id);
0833 if (IS_ERR(ctx))
0834 return PTR_ERR(ctx);
0835
0836 mutex_lock(&ctx->mutex);
0837 memset(&resp, 0, sizeof resp);
0838 addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr;
0839 memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ?
0840 sizeof(struct sockaddr_in) :
0841 sizeof(struct sockaddr_in6));
0842 addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr;
0843 memcpy(&resp.dst_addr, addr, addr->sa_family == AF_INET ?
0844 sizeof(struct sockaddr_in) :
0845 sizeof(struct sockaddr_in6));
0846 if (!ctx->cm_id->device)
0847 goto out;
0848
0849 resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
0850 resp.ibdev_index = ctx->cm_id->device->index;
0851 resp.port_num = ctx->cm_id->port_num;
0852
0853 if (rdma_cap_ib_sa(ctx->cm_id->device, ctx->cm_id->port_num))
0854 ucma_copy_ib_route(&resp, &ctx->cm_id->route);
0855 else if (rdma_protocol_roce(ctx->cm_id->device, ctx->cm_id->port_num))
0856 ucma_copy_iboe_route(&resp, &ctx->cm_id->route);
0857 else if (rdma_protocol_iwarp(ctx->cm_id->device, ctx->cm_id->port_num))
0858 ucma_copy_iw_route(&resp, &ctx->cm_id->route);
0859
0860 out:
0861 mutex_unlock(&ctx->mutex);
0862 if (copy_to_user(u64_to_user_ptr(cmd.response), &resp,
0863 min_t(size_t, out_len, sizeof(resp))))
0864 ret = -EFAULT;
0865
0866 ucma_put_ctx(ctx);
0867 return ret;
0868 }
0869
0870 static void ucma_query_device_addr(struct rdma_cm_id *cm_id,
0871 struct rdma_ucm_query_addr_resp *resp)
0872 {
0873 if (!cm_id->device)
0874 return;
0875
0876 resp->node_guid = (__force __u64) cm_id->device->node_guid;
0877 resp->ibdev_index = cm_id->device->index;
0878 resp->port_num = cm_id->port_num;
0879 resp->pkey = (__force __u16) cpu_to_be16(
0880 ib_addr_get_pkey(&cm_id->route.addr.dev_addr));
0881 }
0882
0883 static ssize_t ucma_query_addr(struct ucma_context *ctx,
0884 void __user *response, int out_len)
0885 {
0886 struct rdma_ucm_query_addr_resp resp;
0887 struct sockaddr *addr;
0888 int ret = 0;
0889
0890 if (out_len < offsetof(struct rdma_ucm_query_addr_resp, ibdev_index))
0891 return -ENOSPC;
0892
0893 memset(&resp, 0, sizeof resp);
0894
0895 addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr;
0896 resp.src_size = rdma_addr_size(addr);
0897 memcpy(&resp.src_addr, addr, resp.src_size);
0898
0899 addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr;
0900 resp.dst_size = rdma_addr_size(addr);
0901 memcpy(&resp.dst_addr, addr, resp.dst_size);
0902
0903 ucma_query_device_addr(ctx->cm_id, &resp);
0904
0905 if (copy_to_user(response, &resp, min_t(size_t, out_len, sizeof(resp))))
0906 ret = -EFAULT;
0907
0908 return ret;
0909 }
0910
0911 static ssize_t ucma_query_path(struct ucma_context *ctx,
0912 void __user *response, int out_len)
0913 {
0914 struct rdma_ucm_query_path_resp *resp;
0915 int i, ret = 0;
0916
0917 if (out_len < sizeof(*resp))
0918 return -ENOSPC;
0919
0920 resp = kzalloc(out_len, GFP_KERNEL);
0921 if (!resp)
0922 return -ENOMEM;
0923
0924 resp->num_paths = ctx->cm_id->route.num_paths;
0925 for (i = 0, out_len -= sizeof(*resp);
0926 i < resp->num_paths && out_len > sizeof(struct ib_path_rec_data);
0927 i++, out_len -= sizeof(struct ib_path_rec_data)) {
0928 struct sa_path_rec *rec = &ctx->cm_id->route.path_rec[i];
0929
0930 resp->path_data[i].flags = IB_PATH_GMP | IB_PATH_PRIMARY |
0931 IB_PATH_BIDIRECTIONAL;
0932 if (rec->rec_type == SA_PATH_REC_TYPE_OPA) {
0933 struct sa_path_rec ib;
0934
0935 sa_convert_path_opa_to_ib(&ib, rec);
0936 ib_sa_pack_path(&ib, &resp->path_data[i].path_rec);
0937
0938 } else {
0939 ib_sa_pack_path(rec, &resp->path_data[i].path_rec);
0940 }
0941 }
0942
0943 if (copy_to_user(response, resp, struct_size(resp, path_data, i)))
0944 ret = -EFAULT;
0945
0946 kfree(resp);
0947 return ret;
0948 }
0949
0950 static ssize_t ucma_query_gid(struct ucma_context *ctx,
0951 void __user *response, int out_len)
0952 {
0953 struct rdma_ucm_query_addr_resp resp;
0954 struct sockaddr_ib *addr;
0955 int ret = 0;
0956
0957 if (out_len < offsetof(struct rdma_ucm_query_addr_resp, ibdev_index))
0958 return -ENOSPC;
0959
0960 memset(&resp, 0, sizeof resp);
0961
0962 ucma_query_device_addr(ctx->cm_id, &resp);
0963
0964 addr = (struct sockaddr_ib *) &resp.src_addr;
0965 resp.src_size = sizeof(*addr);
0966 if (ctx->cm_id->route.addr.src_addr.ss_family == AF_IB) {
0967 memcpy(addr, &ctx->cm_id->route.addr.src_addr, resp.src_size);
0968 } else {
0969 addr->sib_family = AF_IB;
0970 addr->sib_pkey = (__force __be16) resp.pkey;
0971 rdma_read_gids(ctx->cm_id, (union ib_gid *)&addr->sib_addr,
0972 NULL);
0973 addr->sib_sid = rdma_get_service_id(ctx->cm_id, (struct sockaddr *)
0974 &ctx->cm_id->route.addr.src_addr);
0975 }
0976
0977 addr = (struct sockaddr_ib *) &resp.dst_addr;
0978 resp.dst_size = sizeof(*addr);
0979 if (ctx->cm_id->route.addr.dst_addr.ss_family == AF_IB) {
0980 memcpy(addr, &ctx->cm_id->route.addr.dst_addr, resp.dst_size);
0981 } else {
0982 addr->sib_family = AF_IB;
0983 addr->sib_pkey = (__force __be16) resp.pkey;
0984 rdma_read_gids(ctx->cm_id, NULL,
0985 (union ib_gid *)&addr->sib_addr);
0986 addr->sib_sid = rdma_get_service_id(ctx->cm_id, (struct sockaddr *)
0987 &ctx->cm_id->route.addr.dst_addr);
0988 }
0989
0990 if (copy_to_user(response, &resp, min_t(size_t, out_len, sizeof(resp))))
0991 ret = -EFAULT;
0992
0993 return ret;
0994 }
0995
0996 static ssize_t ucma_query(struct ucma_file *file,
0997 const char __user *inbuf,
0998 int in_len, int out_len)
0999 {
1000 struct rdma_ucm_query cmd;
1001 struct ucma_context *ctx;
1002 void __user *response;
1003 int ret;
1004
1005 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1006 return -EFAULT;
1007
1008 response = u64_to_user_ptr(cmd.response);
1009 ctx = ucma_get_ctx(file, cmd.id);
1010 if (IS_ERR(ctx))
1011 return PTR_ERR(ctx);
1012
1013 mutex_lock(&ctx->mutex);
1014 switch (cmd.option) {
1015 case RDMA_USER_CM_QUERY_ADDR:
1016 ret = ucma_query_addr(ctx, response, out_len);
1017 break;
1018 case RDMA_USER_CM_QUERY_PATH:
1019 ret = ucma_query_path(ctx, response, out_len);
1020 break;
1021 case RDMA_USER_CM_QUERY_GID:
1022 ret = ucma_query_gid(ctx, response, out_len);
1023 break;
1024 default:
1025 ret = -ENOSYS;
1026 break;
1027 }
1028 mutex_unlock(&ctx->mutex);
1029
1030 ucma_put_ctx(ctx);
1031 return ret;
1032 }
1033
1034 static void ucma_copy_conn_param(struct rdma_cm_id *id,
1035 struct rdma_conn_param *dst,
1036 struct rdma_ucm_conn_param *src)
1037 {
1038 dst->private_data = src->private_data;
1039 dst->private_data_len = src->private_data_len;
1040 dst->responder_resources = src->responder_resources;
1041 dst->initiator_depth = src->initiator_depth;
1042 dst->flow_control = src->flow_control;
1043 dst->retry_count = src->retry_count;
1044 dst->rnr_retry_count = src->rnr_retry_count;
1045 dst->srq = src->srq;
1046 dst->qp_num = src->qp_num & 0xFFFFFF;
1047 dst->qkey = (id->route.addr.src_addr.ss_family == AF_IB) ? src->qkey : 0;
1048 }
1049
1050 static ssize_t ucma_connect(struct ucma_file *file, const char __user *inbuf,
1051 int in_len, int out_len)
1052 {
1053 struct rdma_conn_param conn_param;
1054 struct rdma_ucm_ece ece = {};
1055 struct rdma_ucm_connect cmd;
1056 struct ucma_context *ctx;
1057 size_t in_size;
1058 int ret;
1059
1060 if (in_len < offsetofend(typeof(cmd), reserved))
1061 return -EINVAL;
1062 in_size = min_t(size_t, in_len, sizeof(cmd));
1063 if (copy_from_user(&cmd, inbuf, in_size))
1064 return -EFAULT;
1065
1066 if (!cmd.conn_param.valid)
1067 return -EINVAL;
1068
1069 ctx = ucma_get_ctx_dev(file, cmd.id);
1070 if (IS_ERR(ctx))
1071 return PTR_ERR(ctx);
1072
1073 ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param);
1074 if (offsetofend(typeof(cmd), ece) <= in_size) {
1075 ece.vendor_id = cmd.ece.vendor_id;
1076 ece.attr_mod = cmd.ece.attr_mod;
1077 }
1078
1079 mutex_lock(&ctx->mutex);
1080 ret = rdma_connect_ece(ctx->cm_id, &conn_param, &ece);
1081 mutex_unlock(&ctx->mutex);
1082 ucma_put_ctx(ctx);
1083 return ret;
1084 }
1085
1086 static ssize_t ucma_listen(struct ucma_file *file, const char __user *inbuf,
1087 int in_len, int out_len)
1088 {
1089 struct rdma_ucm_listen cmd;
1090 struct ucma_context *ctx;
1091 int ret;
1092
1093 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1094 return -EFAULT;
1095
1096 ctx = ucma_get_ctx(file, cmd.id);
1097 if (IS_ERR(ctx))
1098 return PTR_ERR(ctx);
1099
1100 if (cmd.backlog <= 0 || cmd.backlog > max_backlog)
1101 cmd.backlog = max_backlog;
1102 atomic_set(&ctx->backlog, cmd.backlog);
1103
1104 mutex_lock(&ctx->mutex);
1105 ret = rdma_listen(ctx->cm_id, cmd.backlog);
1106 mutex_unlock(&ctx->mutex);
1107 ucma_put_ctx(ctx);
1108 return ret;
1109 }
1110
1111 static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,
1112 int in_len, int out_len)
1113 {
1114 struct rdma_ucm_accept cmd;
1115 struct rdma_conn_param conn_param;
1116 struct rdma_ucm_ece ece = {};
1117 struct ucma_context *ctx;
1118 size_t in_size;
1119 int ret;
1120
1121 if (in_len < offsetofend(typeof(cmd), reserved))
1122 return -EINVAL;
1123 in_size = min_t(size_t, in_len, sizeof(cmd));
1124 if (copy_from_user(&cmd, inbuf, in_size))
1125 return -EFAULT;
1126
1127 ctx = ucma_get_ctx_dev(file, cmd.id);
1128 if (IS_ERR(ctx))
1129 return PTR_ERR(ctx);
1130
1131 if (offsetofend(typeof(cmd), ece) <= in_size) {
1132 ece.vendor_id = cmd.ece.vendor_id;
1133 ece.attr_mod = cmd.ece.attr_mod;
1134 }
1135
1136 if (cmd.conn_param.valid) {
1137 ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param);
1138 mutex_lock(&ctx->mutex);
1139 rdma_lock_handler(ctx->cm_id);
1140 ret = rdma_accept_ece(ctx->cm_id, &conn_param, &ece);
1141 if (!ret) {
1142
1143 ctx->uid = cmd.uid;
1144 }
1145 rdma_unlock_handler(ctx->cm_id);
1146 mutex_unlock(&ctx->mutex);
1147 } else {
1148 mutex_lock(&ctx->mutex);
1149 rdma_lock_handler(ctx->cm_id);
1150 ret = rdma_accept_ece(ctx->cm_id, NULL, &ece);
1151 rdma_unlock_handler(ctx->cm_id);
1152 mutex_unlock(&ctx->mutex);
1153 }
1154 ucma_put_ctx(ctx);
1155 return ret;
1156 }
1157
1158 static ssize_t ucma_reject(struct ucma_file *file, const char __user *inbuf,
1159 int in_len, int out_len)
1160 {
1161 struct rdma_ucm_reject cmd;
1162 struct ucma_context *ctx;
1163 int ret;
1164
1165 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1166 return -EFAULT;
1167
1168 if (!cmd.reason)
1169 cmd.reason = IB_CM_REJ_CONSUMER_DEFINED;
1170
1171 switch (cmd.reason) {
1172 case IB_CM_REJ_CONSUMER_DEFINED:
1173 case IB_CM_REJ_VENDOR_OPTION_NOT_SUPPORTED:
1174 break;
1175 default:
1176 return -EINVAL;
1177 }
1178
1179 ctx = ucma_get_ctx_dev(file, cmd.id);
1180 if (IS_ERR(ctx))
1181 return PTR_ERR(ctx);
1182
1183 mutex_lock(&ctx->mutex);
1184 ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len,
1185 cmd.reason);
1186 mutex_unlock(&ctx->mutex);
1187 ucma_put_ctx(ctx);
1188 return ret;
1189 }
1190
1191 static ssize_t ucma_disconnect(struct ucma_file *file, const char __user *inbuf,
1192 int in_len, int out_len)
1193 {
1194 struct rdma_ucm_disconnect cmd;
1195 struct ucma_context *ctx;
1196 int ret;
1197
1198 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1199 return -EFAULT;
1200
1201 ctx = ucma_get_ctx_dev(file, cmd.id);
1202 if (IS_ERR(ctx))
1203 return PTR_ERR(ctx);
1204
1205 mutex_lock(&ctx->mutex);
1206 ret = rdma_disconnect(ctx->cm_id);
1207 mutex_unlock(&ctx->mutex);
1208 ucma_put_ctx(ctx);
1209 return ret;
1210 }
1211
1212 static ssize_t ucma_init_qp_attr(struct ucma_file *file,
1213 const char __user *inbuf,
1214 int in_len, int out_len)
1215 {
1216 struct rdma_ucm_init_qp_attr cmd;
1217 struct ib_uverbs_qp_attr resp;
1218 struct ucma_context *ctx;
1219 struct ib_qp_attr qp_attr;
1220 int ret;
1221
1222 if (out_len < sizeof(resp))
1223 return -ENOSPC;
1224
1225 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1226 return -EFAULT;
1227
1228 if (cmd.qp_state > IB_QPS_ERR)
1229 return -EINVAL;
1230
1231 ctx = ucma_get_ctx_dev(file, cmd.id);
1232 if (IS_ERR(ctx))
1233 return PTR_ERR(ctx);
1234
1235 resp.qp_attr_mask = 0;
1236 memset(&qp_attr, 0, sizeof qp_attr);
1237 qp_attr.qp_state = cmd.qp_state;
1238 mutex_lock(&ctx->mutex);
1239 ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
1240 mutex_unlock(&ctx->mutex);
1241 if (ret)
1242 goto out;
1243
1244 ib_copy_qp_attr_to_user(ctx->cm_id->device, &resp, &qp_attr);
1245 if (copy_to_user(u64_to_user_ptr(cmd.response),
1246 &resp, sizeof(resp)))
1247 ret = -EFAULT;
1248
1249 out:
1250 ucma_put_ctx(ctx);
1251 return ret;
1252 }
1253
1254 static int ucma_set_option_id(struct ucma_context *ctx, int optname,
1255 void *optval, size_t optlen)
1256 {
1257 int ret = 0;
1258
1259 switch (optname) {
1260 case RDMA_OPTION_ID_TOS:
1261 if (optlen != sizeof(u8)) {
1262 ret = -EINVAL;
1263 break;
1264 }
1265 rdma_set_service_type(ctx->cm_id, *((u8 *) optval));
1266 break;
1267 case RDMA_OPTION_ID_REUSEADDR:
1268 if (optlen != sizeof(int)) {
1269 ret = -EINVAL;
1270 break;
1271 }
1272 ret = rdma_set_reuseaddr(ctx->cm_id, *((int *) optval) ? 1 : 0);
1273 break;
1274 case RDMA_OPTION_ID_AFONLY:
1275 if (optlen != sizeof(int)) {
1276 ret = -EINVAL;
1277 break;
1278 }
1279 ret = rdma_set_afonly(ctx->cm_id, *((int *) optval) ? 1 : 0);
1280 break;
1281 case RDMA_OPTION_ID_ACK_TIMEOUT:
1282 if (optlen != sizeof(u8)) {
1283 ret = -EINVAL;
1284 break;
1285 }
1286 ret = rdma_set_ack_timeout(ctx->cm_id, *((u8 *)optval));
1287 break;
1288 default:
1289 ret = -ENOSYS;
1290 }
1291
1292 return ret;
1293 }
1294
1295 static int ucma_set_ib_path(struct ucma_context *ctx,
1296 struct ib_path_rec_data *path_data, size_t optlen)
1297 {
1298 struct sa_path_rec sa_path;
1299 struct rdma_cm_event event;
1300 int ret;
1301
1302 if (optlen % sizeof(*path_data))
1303 return -EINVAL;
1304
1305 for (; optlen; optlen -= sizeof(*path_data), path_data++) {
1306 if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY |
1307 IB_PATH_BIDIRECTIONAL))
1308 break;
1309 }
1310
1311 if (!optlen)
1312 return -EINVAL;
1313
1314 if (!ctx->cm_id->device)
1315 return -EINVAL;
1316
1317 memset(&sa_path, 0, sizeof(sa_path));
1318
1319 sa_path.rec_type = SA_PATH_REC_TYPE_IB;
1320 ib_sa_unpack_path(path_data->path_rec, &sa_path);
1321
1322 if (rdma_cap_opa_ah(ctx->cm_id->device, ctx->cm_id->port_num)) {
1323 struct sa_path_rec opa;
1324
1325 sa_convert_path_ib_to_opa(&opa, &sa_path);
1326 mutex_lock(&ctx->mutex);
1327 ret = rdma_set_ib_path(ctx->cm_id, &opa);
1328 mutex_unlock(&ctx->mutex);
1329 } else {
1330 mutex_lock(&ctx->mutex);
1331 ret = rdma_set_ib_path(ctx->cm_id, &sa_path);
1332 mutex_unlock(&ctx->mutex);
1333 }
1334 if (ret)
1335 return ret;
1336
1337 memset(&event, 0, sizeof event);
1338 event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
1339 return ucma_event_handler(ctx->cm_id, &event);
1340 }
1341
1342 static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
1343 void *optval, size_t optlen)
1344 {
1345 int ret;
1346
1347 switch (optname) {
1348 case RDMA_OPTION_IB_PATH:
1349 ret = ucma_set_ib_path(ctx, optval, optlen);
1350 break;
1351 default:
1352 ret = -ENOSYS;
1353 }
1354
1355 return ret;
1356 }
1357
1358 static int ucma_set_option_level(struct ucma_context *ctx, int level,
1359 int optname, void *optval, size_t optlen)
1360 {
1361 int ret;
1362
1363 switch (level) {
1364 case RDMA_OPTION_ID:
1365 mutex_lock(&ctx->mutex);
1366 ret = ucma_set_option_id(ctx, optname, optval, optlen);
1367 mutex_unlock(&ctx->mutex);
1368 break;
1369 case RDMA_OPTION_IB:
1370 ret = ucma_set_option_ib(ctx, optname, optval, optlen);
1371 break;
1372 default:
1373 ret = -ENOSYS;
1374 }
1375
1376 return ret;
1377 }
1378
1379 static ssize_t ucma_set_option(struct ucma_file *file, const char __user *inbuf,
1380 int in_len, int out_len)
1381 {
1382 struct rdma_ucm_set_option cmd;
1383 struct ucma_context *ctx;
1384 void *optval;
1385 int ret;
1386
1387 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1388 return -EFAULT;
1389
1390 if (unlikely(cmd.optlen > KMALLOC_MAX_SIZE))
1391 return -EINVAL;
1392
1393 ctx = ucma_get_ctx(file, cmd.id);
1394 if (IS_ERR(ctx))
1395 return PTR_ERR(ctx);
1396
1397 optval = memdup_user(u64_to_user_ptr(cmd.optval),
1398 cmd.optlen);
1399 if (IS_ERR(optval)) {
1400 ret = PTR_ERR(optval);
1401 goto out;
1402 }
1403
1404 ret = ucma_set_option_level(ctx, cmd.level, cmd.optname, optval,
1405 cmd.optlen);
1406 kfree(optval);
1407
1408 out:
1409 ucma_put_ctx(ctx);
1410 return ret;
1411 }
1412
1413 static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
1414 int in_len, int out_len)
1415 {
1416 struct rdma_ucm_notify cmd;
1417 struct ucma_context *ctx;
1418 int ret = -EINVAL;
1419
1420 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1421 return -EFAULT;
1422
1423 ctx = ucma_get_ctx(file, cmd.id);
1424 if (IS_ERR(ctx))
1425 return PTR_ERR(ctx);
1426
1427 mutex_lock(&ctx->mutex);
1428 if (ctx->cm_id->device)
1429 ret = rdma_notify(ctx->cm_id, (enum ib_event_type)cmd.event);
1430 mutex_unlock(&ctx->mutex);
1431
1432 ucma_put_ctx(ctx);
1433 return ret;
1434 }
1435
1436 static ssize_t ucma_process_join(struct ucma_file *file,
1437 struct rdma_ucm_join_mcast *cmd, int out_len)
1438 {
1439 struct rdma_ucm_create_id_resp resp;
1440 struct ucma_context *ctx;
1441 struct ucma_multicast *mc;
1442 struct sockaddr *addr;
1443 int ret;
1444 u8 join_state;
1445
1446 if (out_len < sizeof(resp))
1447 return -ENOSPC;
1448
1449 addr = (struct sockaddr *) &cmd->addr;
1450 if (cmd->addr_size != rdma_addr_size(addr))
1451 return -EINVAL;
1452
1453 if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER)
1454 join_state = BIT(FULLMEMBER_JOIN);
1455 else if (cmd->join_flags == RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER)
1456 join_state = BIT(SENDONLY_FULLMEMBER_JOIN);
1457 else
1458 return -EINVAL;
1459
1460 ctx = ucma_get_ctx_dev(file, cmd->id);
1461 if (IS_ERR(ctx))
1462 return PTR_ERR(ctx);
1463
1464 mc = kzalloc(sizeof(*mc), GFP_KERNEL);
1465 if (!mc) {
1466 ret = -ENOMEM;
1467 goto err_put_ctx;
1468 }
1469
1470 mc->ctx = ctx;
1471 mc->join_state = join_state;
1472 mc->uid = cmd->uid;
1473 memcpy(&mc->addr, addr, cmd->addr_size);
1474
1475 xa_lock(&multicast_table);
1476 if (__xa_alloc(&multicast_table, &mc->id, NULL, xa_limit_32b,
1477 GFP_KERNEL)) {
1478 ret = -ENOMEM;
1479 goto err_free_mc;
1480 }
1481
1482 list_add_tail(&mc->list, &ctx->mc_list);
1483 xa_unlock(&multicast_table);
1484
1485 mutex_lock(&ctx->mutex);
1486 ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr,
1487 join_state, mc);
1488 mutex_unlock(&ctx->mutex);
1489 if (ret)
1490 goto err_xa_erase;
1491
1492 resp.id = mc->id;
1493 if (copy_to_user(u64_to_user_ptr(cmd->response),
1494 &resp, sizeof(resp))) {
1495 ret = -EFAULT;
1496 goto err_leave_multicast;
1497 }
1498
1499 xa_store(&multicast_table, mc->id, mc, 0);
1500
1501 ucma_put_ctx(ctx);
1502 return 0;
1503
1504 err_leave_multicast:
1505 mutex_lock(&ctx->mutex);
1506 rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
1507 mutex_unlock(&ctx->mutex);
1508 ucma_cleanup_mc_events(mc);
1509 err_xa_erase:
1510 xa_lock(&multicast_table);
1511 list_del(&mc->list);
1512 __xa_erase(&multicast_table, mc->id);
1513 err_free_mc:
1514 xa_unlock(&multicast_table);
1515 kfree(mc);
1516 err_put_ctx:
1517 ucma_put_ctx(ctx);
1518 return ret;
1519 }
1520
1521 static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
1522 const char __user *inbuf,
1523 int in_len, int out_len)
1524 {
1525 struct rdma_ucm_join_ip_mcast cmd;
1526 struct rdma_ucm_join_mcast join_cmd;
1527
1528 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1529 return -EFAULT;
1530
1531 join_cmd.response = cmd.response;
1532 join_cmd.uid = cmd.uid;
1533 join_cmd.id = cmd.id;
1534 join_cmd.addr_size = rdma_addr_size_in6(&cmd.addr);
1535 if (!join_cmd.addr_size)
1536 return -EINVAL;
1537
1538 join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER;
1539 memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);
1540
1541 return ucma_process_join(file, &join_cmd, out_len);
1542 }
1543
1544 static ssize_t ucma_join_multicast(struct ucma_file *file,
1545 const char __user *inbuf,
1546 int in_len, int out_len)
1547 {
1548 struct rdma_ucm_join_mcast cmd;
1549
1550 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1551 return -EFAULT;
1552
1553 if (!rdma_addr_size_kss(&cmd.addr))
1554 return -EINVAL;
1555
1556 return ucma_process_join(file, &cmd, out_len);
1557 }
1558
1559 static ssize_t ucma_leave_multicast(struct ucma_file *file,
1560 const char __user *inbuf,
1561 int in_len, int out_len)
1562 {
1563 struct rdma_ucm_destroy_id cmd;
1564 struct rdma_ucm_destroy_id_resp resp;
1565 struct ucma_multicast *mc;
1566 int ret = 0;
1567
1568 if (out_len < sizeof(resp))
1569 return -ENOSPC;
1570
1571 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1572 return -EFAULT;
1573
1574 xa_lock(&multicast_table);
1575 mc = xa_load(&multicast_table, cmd.id);
1576 if (!mc)
1577 mc = ERR_PTR(-ENOENT);
1578 else if (READ_ONCE(mc->ctx->file) != file)
1579 mc = ERR_PTR(-EINVAL);
1580 else if (!refcount_inc_not_zero(&mc->ctx->ref))
1581 mc = ERR_PTR(-ENXIO);
1582
1583 if (IS_ERR(mc)) {
1584 xa_unlock(&multicast_table);
1585 ret = PTR_ERR(mc);
1586 goto out;
1587 }
1588
1589 list_del(&mc->list);
1590 __xa_erase(&multicast_table, mc->id);
1591 xa_unlock(&multicast_table);
1592
1593 mutex_lock(&mc->ctx->mutex);
1594 rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr);
1595 mutex_unlock(&mc->ctx->mutex);
1596
1597 ucma_cleanup_mc_events(mc);
1598
1599 ucma_put_ctx(mc->ctx);
1600 resp.events_reported = mc->events_reported;
1601 kfree(mc);
1602
1603 if (copy_to_user(u64_to_user_ptr(cmd.response),
1604 &resp, sizeof(resp)))
1605 ret = -EFAULT;
1606 out:
1607 return ret;
1608 }
1609
1610 static ssize_t ucma_migrate_id(struct ucma_file *new_file,
1611 const char __user *inbuf,
1612 int in_len, int out_len)
1613 {
1614 struct rdma_ucm_migrate_id cmd;
1615 struct rdma_ucm_migrate_resp resp;
1616 struct ucma_event *uevent, *tmp;
1617 struct ucma_context *ctx;
1618 LIST_HEAD(event_list);
1619 struct fd f;
1620 struct ucma_file *cur_file;
1621 int ret = 0;
1622
1623 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1624 return -EFAULT;
1625
1626
1627 f = fdget(cmd.fd);
1628 if (!f.file)
1629 return -ENOENT;
1630 if (f.file->f_op != &ucma_fops) {
1631 ret = -EINVAL;
1632 goto file_put;
1633 }
1634 cur_file = f.file->private_data;
1635
1636
1637 ctx = ucma_get_ctx(cur_file, cmd.id);
1638 if (IS_ERR(ctx)) {
1639 ret = PTR_ERR(ctx);
1640 goto file_put;
1641 }
1642
1643 rdma_lock_handler(ctx->cm_id);
1644
1645
1646
1647
1648
1649 xa_lock(&ctx_table);
1650 if (_ucma_find_context(cmd.id, cur_file) != ctx) {
1651 xa_unlock(&ctx_table);
1652 ret = -ENOENT;
1653 goto err_unlock;
1654 }
1655 ctx->file = new_file;
1656 xa_unlock(&ctx_table);
1657
1658 mutex_lock(&cur_file->mut);
1659 list_del(&ctx->list);
1660
1661
1662
1663
1664 list_for_each_entry_safe(uevent, tmp, &cur_file->event_list, list)
1665 if (uevent->ctx == ctx)
1666 list_move_tail(&uevent->list, &event_list);
1667 resp.events_reported = ctx->events_reported;
1668 mutex_unlock(&cur_file->mut);
1669
1670 mutex_lock(&new_file->mut);
1671 list_add_tail(&ctx->list, &new_file->ctx_list);
1672 list_splice_tail(&event_list, &new_file->event_list);
1673 mutex_unlock(&new_file->mut);
1674
1675 if (copy_to_user(u64_to_user_ptr(cmd.response),
1676 &resp, sizeof(resp)))
1677 ret = -EFAULT;
1678
1679 err_unlock:
1680 rdma_unlock_handler(ctx->cm_id);
1681 ucma_put_ctx(ctx);
1682 file_put:
1683 fdput(f);
1684 return ret;
1685 }
1686
1687 static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
1688 const char __user *inbuf,
1689 int in_len, int out_len) = {
1690 [RDMA_USER_CM_CMD_CREATE_ID] = ucma_create_id,
1691 [RDMA_USER_CM_CMD_DESTROY_ID] = ucma_destroy_id,
1692 [RDMA_USER_CM_CMD_BIND_IP] = ucma_bind_ip,
1693 [RDMA_USER_CM_CMD_RESOLVE_IP] = ucma_resolve_ip,
1694 [RDMA_USER_CM_CMD_RESOLVE_ROUTE] = ucma_resolve_route,
1695 [RDMA_USER_CM_CMD_QUERY_ROUTE] = ucma_query_route,
1696 [RDMA_USER_CM_CMD_CONNECT] = ucma_connect,
1697 [RDMA_USER_CM_CMD_LISTEN] = ucma_listen,
1698 [RDMA_USER_CM_CMD_ACCEPT] = ucma_accept,
1699 [RDMA_USER_CM_CMD_REJECT] = ucma_reject,
1700 [RDMA_USER_CM_CMD_DISCONNECT] = ucma_disconnect,
1701 [RDMA_USER_CM_CMD_INIT_QP_ATTR] = ucma_init_qp_attr,
1702 [RDMA_USER_CM_CMD_GET_EVENT] = ucma_get_event,
1703 [RDMA_USER_CM_CMD_GET_OPTION] = NULL,
1704 [RDMA_USER_CM_CMD_SET_OPTION] = ucma_set_option,
1705 [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify,
1706 [RDMA_USER_CM_CMD_JOIN_IP_MCAST] = ucma_join_ip_multicast,
1707 [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast,
1708 [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id,
1709 [RDMA_USER_CM_CMD_QUERY] = ucma_query,
1710 [RDMA_USER_CM_CMD_BIND] = ucma_bind,
1711 [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
1712 [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast
1713 };
1714
1715 static ssize_t ucma_write(struct file *filp, const char __user *buf,
1716 size_t len, loff_t *pos)
1717 {
1718 struct ucma_file *file = filp->private_data;
1719 struct rdma_ucm_cmd_hdr hdr;
1720 ssize_t ret;
1721
1722 if (!ib_safe_file_access(filp)) {
1723 pr_err_once("%s: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
1724 __func__, task_tgid_vnr(current), current->comm);
1725 return -EACCES;
1726 }
1727
1728 if (len < sizeof(hdr))
1729 return -EINVAL;
1730
1731 if (copy_from_user(&hdr, buf, sizeof(hdr)))
1732 return -EFAULT;
1733
1734 if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
1735 return -EINVAL;
1736 hdr.cmd = array_index_nospec(hdr.cmd, ARRAY_SIZE(ucma_cmd_table));
1737
1738 if (hdr.in + sizeof(hdr) > len)
1739 return -EINVAL;
1740
1741 if (!ucma_cmd_table[hdr.cmd])
1742 return -ENOSYS;
1743
1744 ret = ucma_cmd_table[hdr.cmd](file, buf + sizeof(hdr), hdr.in, hdr.out);
1745 if (!ret)
1746 ret = len;
1747
1748 return ret;
1749 }
1750
1751 static __poll_t ucma_poll(struct file *filp, struct poll_table_struct *wait)
1752 {
1753 struct ucma_file *file = filp->private_data;
1754 __poll_t mask = 0;
1755
1756 poll_wait(filp, &file->poll_wait, wait);
1757
1758 if (!list_empty(&file->event_list))
1759 mask = EPOLLIN | EPOLLRDNORM;
1760
1761 return mask;
1762 }
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772 static int ucma_open(struct inode *inode, struct file *filp)
1773 {
1774 struct ucma_file *file;
1775
1776 file = kmalloc(sizeof *file, GFP_KERNEL);
1777 if (!file)
1778 return -ENOMEM;
1779
1780 INIT_LIST_HEAD(&file->event_list);
1781 INIT_LIST_HEAD(&file->ctx_list);
1782 init_waitqueue_head(&file->poll_wait);
1783 mutex_init(&file->mut);
1784
1785 filp->private_data = file;
1786 file->filp = filp;
1787
1788 return stream_open(inode, filp);
1789 }
1790
1791 static int ucma_close(struct inode *inode, struct file *filp)
1792 {
1793 struct ucma_file *file = filp->private_data;
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803 while (!list_empty(&file->ctx_list)) {
1804 struct ucma_context *ctx = list_first_entry(
1805 &file->ctx_list, struct ucma_context, list);
1806
1807 WARN_ON(xa_cmpxchg(&ctx_table, ctx->id, ctx, XA_ZERO_ENTRY,
1808 GFP_KERNEL) != ctx);
1809 ucma_destroy_private_ctx(ctx);
1810 }
1811 kfree(file);
1812 return 0;
1813 }
1814
1815 static const struct file_operations ucma_fops = {
1816 .owner = THIS_MODULE,
1817 .open = ucma_open,
1818 .release = ucma_close,
1819 .write = ucma_write,
1820 .poll = ucma_poll,
1821 .llseek = no_llseek,
1822 };
1823
1824 static struct miscdevice ucma_misc = {
1825 .minor = MISC_DYNAMIC_MINOR,
1826 .name = "rdma_cm",
1827 .nodename = "infiniband/rdma_cm",
1828 .mode = 0666,
1829 .fops = &ucma_fops,
1830 };
1831
1832 static int ucma_get_global_nl_info(struct ib_client_nl_info *res)
1833 {
1834 res->abi = RDMA_USER_CM_ABI_VERSION;
1835 res->cdev = ucma_misc.this_device;
1836 return 0;
1837 }
1838
1839 static struct ib_client rdma_cma_client = {
1840 .name = "rdma_cm",
1841 .get_global_nl_info = ucma_get_global_nl_info,
1842 };
1843 MODULE_ALIAS_RDMA_CLIENT("rdma_cm");
1844
1845 static ssize_t abi_version_show(struct device *dev,
1846 struct device_attribute *attr, char *buf)
1847 {
1848 return sysfs_emit(buf, "%d\n", RDMA_USER_CM_ABI_VERSION);
1849 }
1850 static DEVICE_ATTR_RO(abi_version);
1851
1852 static int __init ucma_init(void)
1853 {
1854 int ret;
1855
1856 ret = misc_register(&ucma_misc);
1857 if (ret)
1858 return ret;
1859
1860 ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
1861 if (ret) {
1862 pr_err("rdma_ucm: couldn't create abi_version attr\n");
1863 goto err1;
1864 }
1865
1866 ucma_ctl_table_hdr = register_net_sysctl(&init_net, "net/rdma_ucm", ucma_ctl_table);
1867 if (!ucma_ctl_table_hdr) {
1868 pr_err("rdma_ucm: couldn't register sysctl paths\n");
1869 ret = -ENOMEM;
1870 goto err2;
1871 }
1872
1873 ret = ib_register_client(&rdma_cma_client);
1874 if (ret)
1875 goto err3;
1876
1877 return 0;
1878 err3:
1879 unregister_net_sysctl_table(ucma_ctl_table_hdr);
1880 err2:
1881 device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1882 err1:
1883 misc_deregister(&ucma_misc);
1884 return ret;
1885 }
1886
1887 static void __exit ucma_cleanup(void)
1888 {
1889 ib_unregister_client(&rdma_cma_client);
1890 unregister_net_sysctl_table(ucma_ctl_table_hdr);
1891 device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
1892 misc_deregister(&ucma_misc);
1893 }
1894
1895 module_init(ucma_init);
1896 module_exit(ucma_cleanup);