Skip to content

Commit

Permalink
IB/core: Only enforce security for InfiniBand
Browse files Browse the repository at this point in the history
For now the only LSM security enforcement mechanism available is
specific to InfiniBand. Bypass enforcement for non-IB link types.

This fixes a regression where modify_qp fails for iWARP because
querying the PKEY returns -EINVAL.

Cc: Paul Moore <paul@paul-moore.com>
Cc: Don Dutile <ddutile@redhat.com>
Cc: stable@vger.kernel.org
Reported-by: Potnuri Bharat Teja <bharat@chelsio.com>
Fixes: d291f1a("IB/core: Enforce PKey security on QPs")
Fixes: 47a2b33("IB/core: Enforce security on management datagrams")
Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Tested-by: Potnuri Bharat Teja <bharat@chelsio.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
  • Loading branch information
Daniel Jurgens authored and Jason Gunthorpe committed Dec 1, 2017
1 parent 378efe7 commit 315d160
Showing 1 changed file with 46 additions and 4 deletions.
50 changes: 46 additions & 4 deletions drivers/infiniband/core/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,17 @@ void ib_close_shared_qp_security(struct ib_qp_security *sec)

int ib_create_qp_security(struct ib_qp *qp, struct ib_device *dev)
{
u8 i = rdma_start_port(dev);
bool is_ib = false;
int ret;

while (i <= rdma_end_port(dev) && !is_ib)
is_ib = rdma_protocol_ib(dev, i++);

/* If this isn't an IB device don't create the security context */
if (!is_ib)
return 0;

qp->qp_sec = kzalloc(sizeof(*qp->qp_sec), GFP_KERNEL);
if (!qp->qp_sec)
return -ENOMEM;
Expand All @@ -441,6 +450,10 @@ EXPORT_SYMBOL(ib_create_qp_security);

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
Expand Down Expand Up @@ -470,6 +483,10 @@ 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
* QP security could be marked for an error state
* transition. Wait for this to complete.
Expand Down Expand Up @@ -505,6 +522,10 @@ 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
* wait until this QP security structure is processed
* in the QP to error flow before destroying it because
Expand Down Expand Up @@ -557,26 +578,35 @@ int ib_security_modify_qp(struct ib_qp *qp,
{
int ret = 0;
struct ib_ports_pkeys *tmp_pps;
struct ib_ports_pkeys *new_pps;
struct ib_ports_pkeys *new_pps = NULL;
struct ib_qp *real_qp = qp->real_qp;
bool special_qp = (real_qp->qp_type == IB_QPT_SMI ||
real_qp->qp_type == IB_QPT_GSI ||
real_qp->qp_type >= IB_QPT_RESERVED1);
bool pps_change = ((qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) ||
(qp_attr_mask & IB_QP_ALT_PATH));

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: %d\n",
__func__, real_qp->qp_num);

/* The port/pkey settings are maintained only for the real QP. Open
* handles on the real QP will be in the shared_qp_list. When
* enforcing security on the real QP all the shared QPs will be
* checked as well.
*/

if (pps_change && !special_qp) {
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
* and pkey settings before checking for permission
* in case there is a concurrent cache update
Expand All @@ -600,7 +630,7 @@ int ib_security_modify_qp(struct ib_qp *qp,
qp_attr_mask,
udata);

if (pps_change && !special_qp) {
if (new_pps) {
/* Clean up the lists and free the appropriate
* ports_pkeys structure.
*/
Expand Down Expand Up @@ -631,6 +661,9 @@ int ib_security_pkey_access(struct ib_device *dev,
u16 pkey;
int ret;

if (!rdma_protocol_ib(dev, port_num))
return 0;

ret = ib_get_cached_pkey(dev, port_num, pkey_index, &pkey);
if (ret)
return ret;
Expand Down Expand Up @@ -665,6 +698,9 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
{
int ret;

if (!rdma_protocol_ib(agent->device, agent->port_num))
return 0;

ret = security_ib_alloc_security(&agent->security);
if (ret)
return ret;
Expand All @@ -690,13 +726,19 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent,

void ib_mad_agent_security_cleanup(struct ib_mad_agent *agent)
{
if (!rdma_protocol_ib(agent->device, agent->port_num))
return;

security_ib_free_security(agent->security);
if (agent->lsm_nb_reg)
unregister_lsm_notifier(&agent->lsm_nb);
}

int ib_mad_enforce_security(struct ib_mad_agent_private *map, u16 pkey_index)
{
if (!rdma_protocol_ib(map->agent.device, map->agent.port_num))
return 0;

if (map->agent.qp->qp_type == IB_QPT_SMI && !map->agent.smp_allowed)
return -EACCES;

Expand Down

0 comments on commit 315d160

Please sign in to comment.