| .. | .. |
|---|
| 39 | 39 | #include "core_priv.h" |
|---|
| 40 | 40 | #include "mad_priv.h" |
|---|
| 41 | 41 | |
|---|
| 42 | +static LIST_HEAD(mad_agent_list); |
|---|
| 43 | +/* Lock to protect mad_agent_list */ |
|---|
| 44 | +static DEFINE_SPINLOCK(mad_agent_list_lock); |
|---|
| 45 | + |
|---|
| 42 | 46 | static struct pkey_index_qp_list *get_pkey_idx_qp_list(struct ib_port_pkey *pp) |
|---|
| 43 | 47 | { |
|---|
| 44 | 48 | struct pkey_index_qp_list *pkey = NULL; |
|---|
| 45 | 49 | struct pkey_index_qp_list *tmp_pkey; |
|---|
| 46 | 50 | struct ib_device *dev = pp->sec->dev; |
|---|
| 47 | 51 | |
|---|
| 48 | | - spin_lock(&dev->port_pkey_list[pp->port_num].list_lock); |
|---|
| 49 | | - list_for_each_entry(tmp_pkey, |
|---|
| 50 | | - &dev->port_pkey_list[pp->port_num].pkey_list, |
|---|
| 51 | | - pkey_index_list) { |
|---|
| 52 | + spin_lock(&dev->port_data[pp->port_num].pkey_list_lock); |
|---|
| 53 | + list_for_each_entry (tmp_pkey, &dev->port_data[pp->port_num].pkey_list, |
|---|
| 54 | + pkey_index_list) { |
|---|
| 52 | 55 | if (tmp_pkey->pkey_index == pp->pkey_index) { |
|---|
| 53 | 56 | pkey = tmp_pkey; |
|---|
| 54 | 57 | break; |
|---|
| 55 | 58 | } |
|---|
| 56 | 59 | } |
|---|
| 57 | | - spin_unlock(&dev->port_pkey_list[pp->port_num].list_lock); |
|---|
| 60 | + spin_unlock(&dev->port_data[pp->port_num].pkey_list_lock); |
|---|
| 58 | 61 | return pkey; |
|---|
| 59 | 62 | } |
|---|
| 60 | 63 | |
|---|
| .. | .. |
|---|
| 259 | 262 | if (!pkey) |
|---|
| 260 | 263 | return -ENOMEM; |
|---|
| 261 | 264 | |
|---|
| 262 | | - spin_lock(&dev->port_pkey_list[port_num].list_lock); |
|---|
| 265 | + spin_lock(&dev->port_data[port_num].pkey_list_lock); |
|---|
| 263 | 266 | /* Check for the PKey again. A racing process may |
|---|
| 264 | 267 | * have created it. |
|---|
| 265 | 268 | */ |
|---|
| 266 | 269 | list_for_each_entry(tmp_pkey, |
|---|
| 267 | | - &dev->port_pkey_list[port_num].pkey_list, |
|---|
| 270 | + &dev->port_data[port_num].pkey_list, |
|---|
| 268 | 271 | pkey_index_list) { |
|---|
| 269 | 272 | if (tmp_pkey->pkey_index == pp->pkey_index) { |
|---|
| 270 | 273 | kfree(pkey); |
|---|
| .. | .. |
|---|
| 279 | 282 | spin_lock_init(&pkey->qp_list_lock); |
|---|
| 280 | 283 | INIT_LIST_HEAD(&pkey->qp_list); |
|---|
| 281 | 284 | list_add(&pkey->pkey_index_list, |
|---|
| 282 | | - &dev->port_pkey_list[port_num].pkey_list); |
|---|
| 285 | + &dev->port_data[port_num].pkey_list); |
|---|
| 283 | 286 | } |
|---|
| 284 | | - spin_unlock(&dev->port_pkey_list[port_num].list_lock); |
|---|
| 287 | + spin_unlock(&dev->port_data[port_num].pkey_list_lock); |
|---|
| 285 | 288 | } |
|---|
| 286 | 289 | |
|---|
| 287 | 290 | spin_lock(&pkey->qp_list_lock); |
|---|
| .. | .. |
|---|
| 411 | 414 | |
|---|
| 412 | 415 | int ib_create_qp_security(struct ib_qp *qp, struct ib_device *dev) |
|---|
| 413 | 416 | { |
|---|
| 414 | | - u8 i = rdma_start_port(dev); |
|---|
| 417 | + unsigned int i; |
|---|
| 415 | 418 | bool is_ib = false; |
|---|
| 416 | 419 | int ret; |
|---|
| 417 | 420 | |
|---|
| 418 | | - while (i <= rdma_end_port(dev) && !is_ib) |
|---|
| 419 | | - is_ib = rdma_protocol_ib(dev, i++); |
|---|
| 421 | + rdma_for_each_port (dev, i) { |
|---|
| 422 | + is_ib = rdma_protocol_ib(dev, i); |
|---|
| 423 | + if (is_ib) |
|---|
| 424 | + break; |
|---|
| 425 | + } |
|---|
| 420 | 426 | |
|---|
| 421 | 427 | /* If this isn't an IB device don't create the security context */ |
|---|
| 422 | 428 | if (!is_ib) |
|---|
| .. | .. |
|---|
| 537 | 543 | { |
|---|
| 538 | 544 | struct pkey_index_qp_list *pkey; |
|---|
| 539 | 545 | |
|---|
| 540 | | - list_for_each_entry(pkey, |
|---|
| 541 | | - &device->port_pkey_list[port_num].pkey_list, |
|---|
| 542 | | - pkey_index_list) { |
|---|
| 546 | + list_for_each_entry (pkey, &device->port_data[port_num].pkey_list, |
|---|
| 547 | + pkey_index_list) { |
|---|
| 543 | 548 | check_pkey_qps(pkey, |
|---|
| 544 | 549 | device, |
|---|
| 545 | 550 | port_num, |
|---|
| .. | .. |
|---|
| 547 | 552 | } |
|---|
| 548 | 553 | } |
|---|
| 549 | 554 | |
|---|
| 550 | | -void ib_security_destroy_port_pkey_list(struct ib_device *device) |
|---|
| 555 | +void ib_security_release_port_pkey_list(struct ib_device *device) |
|---|
| 551 | 556 | { |
|---|
| 552 | 557 | struct pkey_index_qp_list *pkey, *tmp_pkey; |
|---|
| 553 | | - int i; |
|---|
| 558 | + unsigned int i; |
|---|
| 554 | 559 | |
|---|
| 555 | | - for (i = rdma_start_port(device); i <= rdma_end_port(device); i++) { |
|---|
| 556 | | - spin_lock(&device->port_pkey_list[i].list_lock); |
|---|
| 560 | + rdma_for_each_port (device, i) { |
|---|
| 557 | 561 | list_for_each_entry_safe(pkey, |
|---|
| 558 | 562 | tmp_pkey, |
|---|
| 559 | | - &device->port_pkey_list[i].pkey_list, |
|---|
| 563 | + &device->port_data[i].pkey_list, |
|---|
| 560 | 564 | pkey_index_list) { |
|---|
| 561 | 565 | list_del(&pkey->pkey_index_list); |
|---|
| 562 | 566 | kfree(pkey); |
|---|
| 563 | 567 | } |
|---|
| 564 | | - spin_unlock(&device->port_pkey_list[i].list_lock); |
|---|
| 565 | 568 | } |
|---|
| 566 | 569 | } |
|---|
| 567 | 570 | |
|---|
| .. | .. |
|---|
| 619 | 622 | } |
|---|
| 620 | 623 | |
|---|
| 621 | 624 | if (!ret) |
|---|
| 622 | | - ret = real_qp->device->modify_qp(real_qp, |
|---|
| 623 | | - qp_attr, |
|---|
| 624 | | - qp_attr_mask, |
|---|
| 625 | | - udata); |
|---|
| 625 | + ret = real_qp->device->ops.modify_qp(real_qp, |
|---|
| 626 | + qp_attr, |
|---|
| 627 | + qp_attr_mask, |
|---|
| 628 | + udata); |
|---|
| 626 | 629 | |
|---|
| 627 | 630 | if (new_pps) { |
|---|
| 628 | 631 | /* Clean up the lists and free the appropriate |
|---|
| .. | .. |
|---|
| 669 | 672 | return security_ib_pkey_access(sec, subnet_prefix, pkey); |
|---|
| 670 | 673 | } |
|---|
| 671 | 674 | |
|---|
| 672 | | -static int ib_mad_agent_security_change(struct notifier_block *nb, |
|---|
| 673 | | - unsigned long event, |
|---|
| 674 | | - void *data) |
|---|
| 675 | +void ib_mad_agent_security_change(void) |
|---|
| 675 | 676 | { |
|---|
| 676 | | - struct ib_mad_agent *ag = container_of(nb, struct ib_mad_agent, lsm_nb); |
|---|
| 677 | + struct ib_mad_agent *ag; |
|---|
| 677 | 678 | |
|---|
| 678 | | - if (event != LSM_POLICY_CHANGE) |
|---|
| 679 | | - return NOTIFY_DONE; |
|---|
| 680 | | - |
|---|
| 681 | | - ag->smp_allowed = !security_ib_endport_manage_subnet(ag->security, |
|---|
| 682 | | - ag->device->name, |
|---|
| 683 | | - ag->port_num); |
|---|
| 684 | | - |
|---|
| 685 | | - return NOTIFY_OK; |
|---|
| 679 | + spin_lock(&mad_agent_list_lock); |
|---|
| 680 | + list_for_each_entry(ag, |
|---|
| 681 | + &mad_agent_list, |
|---|
| 682 | + mad_agent_sec_list) |
|---|
| 683 | + WRITE_ONCE(ag->smp_allowed, |
|---|
| 684 | + !security_ib_endport_manage_subnet(ag->security, |
|---|
| 685 | + dev_name(&ag->device->dev), ag->port_num)); |
|---|
| 686 | + spin_unlock(&mad_agent_list_lock); |
|---|
| 686 | 687 | } |
|---|
| 687 | 688 | |
|---|
| 688 | 689 | int ib_mad_agent_security_setup(struct ib_mad_agent *agent, |
|---|
| .. | .. |
|---|
| 693 | 694 | if (!rdma_protocol_ib(agent->device, agent->port_num)) |
|---|
| 694 | 695 | return 0; |
|---|
| 695 | 696 | |
|---|
| 697 | + INIT_LIST_HEAD(&agent->mad_agent_sec_list); |
|---|
| 698 | + |
|---|
| 696 | 699 | ret = security_ib_alloc_security(&agent->security); |
|---|
| 697 | 700 | if (ret) |
|---|
| 698 | 701 | return ret; |
|---|
| .. | .. |
|---|
| 700 | 703 | if (qp_type != IB_QPT_SMI) |
|---|
| 701 | 704 | return 0; |
|---|
| 702 | 705 | |
|---|
| 706 | + spin_lock(&mad_agent_list_lock); |
|---|
| 703 | 707 | ret = security_ib_endport_manage_subnet(agent->security, |
|---|
| 704 | | - agent->device->name, |
|---|
| 708 | + dev_name(&agent->device->dev), |
|---|
| 705 | 709 | agent->port_num); |
|---|
| 706 | 710 | if (ret) |
|---|
| 707 | 711 | goto free_security; |
|---|
| 708 | 712 | |
|---|
| 709 | | - agent->lsm_nb.notifier_call = ib_mad_agent_security_change; |
|---|
| 710 | | - ret = register_lsm_notifier(&agent->lsm_nb); |
|---|
| 711 | | - if (ret) |
|---|
| 712 | | - goto free_security; |
|---|
| 713 | | - |
|---|
| 714 | | - agent->smp_allowed = true; |
|---|
| 715 | | - agent->lsm_nb_reg = true; |
|---|
| 713 | + WRITE_ONCE(agent->smp_allowed, true); |
|---|
| 714 | + list_add(&agent->mad_agent_sec_list, &mad_agent_list); |
|---|
| 715 | + spin_unlock(&mad_agent_list_lock); |
|---|
| 716 | 716 | return 0; |
|---|
| 717 | 717 | |
|---|
| 718 | 718 | free_security: |
|---|
| 719 | + spin_unlock(&mad_agent_list_lock); |
|---|
| 719 | 720 | security_ib_free_security(agent->security); |
|---|
| 720 | 721 | return ret; |
|---|
| 721 | 722 | } |
|---|
| .. | .. |
|---|
| 725 | 726 | if (!rdma_protocol_ib(agent->device, agent->port_num)) |
|---|
| 726 | 727 | return; |
|---|
| 727 | 728 | |
|---|
| 728 | | - if (agent->lsm_nb_reg) |
|---|
| 729 | | - unregister_lsm_notifier(&agent->lsm_nb); |
|---|
| 729 | + if (agent->qp->qp_type == IB_QPT_SMI) { |
|---|
| 730 | + spin_lock(&mad_agent_list_lock); |
|---|
| 731 | + list_del(&agent->mad_agent_sec_list); |
|---|
| 732 | + spin_unlock(&mad_agent_list_lock); |
|---|
| 733 | + } |
|---|
| 730 | 734 | |
|---|
| 731 | 735 | security_ib_free_security(agent->security); |
|---|
| 732 | 736 | } |
|---|
| .. | .. |
|---|
| 737 | 741 | return 0; |
|---|
| 738 | 742 | |
|---|
| 739 | 743 | if (map->agent.qp->qp_type == IB_QPT_SMI) { |
|---|
| 740 | | - if (!map->agent.smp_allowed) |
|---|
| 744 | + if (!READ_ONCE(map->agent.smp_allowed)) |
|---|
| 741 | 745 | return -EACCES; |
|---|
| 742 | 746 | return 0; |
|---|
| 743 | 747 | } |
|---|