diff mbox series

[RFC,RESEND,06/10] keystore: add opal_get_variable runtime service

Message ID 20180801234042.6740-7-erichte@linux.ibm.com
State RFC
Headers show
Series Initial Implementation of Secure Boot Key Management support | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied

Commit Message

Eric Richter Aug. 1, 2018, 11:40 p.m. UTC
The opal_get_variable runtime service retrieves a variable's data from
the keystore list if the requested name (as a NULL-terminated string)
exists in the requested section (enum for ACTIVE_BANK vs UPDATE_QUEUE).

The kernel may query the size of a variable by calling this service by
passing a NULL buffer parameter, and the by-reference varsize parameter
will be set to the variable's data size if found. This will also occur
if the varsize parameter is smaller than the requested data's size, to
prevent overflows.

NOTE: Included in this patch is a hacky macro to switch on the section
enum, which is a behavior common to each of these runtime services. It
should probably be changed to a static or inline function in the future.

Signed-off-by: Eric Richter <erichte@linux.ibm.com>
---
 libstb/keystore.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

Stewart Smith March 4, 2019, 7:12 a.m. UTC | #1
Eric Richter <erichte@linux.ibm.com> writes:
> The opal_get_variable runtime service retrieves a variable's data from
> the keystore list if the requested name (as a NULL-terminated string)
> exists in the requested section (enum for ACTIVE_BANK vs UPDATE_QUEUE).
>
> The kernel may query the size of a variable by calling this service by
> passing a NULL buffer parameter, and the by-reference varsize parameter
> will be set to the variable's data size if found. This will also occur
> if the varsize parameter is smaller than the requested data's size, to
> prevent overflows.
>
> NOTE: Included in this patch is a hacky macro to switch on the section
> enum, which is a behavior common to each of these runtime services. It
> should probably be changed to a static or inline function in the future.
>
> Signed-off-by: Eric Richter <erichte@linux.ibm.com>
> ---
>  libstb/keystore.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)

I'll not spend much time looking at the details of this and the other
OPAL call implementations as I understand some design has changed.

I think my big points have been made elsewhere:
- documentation in doc/ for all formats and semantics
- ability to unit test and fuzz *everything*
- and the safety of each of the routines parsing anything.
diff mbox series

Patch

diff --git a/libstb/keystore.c b/libstb/keystore.c
index 7d6027ef..8e19dbb6 100644
--- a/libstb/keystore.c
+++ b/libstb/keystore.c
@@ -34,6 +34,57 @@  static bool keystore_ready = false; /* has the keystore been loaded? */
 // TODO: OPAL_UNSUPPORTED?
 #define CHECK_KEYSTORE_READY	if(!keystore_ready) {prlog(PR_ERR, "Ignoring call, keystore not ready\n"); return OPAL_RESOURCE; }
 
+// Translate the enum into a bank list pointer
+#define GET_BANK(a) ((a&ACTIVE_BANK)?&active_bank_list:(((a&UPDATE_QUEUE)?&update_queue_list:NULL)))
+
+
+static int64_t opal_get_variable(uint64_t k_buffer, uint64_t k_varsize, uint64_t k_varname, uint64_t section)
+{
+	// Outputs
+	char *buffer = (char*) k_buffer;
+	uint64_t *varsize = (uint64_t*) k_varsize;
+	// Inputs
+	char *varname = (char*) k_varname;
+	struct list_head *bank;
+
+	struct keystore_variable *var = NULL;
+
+	CHECK_KEYSTORE_READY;
+
+	if (!varsize) {
+		prlog(PR_INFO, "Variable size parameter is NULL\n");
+		return OPAL_PARAMETER;
+	}
+
+	bank = GET_BANK(section);
+	if (!bank) {
+		prlog(PR_INFO, "Invalid section '%lld'\n", section);
+		return OPAL_PARAMETER;
+	}
+
+	list_for_each(bank, var, link) {
+		if (!strcmp(varname, var->name)) {
+			goto found;
+		}
+	}
+
+	prlog(PR_DEBUG, "No matching variable found for name '%s' in bank %lld\n", varname, section);
+	return OPAL_EMPTY;
+
+found:
+	// Check if this is a size query, or buffer is too small
+	if ((NULL == buffer) || (*varsize < var->data_size)) {
+		prlog(PR_DEBUG, "NULL/insufficient size check, returning varsize = %llu\n", var->data_size);
+		*varsize = var->data_size;
+		return OPAL_PARTIAL;
+	}
+
+	memcpy(buffer, var->data, var->data_size);
+	*varsize = var->data_size;
+
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_GET_VARIABLE, opal_get_variable, 4);
 
 
 int keystore_init(void)