// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2022 Google LLC
 * Author: ramjiyani@google.com (Ramji Jiyani)
 */

#include <linux/bsearch.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/string.h>

/*
 * Build time generated header files
 *
 * gki_module_protected_exports.h -- Symbols protected from _export_ by unsigned modules
 * gki_module_unprotected.h -- Symbols allowed to _access_ by unsigned modules
 */
#include <generated/gki_module_protected_exports.h>
#include <generated/gki_module_unprotected.h>

#define MAX_STRCMP_LEN (max(MAX_UNPROTECTED_NAME_LEN, MAX_PROTECTED_EXPORTS_NAME_LEN))

/* bsearch() comparision callback */
static int cmp_name(const void *sym, const void *protected_sym)
{
	return strncmp(sym, protected_sym, MAX_STRCMP_LEN);
}

/**
 * gki_is_module_protected_export - Is a symbol exported from a protected GKI module?
 *
 * @name:	Symbol being checked against exported symbols from protected GKI modules
 */
bool gki_is_module_protected_export(const char *name)
{
	if (NR_UNPROTECTED_SYMBOLS) {
		return bsearch(name, gki_protected_exports_symbols, NR_PROTECTED_EXPORTS_SYMBOLS,
		       MAX_PROTECTED_EXPORTS_NAME_LEN, cmp_name) != NULL;
	} else {
		/*
		 * If there are no symbols in unprotected list; We don't need to
		 * protect exports as there is no KMI enforcement.
		 * Treat everything exportable in this case.
		 */
		return false;
	}
}

/**
 * gki_is_module_unprotected_symbol - Is a symbol unprotected for unsigned module?
 *
 * @name:	Symbol being checked in list of unprotected symbols
 */
bool gki_is_module_unprotected_symbol(const char *name)
{
	if (NR_UNPROTECTED_SYMBOLS) {
		return bsearch(name, gki_unprotected_symbols, NR_UNPROTECTED_SYMBOLS,
				MAX_UNPROTECTED_NAME_LEN, cmp_name) != NULL;
	} else {
		/*
		 * If there are no symbols in unprotected list;
		 * there isn't a KMI enforcement for the kernel.
		 * Treat everything accessible in this case.
		 */
		return true;
	}
}
