/*
 * Pkey table
 *
 * SELinux must keep a mapping of Infinband PKEYs to labels/SIDs.  This
 * mapping is maintained as part of the normal policy but a fast cache is
 * needed to reduce the lookup overhead.
 *
 * This code is heavily based on the "netif" and "netport" concept originally
 * developed by
 * James Morris <jmorris@redhat.com> and
 * Paul Moore <paul@paul-moore.com>
 *   (see security/selinux/netif.c and security/selinux/netport.c for more
 *   information)
 *
 */

/*
 * (c) Mellanox Technologies, 2016
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
#include <linux/spinlock.h>

#include "ibpkey.h"
#include "objsec.h"

#define SEL_PKEY_HASH_SIZE       256
#define SEL_PKEY_HASH_BKT_LIMIT   16

struct sel_ib_pkey_bkt {
	int size;
	struct list_head list;
};

struct sel_ib_pkey {
	struct pkey_security_struct psec;
	struct list_head list;
	struct rcu_head rcu;
};

static LIST_HEAD(sel_ib_pkey_list);
static DEFINE_SPINLOCK(sel_ib_pkey_lock);
static struct sel_ib_pkey_bkt sel_ib_pkey_hash[SEL_PKEY_HASH_SIZE];

/**
 * sel_ib_pkey_hashfn - Hashing function for the pkey table
 * @pkey: pkey number
 *
 * Description:
 * This is the hashing function for the pkey table, it returns the bucket
 * number for the given pkey.
 *
 */
static unsigned int sel_ib_pkey_hashfn(u16 pkey)
{
	return (pkey & (SEL_PKEY_HASH_SIZE - 1));
}

/**
 * sel_ib_pkey_find - Search for a pkey record
 * @subnet_prefix: subnet_prefix
 * @pkey_num: pkey_num
 *
 * Description:
 * Search the pkey table and return the matching record.  If an entry
 * can not be found in the table return NULL.
 *
 */
static struct sel_ib_pkey *sel_ib_pkey_find(u64 subnet_prefix, u16 pkey_num)
{
	unsigned int idx;
	struct sel_ib_pkey *pkey;

	idx = sel_ib_pkey_hashfn(pkey_num);
	list_for_each_entry_rcu(pkey, &sel_ib_pkey_hash[idx].list, list) {
		if (pkey->psec.pkey == pkey_num &&
		    pkey->psec.subnet_prefix == subnet_prefix)
			return pkey;
	}

	return NULL;
}

/**
 * sel_ib_pkey_insert - Insert a new pkey into the table
 * @pkey: the new pkey record
 *
 * Description:
 * Add a new pkey record to the hash table.
 *
 */
static void sel_ib_pkey_insert(struct sel_ib_pkey *pkey)
{
	unsigned int idx;

	/* we need to impose a limit on the growth of the hash table so check
	 * this bucket to make sure it is within the specified bounds
	 */
	idx = sel_ib_pkey_hashfn(pkey->psec.pkey);
	list_add_rcu(&pkey->list, &sel_ib_pkey_hash[idx].list);
	if (sel_ib_pkey_hash[idx].size == SEL_PKEY_HASH_BKT_LIMIT) {
		struct sel_ib_pkey *tail;

		tail = list_entry(
			rcu_dereference_protected(
				sel_ib_pkey_hash[idx].list.prev,
				lockdep_is_held(&sel_ib_pkey_lock)),
			struct sel_ib_pkey, list);
		list_del_rcu(&tail->list);
		kfree_rcu(tail, rcu);
	} else {
		sel_ib_pkey_hash[idx].size++;
	}
}

/**
 * sel_ib_pkey_sid_slow - Lookup the SID of a pkey using the policy
 * @subnet_prefix: subnet prefix
 * @pkey_num: pkey number
 * @sid: pkey SID
 *
 * Description:
 * This function determines the SID of a pkey by querying the security
 * policy.  The result is added to the pkey table to speedup future
 * queries.  Returns zero on success, negative values on failure.
 *
 */
static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
{
	int ret;
	struct sel_ib_pkey *pkey;
	struct sel_ib_pkey *new = NULL;
	unsigned long flags;

	spin_lock_irqsave(&sel_ib_pkey_lock, flags);
	pkey = sel_ib_pkey_find(subnet_prefix, pkey_num);
	if (pkey) {
		*sid = pkey->psec.sid;
		spin_unlock_irqrestore(&sel_ib_pkey_lock, flags);
		return 0;
	}

	ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num,
				   sid);
	if (ret)
		goto out;

	/* If this memory allocation fails still return 0. The SID
	 * is valid, it just won't be added to the cache.
	 */
	new = kzalloc(sizeof(*new), GFP_ATOMIC);
	if (!new)
		goto out;

	new->psec.subnet_prefix = subnet_prefix;
	new->psec.pkey = pkey_num;
	new->psec.sid = *sid;
	sel_ib_pkey_insert(new);

out:
	spin_unlock_irqrestore(&sel_ib_pkey_lock, flags);
	return ret;
}

/**
 * sel_ib_pkey_sid - Lookup the SID of a PKEY
 * @subnet_prefix: subnet_prefix
 * @pkey_num: pkey number
 * @sid: pkey SID
 *
 * Description:
 * This function determines the SID of a PKEY using the fastest method
 * possible.  First the pkey table is queried, but if an entry can't be found
 * then the policy is queried and the result is added to the table to speedup
 * future queries.  Returns zero on success, negative values on failure.
 *
 */
int sel_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *sid)
{
	struct sel_ib_pkey *pkey;

	rcu_read_lock();
	pkey = sel_ib_pkey_find(subnet_prefix, pkey_num);
	if (pkey) {
		*sid = pkey->psec.sid;
		rcu_read_unlock();
		return 0;
	}
	rcu_read_unlock();

	return sel_ib_pkey_sid_slow(subnet_prefix, pkey_num, sid);
}

/**
 * sel_ib_pkey_flush - Flush the entire pkey table
 *
 * Description:
 * Remove all entries from the pkey table
 *
 */
void sel_ib_pkey_flush(void)
{
	unsigned int idx;
	struct sel_ib_pkey *pkey, *pkey_tmp;
	unsigned long flags;

	spin_lock_irqsave(&sel_ib_pkey_lock, flags);
	for (idx = 0; idx < SEL_PKEY_HASH_SIZE; idx++) {
		list_for_each_entry_safe(pkey, pkey_tmp,
					 &sel_ib_pkey_hash[idx].list, list) {
			list_del_rcu(&pkey->list);
			kfree_rcu(pkey, rcu);
		}
		sel_ib_pkey_hash[idx].size = 0;
	}
	spin_unlock_irqrestore(&sel_ib_pkey_lock, flags);
}

static __init int sel_ib_pkey_init(void)
{
	int iter;

	if (!selinux_enabled)
		return 0;

	for (iter = 0; iter < SEL_PKEY_HASH_SIZE; iter++) {
		INIT_LIST_HEAD(&sel_ib_pkey_hash[iter].list);
		sel_ib_pkey_hash[iter].size = 0;
	}

	return 0;
}

subsys_initcall(sel_ib_pkey_init);
