Add a tboot command line option that falls back to booting the kernel
directly instead of performing a measured launch, if the previous measured
launch failed.
 
This acts as a failsafe and prevents the system from going into an endless
reboot loop.
 
Testing:
Disable Vt-d on system. Boot without ignore_prev_err, and with
ignore_prev_err=true. Verify system keeps trying to boot and resets on SENTER.
Set ignore_prev_err=false. Verify tboot skips measured launch and transfers
control directly to the kernel. Soft reset system and verify error is not 
cleared. 
Power-cycle system and verify TXT error is cleared.
 
 
Signed-off-by: Sahil Rihan <sri...@fb.com>
 
 
diff --git a/README b/README
--- a/README
+++ b/README
@@ -272,6 +272,25 @@
    It means tboot will use this algorithm to compute hash and use 
TPM2_PCR_Extend
    to extend it into PCRs.
 
+o  Recovering from measured launch failures.
+   When there's an error during SENTER, the system usually reboots. Since the 
underlying
+   cause is some sort of configuration error, the system can end up in a loop 
+   rebooting endlessly after each attempted measured launch. In some 
environments it
+   make more sense to fall back to booting the kernel directly so that the 
system comes
+   up and is remotely accessible. After that the issue can be diagnosed and 
the system
+   power-cycled to clear the error. To enable this behavior a command line 
option can 
+   be used:
+          ignore_prev_err=false|true  // defaults to true
+
+   The option defaults to true, which preserves the original behavior i.e. try 
a measured
+   launch even if the previous measured launch had errors.
+
+   Setting the value to false will check if the previous measured launch was 
successful
+   by inspecting the TXT.ERRORCODE value. If measured launch failed, tboot 
will launch
+   the kernel directly without trying to perform a measured launch.
+
+   Note: TXT.ERRORCODE is only cleared if the system is power cycled. A reboot 
is not
+   sufficient to clear the error code.
 
 PCR Usage:
---------
diff --git a/include/tb_error.h b/include/tb_error.h
--- a/include/tb_error.h
+++ b/include/tb_error.h
@@ -66,6 +66,7 @@
     TB_ERR_FATAL,                           /* generic fatal error */
     TB_ERR_NV_VERIFICATION_FAILED,          /* NV failed to verify against
                                                policy */
+    TB_ERR_PREV_TXT_ERROR,                  /* previous measured launch failed 
*/
     TB_ERR_MAX
} tb_error_t;
 
diff --git a/tboot/common/cmdline.c b/tboot/common/cmdline.c
--- a/tboot/common/cmdline.c
+++ b/tboot/common/cmdline.c
@@ -83,7 +83,8 @@
     { "min_ram", "0" },              /* size in bytes | 0 for no min */
     { "call_racm", "false" },        /* true|false|check */
     { "measure_nv", "false" },       /* true|false */
-    { "extpol",    "sha1" },        /* agile|embedded|sha1|sha256|sm3|... */
+    { "extpol",    "sha1" },         /* agile|embedded|sha1|sha256|sm3|... */
+    { "ignore_prev_err", "true"},    /* true|false */
     { NULL, NULL }
};
static char 
g_tboot_param_values[ARRAY_SIZE(g_tboot_cmdline_options)][MAX_VALUE_LEN];
@@ -528,6 +529,15 @@
     }
}
 
+bool get_tboot_ignore_prev_err(void)
+{
+    const char *ignore_prev_err = get_option_val(g_tboot_cmdline_options,
+                                       g_tboot_param_values, 
"ignore_prev_err");
+    if ( ignore_prev_err == NULL || strcmp(ignore_prev_err, "true") == 0 )
+        return true;
+    return false;
+}
+
/*
  * linux kernel command line parsing
  */
diff --git a/tboot/common/policy.c b/tboot/common/policy.c
--- a/tboot/common/policy.c
+++ b/tboot/common/policy.c
@@ -97,6 +97,7 @@
     { TB_POLTYPE_CONT_NON_FATAL,               TB_POLACT_CONTINUE,
       {
           {TB_ERR_FATAL,                       TB_POLACT_HALT},
+          {TB_ERR_PREV_TXT_ERROR,              TB_POLACT_UNMEASURED_LAUNCH},
           {TB_ERR_TPM_NOT_READY,               TB_POLACT_UNMEASURED_LAUNCH},
           {TB_ERR_SMX_NOT_SUPPORTED,           TB_POLACT_UNMEASURED_LAUNCH},
           {TB_ERR_VMX_NOT_SUPPORTED,           TB_POLACT_UNMEASURED_LAUNCH},
diff --git a/tboot/common/tb_error.c b/tboot/common/tb_error.c
--- a/tboot/common/tb_error.c
+++ b/tboot/common/tb_error.c
@@ -114,6 +114,9 @@
         case TB_ERR_NV_VERIFICATION_FAILED:
             printk(TBOOT_ERR"verifying nv against policy failed.\n");
             break;
+        case TB_ERR_PREV_TXT_ERROR:
+            printk(TBOOT_ERR"previous measured launch had errors, skipping 
measured launch...\n");
+            break;
         default:
             printk(TBOOT_ERR"unknown error (%d).\n", error);
             break;
diff --git a/tboot/common/tboot.c b/tboot/common/tboot.c
--- a/tboot/common/tboot.c
+++ b/tboot/common/tboot.c
@@ -414,7 +414,10 @@
     apply_policy(err);
 
     /* print any errors on last boot, which must be from TXT launch */
-    txt_get_error();
+    txt_display_errors();
+    if (txt_has_error() && get_tboot_ignore_prev_err() == false) {
+        apply_policy(TB_ERR_PREV_TXT_ERROR);
+    }
 
     /* need to verify that platform can perform measured launch */
     err = verify_platform();
diff --git a/tboot/include/cmdline.h b/tboot/include/cmdline.h
--- a/tboot/include/cmdline.h
+++ b/tboot/include/cmdline.h
@@ -54,6 +54,7 @@
extern bool get_tboot_call_racm_check(void);
extern bool get_tboot_measure_nv(void);
extern void get_tboot_extpol(void);
+extern bool get_tboot_ignore_prev_err(void);
 
 /* for parse cmdline of linux kernel, say vga and mem */
extern void linux_parse_cmdline(const char *cmdline);
diff --git a/tboot/include/txt/txt.h b/tboot/include/txt/txt.h
--- a/tboot/include/txt/txt.h
+++ b/tboot/include/txt/txt.h
@@ -39,7 +39,8 @@
// #include <multiboot.h>
 
 extern bool txt_is_launched(void);
-extern bool txt_get_error(void);
+extern void txt_display_errors(void);
+extern bool txt_has_error(void);
extern void txt_get_racm_error(void);
extern tb_error_t supports_txt(void);
extern tb_error_t txt_verify_platform(void);
diff --git a/tboot/txt/errors.c b/tboot/txt/errors.c
--- a/tboot/txt/errors.c
+++ b/tboot/txt/errors.c
@@ -46,7 +46,7 @@
#include <txt/errorcode.h>
 
 
-static void display_errors(void)
+void txt_display_errors(void)
{
     txt_errorcode_t err;
     txt_ests_t ests;
@@ -58,7 +58,7 @@
      * display TXT.ERRORODE error
      */
     err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE);
-    if (err._raw == 0 || err._raw == 0xc0000001 || err._raw == 0xc0000009)
+    if (txt_has_error() == false)
         printk(TBOOT_INFO"TXT.ERRORCODE: 0x%Lx\n", err._raw);
     else
         printk(TBOOT_ERR"TXT.ERRORCODE: 0x%Lx\n", err._raw);
@@ -112,17 +112,16 @@
         printk(TBOOT_ERR"TXT.E2STS: 0x%Lx\n", e2sts._raw);
}
 
-bool txt_get_error(void)
+bool txt_has_error(void)
{
     txt_errorcode_t err;
 
-    display_errors();
-
     err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE);
-    if ( err.valid )
+    if (err._raw == 0 || err._raw == 0xc0000001 || err._raw == 0xc0000009) {
         return false;
-    else
+    } else {
         return true;
+    }
}
 
 #define CLASS_ACM_ENTRY 0x1
 
 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
tboot-devel mailing list
tboot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tboot-devel

Reply via email to