ret = security_ib_pkey_access(qp_sec->security, subnet_prefix, pkey); if (ret) return ret;
list_for_each_entry(shared_qp_sec,
&qp_sec->shared_qp_list,
shared_qp_list) {
ret = security_ib_pkey_access(shared_qp_sec->security,
subnet_prefix,
pkey); if (ret) return ret;
} return0;
}
/* The caller of this function must hold the QP security *mutexoftheQPofthesecuritystructurein*pps. * *Ittakesseparateports_pkeysandsecuritystructure *becauseinsomecasestheppswillbeforanewsettings *ortheppswillbefortherealQPandsecuritystructure *willbeforasharedQP.
*/ staticint check_qp_port_pkey_settings(struct ib_ports_pkeys *pps, struct ib_qp_security *sec)
{
u64 subnet_prefix;
u16 pkey; int ret = 0;
if (!pps) return0;
if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {
ret = get_pkey_and_subnet_prefix(&pps->main,
&pkey,
&subnet_prefix); if (ret) return ret;
ret = enforce_qp_pkey_security(pkey,
subnet_prefix,
sec); if (ret) return ret;
}
if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {
ret = get_pkey_and_subnet_prefix(&pps->alt,
&pkey,
&subnet_prefix); if (ret) return ret;
ret = enforce_qp_pkey_security(pkey,
subnet_prefix,
sec);
}
return ret;
}
/* The caller of this function must hold the QP security *mutex.
*/ staticvoid qp_to_error(struct ib_qp_security *sec)
{ struct ib_qp_security *shared_qp_sec; struct ib_qp_attr attr = {
.qp_state = IB_QPS_ERR
}; struct ib_event event = {
.event = IB_EVENT_QP_FATAL
};
/* If the QP is in the process of being destroyed *theqppointerinthesecuritystructureis *undefined.Itcannotbemodifiednow.
*/ if (sec->destroying) return;
/* The caller of this function must hold the QP security *mutex.
*/ staticint port_pkey_list_insert(struct ib_port_pkey *pp)
{ struct pkey_index_qp_list *tmp_pkey; struct pkey_index_qp_list *pkey; struct ib_device *dev;
u32 port_num = pp->port_num; int ret = 0;
if (pp->state != IB_PORT_PKEY_VALID) return0;
dev = pp->sec->dev;
pkey = get_pkey_idx_qp_list(pp);
if (!pkey) { bool found = false;
pkey = kzalloc(sizeof(*pkey), GFP_KERNEL); if (!pkey) return -ENOMEM;
spin_lock(&dev->port_data[port_num].pkey_list_lock); /* Check for the PKey again. A racing process may *havecreatedit.
*/
list_for_each_entry(tmp_pkey,
&dev->port_data[port_num].pkey_list,
pkey_index_list) { if (tmp_pkey->pkey_index == pp->pkey_index) {
kfree(pkey);
pkey = tmp_pkey;
found = true; break;
}
}
/* The caller of this function must hold the QP security *mutex.
*/ staticvoid port_pkey_list_remove(struct ib_port_pkey *pp)
{ struct pkey_index_qp_list *pkey;
/* The caller of this function must hold the QP security *mutex.
*/ staticstruct ib_ports_pkeys *get_new_pps(conststruct ib_qp *qp, conststruct ib_qp_attr *qp_attr, int qp_attr_mask)
{ struct ib_ports_pkeys *new_pps; struct ib_ports_pkeys *qp_pps = qp->qp_sec->ports_pkeys;
new_pps = kzalloc(sizeof(*new_pps), GFP_KERNEL); if (!new_pps) return NULL;
void ib_destroy_qp_security_begin(struct ib_qp_security *sec)
{ /* Return if not IB */ if (!sec) return;
mutex_lock(&sec->mutex);
/* Remove the QP from the lists so it won't get added to *ato_error_listduringthedestroyprocess.
*/ if (sec->ports_pkeys) {
port_pkey_list_remove(&sec->ports_pkeys->main);
port_pkey_list_remove(&sec->ports_pkeys->alt);
}
/* If the QP is already in one or more of those lists *thedestroyingflagwillensurethetoerrorflow *doesn'toperateonanundefinedQP.
*/
sec->destroying = true;
/* Record the error list count to know how many completions *towaitfor.
*/
sec->error_comps_pending = atomic_read(&sec->error_list_count);
mutex_unlock(&sec->mutex);
}
void ib_destroy_qp_security_abort(struct ib_qp_security *sec)
{ int ret; int i;
/* Return if not IB */ if (!sec) return;
/* If a concurrent cache update is in progress this *QPsecuritycouldbemarkedforanerrorstate *transition.Waitforthistocomplete.
*/ for (i = 0; i < sec->error_comps_pending; i++)
wait_for_completion(&sec->error_complete);
mutex_lock(&sec->mutex);
sec->destroying = false;
/* Restore the position in the lists and verify *accessisstillallowedincaseacacheupdate *occurredwhileattemptingtodestroy. * *Becausethesesettingwerelistedalready *andremovedduringib_destroy_qp_security_begin *weknowthepkey_index_qp_listforthePKey *alreadyexistssoport_pkey_list_insertwon'tfail.
*/ if (sec->ports_pkeys) {
port_pkey_list_insert(&sec->ports_pkeys->main);
port_pkey_list_insert(&sec->ports_pkeys->alt);
}
ret = check_qp_port_pkey_settings(sec->ports_pkeys, sec); if (ret)
qp_to_error(sec);
mutex_unlock(&sec->mutex);
}
void ib_destroy_qp_security_end(struct ib_qp_security *sec)
{ int i;
/* Return if not IB */ if (!sec) return;
/* If a concurrent cache update is occurring we must *waituntilthisQPsecuritystructureisprocessed *intheQPtoerrorflowbeforedestroyingitbecause *theto_error_listisinuse.
*/ for (i = 0; i < sec->error_comps_pending; i++)
wait_for_completion(&sec->error_complete);
WARN_ONCE((qp_attr_mask & IB_QP_PORT &&
rdma_protocol_ib(real_qp->device, qp_attr->port_num) &&
!real_qp->qp_sec), "%s: QP security is not initialized for IB QP: %u\n",
__func__, real_qp->qp_num);
/* The port/pkey settings are maintained only for the real QP. Open *handlesontherealQPwillbeintheshared_qp_list.When *enforcingsecurityontherealQPallthesharedQPswillbe *checkedaswell.
*/
if (pps_change && !special_qp && real_qp->qp_sec) {
mutex_lock(&real_qp->qp_sec->mutex);
new_pps = get_new_pps(real_qp,
qp_attr,
qp_attr_mask); if (!new_pps) {
mutex_unlock(&real_qp->qp_sec->mutex); return -ENOMEM;
} /* Add this QP to the lists for the new port *andpkeysettingsbeforecheckingforpermission *incasethereisaconcurrentcacheupdate *occurring.Walkingthelistforacachechange *doesn'tacquirethesecuritymutexunlessit's *sendingtheQPtoerror.
*/
ret = port_pkey_list_insert(&new_pps->main);
if (!ret)
ret = port_pkey_list_insert(&new_pps->alt);
if (!ret)
ret = check_qp_port_pkey_settings(new_pps,
real_qp->qp_sec);
}
if (!ret)
ret = real_qp->device->ops.modify_qp(real_qp,
qp_attr,
qp_attr_mask,
udata);
if (new_pps) { /* Clean up the lists and free the appropriate *ports_pkeysstructure.
*/ if (ret) {
tmp_pps = new_pps;
} else {
tmp_pps = real_qp->qp_sec->ports_pkeys;
real_qp->qp_sec->ports_pkeys = new_pps;
}
int ib_mad_agent_security_setup(struct ib_mad_agent *agent, enum ib_qp_type qp_type)
{ int ret;
if (!rdma_protocol_ib(agent->device, agent->port_num)) return0;
INIT_LIST_HEAD(&agent->mad_agent_sec_list);
ret = security_ib_alloc_security(&agent->security); if (ret) return ret;
if (qp_type != IB_QPT_SMI) return0;
spin_lock(&mad_agent_list_lock);
ret = security_ib_endport_manage_subnet(agent->security,
dev_name(&agent->device->dev),
agent->port_num); if (ret) goto free_security;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.