.. | .. |
---|
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 | } |
---|