[RFC,RESEND,10/10] keystore: add experimental opal_lock_variables runtime service

Message ID 20180801234042.6740-11-erichte@linux.ibm.com
State New
Headers show
Series
  • Initial Implementation of Secure Boot Key Management support
Related show

Checks

Context Check Description
snowpatch_ozlabs/make_check success Test make_check on branch master
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied

Commit Message

Eric Richter Aug. 1, 2018, 11:40 p.m.
The opal_lock_variables runtime service can be called to lock specific
operations until the next full reboot. For example, it could be called
to write lock the keystore in-memory copy until the next full reboot.
Currently, only opal_set_variable and opal_secboot_commit are able to
write-locked.

NOTE: This is a very drafty patch. It is currently unknown if this
feature is even necessary, or if it even protects anything. The intended
use is to lock down the in-memory keystore after the update queue has
been processed in early skiroot, so that subsequent kernels can no
longer manipulate the in-memory keystore or secboot partition beyond
writes to the update queue.

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

Patch

diff --git a/libstb/keystore.c b/libstb/keystore.c
index 1c853380..34e5b72e 100644
--- a/libstb/keystore.c
+++ b/libstb/keystore.c
@@ -30,6 +30,7 @@  static struct list_head active_bank_list = LIST_HEAD_INIT(active_bank_list);
 static struct list_head update_queue_list = LIST_HEAD_INIT(update_queue_list);
 
 static bool keystore_ready = false; /* has the keystore been loaded? */
+static int active_lock = 0;
 
 // TODO: OPAL_UNSUPPORTED?
 #define CHECK_KEYSTORE_READY	if(!keystore_ready) {prlog(PR_ERR, "Ignoring call, keystore not ready\n"); return OPAL_RESOURCE; }
@@ -100,6 +101,11 @@  static int64_t opal_set_variable(uint64_t k_varname, uint64_t k_vardata, uint64_
 
 	bank = GET_BANK(section);
 
+	if ((section == ACTIVE_BANK) && (active_lock)) {
+		prlog(PR_ERR, "Variable Bank has been locked, refusing to update variable\n");
+		return OPAL_RESOURCE;
+	}
+
 	list_for_each(bank, var, link) {
 		if (!strcmp(varname, var->name)) {
 			goto found;
@@ -197,7 +203,6 @@  static int64_t opal_get_next_variable(uint64_t k_varname, uint64_t k_size, uint6
 }
 opal_call(OPAL_GET_NEXT_VARIABLE, opal_get_next_variable, 3);
 
-
 // Cleanup function to empty out a bank list
 static void clear_bank_list(struct list_head *head)
 {
@@ -218,7 +223,7 @@  static int64_t opal_secboot_commit(uint64_t section)
 
 	CHECK_KEYSTORE_READY;
 
-	if (section & ACTIVE_BANK) {
+	if ((section & ACTIVE_BANK) && (!active_lock)) {
 		ret = secboot_part_serialize_and_write(&active_bank_list, ACTIVE_BANK);
 	}
 
@@ -237,6 +242,24 @@  static int64_t opal_secboot_commit(uint64_t section)
 opal_call(OPAL_SECBOOT_COMMIT, opal_secboot_commit, 1);
 
 
+
+// TODO: Determine and implement actual R/W mode locks
+static int64_t opal_lock_variables(uint64_t section, uint64_t mode)
+{
+	(void) mode;
+
+	CHECK_KEYSTORE_READY;
+
+	if (section == ACTIVE_BANK) {
+		active_lock = 1;
+	}
+
+	return OPAL_SUCCESS;
+}
+opal_call(OPAL_LOCK_VARIABLES, opal_lock_variables, 2);
+
+
+
 int keystore_init(void)
 {
 	int rc;
@@ -265,6 +288,7 @@  int keystore_init(void)
 	}
 
 	keystore_ready = true;
+	active_lock = 0;
 
 	prlog(PR_INFO, "Keystore initialized successfully\n");