efi_loader: segfault in efi_clear_os_indications()

If we call efi_clear_os_indications() before initializing the memory store
for UEFI variables a NULL pointer dereference occurs.

The error was observed on the sandbox with:

    usb start
    host bind 0 sandbox.img
    load host 0:1 $kernel_addr_r helloworld.efi
    bootefi $kernel_addr_r

Here efi_resister_disk() failed due to an error in the BTRFS implementation.

Move the logic to clear EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED
to the rest of the capsule code.

If CONFIG_EFI_IGNORE_OSINDICATIONS=y, we should still clear the flag.
If OsIndications does not exist, we should not create it as it is owned by
the operating system.

Fixes: 149108a3eb59 ("efi_loader: clear OsIndications")
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 502bcfc..8301eed 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -1037,30 +1037,45 @@
 }
 
 /**
- * check_run_capsules - Check whether capsule update should run
+ * check_run_capsules() - check whether capsule update should run
  *
  * The spec says OsIndications must be set in order to run the capsule update
  * on-disk.  Since U-Boot doesn't support runtime SetVariable, allow capsules to
  * run explicitly if CONFIG_EFI_IGNORE_OSINDICATIONS is selected
+ *
+ * Return:	EFI_SUCCESS if update to run, EFI_NOT_FOUND otherwise
  */
-static bool check_run_capsules(void)
+static efi_status_t check_run_capsules(void)
 {
 	u64 os_indications;
 	efi_uintn_t size;
-	efi_status_t ret;
-
-	if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS))
-		return true;
+	efi_status_t r;
 
 	size = sizeof(os_indications);
-	ret = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid,
-				   NULL, &size, &os_indications, NULL);
-	if (ret == EFI_SUCCESS &&
-	    (os_indications
-	      & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED))
-		return true;
+	r = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid,
+				 NULL, &size, &os_indications, NULL);
+	if (r != EFI_SUCCESS || size != sizeof(os_indications))
+		return EFI_NOT_FOUND;
 
-	return false;
+	if (os_indications &
+	    EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) {
+		os_indications &=
+			~EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED;
+		r = efi_set_variable_int(L"OsIndications",
+					 &efi_global_variable_guid,
+					 EFI_VARIABLE_NON_VOLATILE |
+					 EFI_VARIABLE_BOOTSERVICE_ACCESS |
+					 EFI_VARIABLE_RUNTIME_ACCESS,
+					 sizeof(os_indications),
+					 &os_indications, false);
+		if (r != EFI_SUCCESS)
+			log_err("Setting %ls failed\n", L"OsIndications");
+		return EFI_SUCCESS;
+	} else if (IS_ENABLED(CONFIG_EFI_IGNORE_OSINDICATIONS)) {
+		return EFI_SUCCESS;
+	} else  {
+		return EFI_NOT_FOUND;
+	}
 }
 
 /**
@@ -1078,7 +1093,7 @@
 	unsigned int nfiles, index, i;
 	efi_status_t ret;
 
-	if (!check_run_capsules())
+	if (check_run_capsules() != EFI_SUCCESS)
 		return EFI_SUCCESS;
 
 	index = get_last_capsule();