brintos

brintos / linux-shallow public Read only

0
0
Text · 18.0 KiB · 3512c2e Raw
751 lines · c
1/*2 * Copyright (c) 2016 Mellanox Technologies Ltd.  All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses.  You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 *     Redistribution and use in source and binary forms, with or11 *     without modification, are permitted provided that the following12 *     conditions are met:13 *14 *      - Redistributions of source code must retain the above15 *        copyright notice, this list of conditions and the following16 *        disclaimer.17 *18 *      - Redistributions in binary form must reproduce the above19 *        copyright notice, this list of conditions and the following20 *        disclaimer in the documentation and/or other materials21 *        provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 */32 33#include <linux/security.h>34#include <linux/completion.h>35#include <linux/list.h>36 37#include <rdma/ib_verbs.h>38#include <rdma/ib_cache.h>39#include "core_priv.h"40#include "mad_priv.h"41 42static LIST_HEAD(mad_agent_list);43/* Lock to protect mad_agent_list */44static DEFINE_SPINLOCK(mad_agent_list_lock);45 46static struct pkey_index_qp_list *get_pkey_idx_qp_list(struct ib_port_pkey *pp)47{48	struct pkey_index_qp_list *pkey = NULL;49	struct pkey_index_qp_list *tmp_pkey;50	struct ib_device *dev = pp->sec->dev;51 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) {55		if (tmp_pkey->pkey_index == pp->pkey_index) {56			pkey = tmp_pkey;57			break;58		}59	}60	spin_unlock(&dev->port_data[pp->port_num].pkey_list_lock);61	return pkey;62}63 64static int get_pkey_and_subnet_prefix(struct ib_port_pkey *pp,65				      u16 *pkey,66				      u64 *subnet_prefix)67{68	struct ib_device *dev = pp->sec->dev;69	int ret;70 71	ret = ib_get_cached_pkey(dev, pp->port_num, pp->pkey_index, pkey);72	if (ret)73		return ret;74 75	ib_get_cached_subnet_prefix(dev, pp->port_num, subnet_prefix);76 77	return ret;78}79 80static int enforce_qp_pkey_security(u16 pkey,81				    u64 subnet_prefix,82				    struct ib_qp_security *qp_sec)83{84	struct ib_qp_security *shared_qp_sec;85	int ret;86 87	ret = security_ib_pkey_access(qp_sec->security, subnet_prefix, pkey);88	if (ret)89		return ret;90 91	list_for_each_entry(shared_qp_sec,92			    &qp_sec->shared_qp_list,93			    shared_qp_list) {94		ret = security_ib_pkey_access(shared_qp_sec->security,95					      subnet_prefix,96					      pkey);97		if (ret)98			return ret;99	}100	return 0;101}102 103/* The caller of this function must hold the QP security104 * mutex of the QP of the security structure in *pps.105 *106 * It takes separate ports_pkeys and security structure107 * because in some cases the pps will be for a new settings108 * or the pps will be for the real QP and security structure109 * will be for a shared QP.110 */111static int check_qp_port_pkey_settings(struct ib_ports_pkeys *pps,112				       struct ib_qp_security *sec)113{114	u64 subnet_prefix;115	u16 pkey;116	int ret = 0;117 118	if (!pps)119		return 0;120 121	if (pps->main.state != IB_PORT_PKEY_NOT_VALID) {122		ret = get_pkey_and_subnet_prefix(&pps->main,123						 &pkey,124						 &subnet_prefix);125		if (ret)126			return ret;127 128		ret = enforce_qp_pkey_security(pkey,129					       subnet_prefix,130					       sec);131		if (ret)132			return ret;133	}134 135	if (pps->alt.state != IB_PORT_PKEY_NOT_VALID) {136		ret = get_pkey_and_subnet_prefix(&pps->alt,137						 &pkey,138						 &subnet_prefix);139		if (ret)140			return ret;141 142		ret = enforce_qp_pkey_security(pkey,143					       subnet_prefix,144					       sec);145	}146 147	return ret;148}149 150/* The caller of this function must hold the QP security151 * mutex.152 */153static void qp_to_error(struct ib_qp_security *sec)154{155	struct ib_qp_security *shared_qp_sec;156	struct ib_qp_attr attr = {157		.qp_state = IB_QPS_ERR158	};159	struct ib_event event = {160		.event = IB_EVENT_QP_FATAL161	};162 163	/* If the QP is in the process of being destroyed164	 * the qp pointer in the security structure is165	 * undefined.  It cannot be modified now.166	 */167	if (sec->destroying)168		return;169 170	ib_modify_qp(sec->qp,171		     &attr,172		     IB_QP_STATE);173 174	if (sec->qp->event_handler && sec->qp->qp_context) {175		event.element.qp = sec->qp;176		sec->qp->event_handler(&event,177				       sec->qp->qp_context);178	}179 180	list_for_each_entry(shared_qp_sec,181			    &sec->shared_qp_list,182			    shared_qp_list) {183		struct ib_qp *qp = shared_qp_sec->qp;184 185		if (qp->event_handler && qp->qp_context) {186			event.element.qp = qp;187			event.device = qp->device;188			qp->event_handler(&event,189					  qp->qp_context);190		}191	}192}193 194static inline void check_pkey_qps(struct pkey_index_qp_list *pkey,195				  struct ib_device *device,196				  u32 port_num,197				  u64 subnet_prefix)198{199	struct ib_port_pkey *pp, *tmp_pp;200	bool comp;201	LIST_HEAD(to_error_list);202	u16 pkey_val;203 204	if (!ib_get_cached_pkey(device,205				port_num,206				pkey->pkey_index,207				&pkey_val)) {208		spin_lock(&pkey->qp_list_lock);209		list_for_each_entry(pp, &pkey->qp_list, qp_list) {210			if (atomic_read(&pp->sec->error_list_count))211				continue;212 213			if (enforce_qp_pkey_security(pkey_val,214						     subnet_prefix,215						     pp->sec)) {216				atomic_inc(&pp->sec->error_list_count);217				list_add(&pp->to_error_list,218					 &to_error_list);219			}220		}221		spin_unlock(&pkey->qp_list_lock);222	}223 224	list_for_each_entry_safe(pp,225				 tmp_pp,226				 &to_error_list,227				 to_error_list) {228		mutex_lock(&pp->sec->mutex);229		qp_to_error(pp->sec);230		list_del(&pp->to_error_list);231		atomic_dec(&pp->sec->error_list_count);232		comp = pp->sec->destroying;233		mutex_unlock(&pp->sec->mutex);234 235		if (comp)236			complete(&pp->sec->error_complete);237	}238}239 240/* The caller of this function must hold the QP security241 * mutex.242 */243static int port_pkey_list_insert(struct ib_port_pkey *pp)244{245	struct pkey_index_qp_list *tmp_pkey;246	struct pkey_index_qp_list *pkey;247	struct ib_device *dev;248	u32 port_num = pp->port_num;249	int ret = 0;250 251	if (pp->state != IB_PORT_PKEY_VALID)252		return 0;253 254	dev = pp->sec->dev;255 256	pkey = get_pkey_idx_qp_list(pp);257 258	if (!pkey) {259		bool found = false;260 261		pkey = kzalloc(sizeof(*pkey), GFP_KERNEL);262		if (!pkey)263			return -ENOMEM;264 265		spin_lock(&dev->port_data[port_num].pkey_list_lock);266		/* Check for the PKey again.  A racing process may267		 * have created it.268		 */269		list_for_each_entry(tmp_pkey,270				    &dev->port_data[port_num].pkey_list,271				    pkey_index_list) {272			if (tmp_pkey->pkey_index == pp->pkey_index) {273				kfree(pkey);274				pkey = tmp_pkey;275				found = true;276				break;277			}278		}279 280		if (!found) {281			pkey->pkey_index = pp->pkey_index;282			spin_lock_init(&pkey->qp_list_lock);283			INIT_LIST_HEAD(&pkey->qp_list);284			list_add(&pkey->pkey_index_list,285				 &dev->port_data[port_num].pkey_list);286		}287		spin_unlock(&dev->port_data[port_num].pkey_list_lock);288	}289 290	spin_lock(&pkey->qp_list_lock);291	list_add(&pp->qp_list, &pkey->qp_list);292	spin_unlock(&pkey->qp_list_lock);293 294	pp->state = IB_PORT_PKEY_LISTED;295 296	return ret;297}298 299/* The caller of this function must hold the QP security300 * mutex.301 */302static void port_pkey_list_remove(struct ib_port_pkey *pp)303{304	struct pkey_index_qp_list *pkey;305 306	if (pp->state != IB_PORT_PKEY_LISTED)307		return;308 309	pkey = get_pkey_idx_qp_list(pp);310 311	spin_lock(&pkey->qp_list_lock);312	list_del(&pp->qp_list);313	spin_unlock(&pkey->qp_list_lock);314 315	/* The setting may still be valid, i.e. after316	 * a destroy has failed for example.317	 */318	pp->state = IB_PORT_PKEY_VALID;319}320 321static void destroy_qp_security(struct ib_qp_security *sec)322{323	security_ib_free_security(sec->security);324	kfree(sec->ports_pkeys);325	kfree(sec);326}327 328/* The caller of this function must hold the QP security329 * mutex.330 */331static struct ib_ports_pkeys *get_new_pps(const struct ib_qp *qp,332					  const struct ib_qp_attr *qp_attr,333					  int qp_attr_mask)334{335	struct ib_ports_pkeys *new_pps;336	struct ib_ports_pkeys *qp_pps = qp->qp_sec->ports_pkeys;337 338	new_pps = kzalloc(sizeof(*new_pps), GFP_KERNEL);339	if (!new_pps)340		return NULL;341 342	if (qp_attr_mask & IB_QP_PORT)343		new_pps->main.port_num = qp_attr->port_num;344	else if (qp_pps)345		new_pps->main.port_num = qp_pps->main.port_num;346 347	if (qp_attr_mask & IB_QP_PKEY_INDEX)348		new_pps->main.pkey_index = qp_attr->pkey_index;349	else if (qp_pps)350		new_pps->main.pkey_index = qp_pps->main.pkey_index;351 352	if (((qp_attr_mask & IB_QP_PKEY_INDEX) &&353	     (qp_attr_mask & IB_QP_PORT)) ||354	    (qp_pps && qp_pps->main.state != IB_PORT_PKEY_NOT_VALID))355		new_pps->main.state = IB_PORT_PKEY_VALID;356 357	if (qp_attr_mask & IB_QP_ALT_PATH) {358		new_pps->alt.port_num = qp_attr->alt_port_num;359		new_pps->alt.pkey_index = qp_attr->alt_pkey_index;360		new_pps->alt.state = IB_PORT_PKEY_VALID;361	} else if (qp_pps) {362		new_pps->alt.port_num = qp_pps->alt.port_num;363		new_pps->alt.pkey_index = qp_pps->alt.pkey_index;364		if (qp_pps->alt.state != IB_PORT_PKEY_NOT_VALID)365			new_pps->alt.state = IB_PORT_PKEY_VALID;366	}367 368	new_pps->main.sec = qp->qp_sec;369	new_pps->alt.sec = qp->qp_sec;370	return new_pps;371}372 373int ib_open_shared_qp_security(struct ib_qp *qp, struct ib_device *dev)374{375	struct ib_qp *real_qp = qp->real_qp;376	int ret;377 378	ret = ib_create_qp_security(qp, dev);379 380	if (ret)381		return ret;382 383	if (!qp->qp_sec)384		return 0;385 386	mutex_lock(&real_qp->qp_sec->mutex);387	ret = check_qp_port_pkey_settings(real_qp->qp_sec->ports_pkeys,388					  qp->qp_sec);389 390	if (ret)391		goto ret;392 393	if (qp != real_qp)394		list_add(&qp->qp_sec->shared_qp_list,395			 &real_qp->qp_sec->shared_qp_list);396ret:397	mutex_unlock(&real_qp->qp_sec->mutex);398	if (ret)399		destroy_qp_security(qp->qp_sec);400 401	return ret;402}403 404void ib_close_shared_qp_security(struct ib_qp_security *sec)405{406	struct ib_qp *real_qp = sec->qp->real_qp;407 408	mutex_lock(&real_qp->qp_sec->mutex);409	list_del(&sec->shared_qp_list);410	mutex_unlock(&real_qp->qp_sec->mutex);411 412	destroy_qp_security(sec);413}414 415int ib_create_qp_security(struct ib_qp *qp, struct ib_device *dev)416{417	unsigned int i;418	bool is_ib = false;419	int ret;420 421	rdma_for_each_port (dev, i) {422		is_ib = rdma_protocol_ib(dev, i);423		if (is_ib)424			break;425	}426 427	/* If this isn't an IB device don't create the security context */428	if (!is_ib)429		return 0;430 431	qp->qp_sec = kzalloc(sizeof(*qp->qp_sec), GFP_KERNEL);432	if (!qp->qp_sec)433		return -ENOMEM;434 435	qp->qp_sec->qp = qp;436	qp->qp_sec->dev = dev;437	mutex_init(&qp->qp_sec->mutex);438	INIT_LIST_HEAD(&qp->qp_sec->shared_qp_list);439	atomic_set(&qp->qp_sec->error_list_count, 0);440	init_completion(&qp->qp_sec->error_complete);441	ret = security_ib_alloc_security(&qp->qp_sec->security);442	if (ret) {443		kfree(qp->qp_sec);444		qp->qp_sec = NULL;445	}446 447	return ret;448}449EXPORT_SYMBOL(ib_create_qp_security);450 451void ib_destroy_qp_security_begin(struct ib_qp_security *sec)452{453	/* Return if not IB */454	if (!sec)455		return;456 457	mutex_lock(&sec->mutex);458 459	/* Remove the QP from the lists so it won't get added to460	 * a to_error_list during the destroy process.461	 */462	if (sec->ports_pkeys) {463		port_pkey_list_remove(&sec->ports_pkeys->main);464		port_pkey_list_remove(&sec->ports_pkeys->alt);465	}466 467	/* If the QP is already in one or more of those lists468	 * the destroying flag will ensure the to error flow469	 * doesn't operate on an undefined QP.470	 */471	sec->destroying = true;472 473	/* Record the error list count to know how many completions474	 * to wait for.475	 */476	sec->error_comps_pending = atomic_read(&sec->error_list_count);477 478	mutex_unlock(&sec->mutex);479}480 481void ib_destroy_qp_security_abort(struct ib_qp_security *sec)482{483	int ret;484	int i;485 486	/* Return if not IB */487	if (!sec)488		return;489 490	/* If a concurrent cache update is in progress this491	 * QP security could be marked for an error state492	 * transition.  Wait for this to complete.493	 */494	for (i = 0; i < sec->error_comps_pending; i++)495		wait_for_completion(&sec->error_complete);496 497	mutex_lock(&sec->mutex);498	sec->destroying = false;499 500	/* Restore the position in the lists and verify501	 * access is still allowed in case a cache update502	 * occurred while attempting to destroy.503	 *504	 * Because these setting were listed already505	 * and removed during ib_destroy_qp_security_begin506	 * we know the pkey_index_qp_list for the PKey507	 * already exists so port_pkey_list_insert won't fail.508	 */509	if (sec->ports_pkeys) {510		port_pkey_list_insert(&sec->ports_pkeys->main);511		port_pkey_list_insert(&sec->ports_pkeys->alt);512	}513 514	ret = check_qp_port_pkey_settings(sec->ports_pkeys, sec);515	if (ret)516		qp_to_error(sec);517 518	mutex_unlock(&sec->mutex);519}520 521void ib_destroy_qp_security_end(struct ib_qp_security *sec)522{523	int i;524 525	/* Return if not IB */526	if (!sec)527		return;528 529	/* If a concurrent cache update is occurring we must530	 * wait until this QP security structure is processed531	 * in the QP to error flow before destroying it because532	 * the to_error_list is in use.533	 */534	for (i = 0; i < sec->error_comps_pending; i++)535		wait_for_completion(&sec->error_complete);536 537	destroy_qp_security(sec);538}539 540void ib_security_cache_change(struct ib_device *device,541			      u32 port_num,542			      u64 subnet_prefix)543{544	struct pkey_index_qp_list *pkey;545 546	list_for_each_entry (pkey, &device->port_data[port_num].pkey_list,547			     pkey_index_list) {548		check_pkey_qps(pkey,549			       device,550			       port_num,551			       subnet_prefix);552	}553}554 555void ib_security_release_port_pkey_list(struct ib_device *device)556{557	struct pkey_index_qp_list *pkey, *tmp_pkey;558	unsigned int i;559 560	rdma_for_each_port (device, i) {561		list_for_each_entry_safe(pkey,562					 tmp_pkey,563					 &device->port_data[i].pkey_list,564					 pkey_index_list) {565			list_del(&pkey->pkey_index_list);566			kfree(pkey);567		}568	}569}570 571int ib_security_modify_qp(struct ib_qp *qp,572			  struct ib_qp_attr *qp_attr,573			  int qp_attr_mask,574			  struct ib_udata *udata)575{576	int ret = 0;577	struct ib_ports_pkeys *tmp_pps;578	struct ib_ports_pkeys *new_pps = NULL;579	struct ib_qp *real_qp = qp->real_qp;580	bool special_qp = (real_qp->qp_type == IB_QPT_SMI ||581			   real_qp->qp_type == IB_QPT_GSI ||582			   real_qp->qp_type >= IB_QPT_RESERVED1);583	bool pps_change = ((qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) ||584			   (qp_attr_mask & IB_QP_ALT_PATH));585 586	WARN_ONCE((qp_attr_mask & IB_QP_PORT &&587		   rdma_protocol_ib(real_qp->device, qp_attr->port_num) &&588		   !real_qp->qp_sec),589		   "%s: QP security is not initialized for IB QP: %u\n",590		   __func__, real_qp->qp_num);591 592	/* The port/pkey settings are maintained only for the real QP. Open593	 * handles on the real QP will be in the shared_qp_list. When594	 * enforcing security on the real QP all the shared QPs will be595	 * checked as well.596	 */597 598	if (pps_change && !special_qp && real_qp->qp_sec) {599		mutex_lock(&real_qp->qp_sec->mutex);600		new_pps = get_new_pps(real_qp,601				      qp_attr,602				      qp_attr_mask);603		if (!new_pps) {604			mutex_unlock(&real_qp->qp_sec->mutex);605			return -ENOMEM;606		}607		/* Add this QP to the lists for the new port608		 * and pkey settings before checking for permission609		 * in case there is a concurrent cache update610		 * occurring.  Walking the list for a cache change611		 * doesn't acquire the security mutex unless it's612		 * sending the QP to error.613		 */614		ret = port_pkey_list_insert(&new_pps->main);615 616		if (!ret)617			ret = port_pkey_list_insert(&new_pps->alt);618 619		if (!ret)620			ret = check_qp_port_pkey_settings(new_pps,621							  real_qp->qp_sec);622	}623 624	if (!ret)625		ret = real_qp->device->ops.modify_qp(real_qp,626						     qp_attr,627						     qp_attr_mask,628						     udata);629 630	if (new_pps) {631		/* Clean up the lists and free the appropriate632		 * ports_pkeys structure.633		 */634		if (ret) {635			tmp_pps = new_pps;636		} else {637			tmp_pps = real_qp->qp_sec->ports_pkeys;638			real_qp->qp_sec->ports_pkeys = new_pps;639		}640 641		if (tmp_pps) {642			port_pkey_list_remove(&tmp_pps->main);643			port_pkey_list_remove(&tmp_pps->alt);644		}645		kfree(tmp_pps);646		mutex_unlock(&real_qp->qp_sec->mutex);647	}648	return ret;649}650 651static int ib_security_pkey_access(struct ib_device *dev,652				   u32 port_num,653				   u16 pkey_index,654				   void *sec)655{656	u64 subnet_prefix;657	u16 pkey;658	int ret;659 660	if (!rdma_protocol_ib(dev, port_num))661		return 0;662 663	ret = ib_get_cached_pkey(dev, port_num, pkey_index, &pkey);664	if (ret)665		return ret;666 667	ib_get_cached_subnet_prefix(dev, port_num, &subnet_prefix);668 669	return security_ib_pkey_access(sec, subnet_prefix, pkey);670}671 672void ib_mad_agent_security_change(void)673{674	struct ib_mad_agent *ag;675 676	spin_lock(&mad_agent_list_lock);677	list_for_each_entry(ag,678			    &mad_agent_list,679			    mad_agent_sec_list)680		WRITE_ONCE(ag->smp_allowed,681			   !security_ib_endport_manage_subnet(ag->security,682				dev_name(&ag->device->dev), ag->port_num));683	spin_unlock(&mad_agent_list_lock);684}685 686int ib_mad_agent_security_setup(struct ib_mad_agent *agent,687				enum ib_qp_type qp_type)688{689	int ret;690 691	if (!rdma_protocol_ib(agent->device, agent->port_num))692		return 0;693 694	INIT_LIST_HEAD(&agent->mad_agent_sec_list);695 696	ret = security_ib_alloc_security(&agent->security);697	if (ret)698		return ret;699 700	if (qp_type != IB_QPT_SMI)701		return 0;702 703	spin_lock(&mad_agent_list_lock);704	ret = security_ib_endport_manage_subnet(agent->security,705						dev_name(&agent->device->dev),706						agent->port_num);707	if (ret)708		goto free_security;709 710	WRITE_ONCE(agent->smp_allowed, true);711	list_add(&agent->mad_agent_sec_list, &mad_agent_list);712	spin_unlock(&mad_agent_list_lock);713	return 0;714 715free_security:716	spin_unlock(&mad_agent_list_lock);717	security_ib_free_security(agent->security);718	return ret;719}720 721void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent)722{723	if (!rdma_protocol_ib(agent->device, agent->port_num))724		return;725 726	if (agent->qp->qp_type == IB_QPT_SMI) {727		spin_lock(&mad_agent_list_lock);728		list_del(&agent->mad_agent_sec_list);729		spin_unlock(&mad_agent_list_lock);730	}731 732	security_ib_free_security(agent->security);733}734 735int ib_mad_enforce_security(struct ib_mad_agent_private *map, u16 pkey_index)736{737	if (!rdma_protocol_ib(map->agent.device, map->agent.port_num))738		return 0;739 740	if (map->agent.qp->qp_type == IB_QPT_SMI) {741		if (!READ_ONCE(map->agent.smp_allowed))742			return -EACCES;743		return 0;744	}745 746	return ib_security_pkey_access(map->agent.device,747				       map->agent.port_num,748				       pkey_index,749				       map->agent.security);750}751