Message ID | 1524662285-19617-6-git-send-email-igor.opaniuk@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | Initial integration of AVB2.0 | expand |
On 25 April 2018 at 16:18, Igor Opaniuk <igor.opaniuk@linaro.org> wrote: > 1. Add initial support of boot states mode (red, green, yellow) > 2. Add functions for enforcing dm-verity configurations > > Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org> > --- > cmd/avb.c | 17 ++++++- > common/avb_verify.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++-- > include/avb_verify.h | 19 ++++++- > 3 files changed, 171 insertions(+), 5 deletions(-) > > diff --git a/cmd/avb.c b/cmd/avb.c > index d040906..2c15b47 100644 > --- a/cmd/avb.c > +++ b/cmd/avb.c > @@ -218,6 +218,8 @@ int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag, > { > AvbSlotVerifyResult slot_result; > AvbSlotVerifyData *out_data; > + char *cmdline; > + char *extra_args; > > bool unlocked = false; > int res = CMD_RET_FAILURE; > @@ -243,10 +245,23 @@ int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag, > "", unlocked, &out_data); > switch (slot_result) { > case AVB_SLOT_VERIFY_RESULT_OK: > + /* Until we don't have support of changing unlock states, we > + * assume that we are by default in locked state. > + * So in this case we can boot only when verification is > + * successful; we also supply in cmdline GREEN boot state > + */ > printf("Verification passed successfully\n"); > > /* export additional bootargs to AVB_BOOTARGS env var */ > - env_set(AVB_BOOTARGS, out_data->cmdline); > + > + extra_args = avb_set_state(avb_ops, AVB_GREEN); > + if (extra_args) > + cmdline = append_cmd_line(out_data->cmdline, > + extra_args); > + else > + cmdline = out_data->cmdline; > + > + env_set(AVB_BOOTARGS, cmdline); > > res = CMD_RET_SUCCESS; > break; > diff --git a/common/avb_verify.c b/common/avb_verify.c > index b3d1229..df5e407 100644 > --- a/common/avb_verify.c > +++ b/common/avb_verify.c > @@ -119,6 +119,140 @@ const unsigned char avb_root_pub[1032] = { > > /** > * ============================================================================ > + * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity > + * ============================================================================ > + */ > +char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state) > +{ > + struct AvbOpsData *data; > + char *cmdline = NULL; > + > + if (!ops) > + return NULL; > + > + data = (struct AvbOpsData *)ops->user_data; > + if (!data) > + return NULL; > + > + data->boot_state = boot_state; > + switch (boot_state) { > + case AVB_GREEN: > + cmdline = "androidboot.verifiedbootstate=green"; > + break; > + case AVB_YELLOW: > + cmdline = "androidboot.verifiedbootstate=yellow"; > + break; > + case AVB_ORANGE: > + cmdline = "androidboot.verifiedbootstate=orange"; > + case AVB_RED: > + break; > + } > + > + return cmdline; > +} > + > +char *append_cmd_line(char *cmdline_orig, char *cmdline_new) > +{ > + char *cmd_line; > + > + if (!cmdline_new) > + return cmdline_orig; > + > + if (cmdline_orig) > + cmd_line = cmdline_orig; > + else > + cmd_line = " "; > + > + cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL); > + > + return cmd_line; > +} > + > +static int avb_find_dm_args(char **args, char *str) > +{ > + int i = 0; > + > + if (!str) > + return -1; > + > + do { > + if ((!args[i]) || (i >= AVB_MAX_ARGS)) Conditions probably should be swapped, to avoid "index out of bounds" error. > + return -1; > + > + if (strstr(args[i], str)) > + return i; > + > + i++; > + } while (1); > +} Just a suggestion: wouldn't it be better to use "for" instead of "do/while" here? Like this: for (i = 0; i < AVB_MAX_ARGS, args[i]; ++i) { if (strstr(args[i], str)) return i; } return -1; > + > +static char *avb_set_enforce_option(const char *cmdline, const char *option) > +{ > + char *cmdarg[AVB_MAX_ARGS]; > + char *newargs = NULL; > + int i = 0; > + int total_args; > + > + memset(cmdarg, 0, sizeof(cmdarg)); > + cmdarg[i++] = strtok((char *)cmdline, " "); > + > + do { > + cmdarg[i] = strtok(NULL, " "); > + if (!cmdarg[i]) > + break; > + > + if (++i >= AVB_MAX_ARGS) { > + printf("%s: Can't handle more then %d args\n", > + __func__, i); > + return NULL; > + } > + } while (true); > + > + total_args = i; > + i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING); > + if (i >= 0) { > + cmdarg[i] = (char *)option; > + } else { > + i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART); > + if (i < 0) { > + printf("%s: No verity options found\n", __func__); > + return NULL; > + } > + > + cmdarg[i] = (char *)option; > + } > + > + for (i = 0; i <= total_args; i++) > + newargs = append_cmd_line(newargs, cmdarg[i]); > + > + return newargs; > +} > + > +char *avb_set_ignore_corruption(const char *cmdline) > +{ > + char *newargs = NULL; > + > + newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING); > + if (newargs) > + newargs = append_cmd_line(newargs, > + "androidboot.veritymode=eio"); > + > + return newargs; > +} > + > +char *avb_set_enforce_verity(const char *cmdline) > +{ > + char *newargs; > + > + newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART); > + if (newargs) > + newargs = append_cmd_line(newargs, > + "androidboot.veritymode=enforcing"); > + return newargs; > +} > + > +/** > + * ============================================================================ > * IO(mmc) auxiliary functions > * ============================================================================ > */ > @@ -478,7 +612,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops, > u64 *out_rollback_index) > { > /* For now we always return 0 as the stored rollback index. */ > - printf("TODO: implement %s.\n", __func__); > + printf("%s not supported yet\n", __func__); > > if (out_rollback_index) > *out_rollback_index = 0; > @@ -502,7 +636,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops, > u64 rollback_index) > { > /* For now this is a no-op. */ > - printf("TODO: implement %s.\n", __func__); > + printf("%s not supported yet\n", __func__); > > return AVB_IO_RESULT_OK; > } > @@ -522,7 +656,7 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) > { > /* For now we always return that the device is unlocked. */ > > - printf("TODO: implement %s.\n", __func__); > + printf("%s not supported yet\n", __func__); > > *out_is_unlocked = true; > > diff --git a/include/avb_verify.h b/include/avb_verify.h > index fb7ab23..9363ca5 100644 > --- a/include/avb_verify.h > +++ b/include/avb_verify.h > @@ -11,12 +11,23 @@ > #include <avb/libavb_ab.h> > #include <mmc.h> > > -#define ALLOWED_BUF_ALIGN 8 > +#define AVB_MAX_ARGS 1024 > +#define VERITY_TABLE_OPT_RESTART "restart_on_corruption" > +#define VERITY_TABLE_OPT_LOGGING "ignore_corruption" > +#define ALLOWED_BUF_ALIGN 8 > + > +enum avb_boot_state { > + AVB_GREEN, > + AVB_YELLOW, > + AVB_ORANGE, > + AVB_RED, > +}; > > struct AvbOpsData { > struct AvbOps ops; > struct AvbABOps ab_ops; > int mmc_dev; > + enum avb_boot_state boot_state; > }; > > struct mmc_part { > @@ -34,6 +45,12 @@ enum mmc_io_type { > AvbOps *avb_ops_alloc(int boot_device); > void avb_ops_free(AvbOps *ops); > > +char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state); > +char *avb_set_enforce_verity(const char *cmdline); > +char *avb_set_ignore_corruption(const char *cmdline); > + > +char *append_cmd_line(char *cmdline_orig, char *cmdline_new); > + > /** > * ============================================================================ > * I/O helper inline functions > -- > 2.7.4 >
diff --git a/cmd/avb.c b/cmd/avb.c index d040906..2c15b47 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -218,6 +218,8 @@ int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag, { AvbSlotVerifyResult slot_result; AvbSlotVerifyData *out_data; + char *cmdline; + char *extra_args; bool unlocked = false; int res = CMD_RET_FAILURE; @@ -243,10 +245,23 @@ int do_avb_verify_part(cmd_tbl_t *cmdtp, int flag, "", unlocked, &out_data); switch (slot_result) { case AVB_SLOT_VERIFY_RESULT_OK: + /* Until we don't have support of changing unlock states, we + * assume that we are by default in locked state. + * So in this case we can boot only when verification is + * successful; we also supply in cmdline GREEN boot state + */ printf("Verification passed successfully\n"); /* export additional bootargs to AVB_BOOTARGS env var */ - env_set(AVB_BOOTARGS, out_data->cmdline); + + extra_args = avb_set_state(avb_ops, AVB_GREEN); + if (extra_args) + cmdline = append_cmd_line(out_data->cmdline, + extra_args); + else + cmdline = out_data->cmdline; + + env_set(AVB_BOOTARGS, cmdline); res = CMD_RET_SUCCESS; break; diff --git a/common/avb_verify.c b/common/avb_verify.c index b3d1229..df5e407 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -119,6 +119,140 @@ const unsigned char avb_root_pub[1032] = { /** * ============================================================================ + * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity + * ============================================================================ + */ +char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state) +{ + struct AvbOpsData *data; + char *cmdline = NULL; + + if (!ops) + return NULL; + + data = (struct AvbOpsData *)ops->user_data; + if (!data) + return NULL; + + data->boot_state = boot_state; + switch (boot_state) { + case AVB_GREEN: + cmdline = "androidboot.verifiedbootstate=green"; + break; + case AVB_YELLOW: + cmdline = "androidboot.verifiedbootstate=yellow"; + break; + case AVB_ORANGE: + cmdline = "androidboot.verifiedbootstate=orange"; + case AVB_RED: + break; + } + + return cmdline; +} + +char *append_cmd_line(char *cmdline_orig, char *cmdline_new) +{ + char *cmd_line; + + if (!cmdline_new) + return cmdline_orig; + + if (cmdline_orig) + cmd_line = cmdline_orig; + else + cmd_line = " "; + + cmd_line = avb_strdupv(cmd_line, " ", cmdline_new, NULL); + + return cmd_line; +} + +static int avb_find_dm_args(char **args, char *str) +{ + int i = 0; + + if (!str) + return -1; + + do { + if ((!args[i]) || (i >= AVB_MAX_ARGS)) + return -1; + + if (strstr(args[i], str)) + return i; + + i++; + } while (1); +} + +static char *avb_set_enforce_option(const char *cmdline, const char *option) +{ + char *cmdarg[AVB_MAX_ARGS]; + char *newargs = NULL; + int i = 0; + int total_args; + + memset(cmdarg, 0, sizeof(cmdarg)); + cmdarg[i++] = strtok((char *)cmdline, " "); + + do { + cmdarg[i] = strtok(NULL, " "); + if (!cmdarg[i]) + break; + + if (++i >= AVB_MAX_ARGS) { + printf("%s: Can't handle more then %d args\n", + __func__, i); + return NULL; + } + } while (true); + + total_args = i; + i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_LOGGING); + if (i >= 0) { + cmdarg[i] = (char *)option; + } else { + i = avb_find_dm_args(&cmdarg[0], VERITY_TABLE_OPT_RESTART); + if (i < 0) { + printf("%s: No verity options found\n", __func__); + return NULL; + } + + cmdarg[i] = (char *)option; + } + + for (i = 0; i <= total_args; i++) + newargs = append_cmd_line(newargs, cmdarg[i]); + + return newargs; +} + +char *avb_set_ignore_corruption(const char *cmdline) +{ + char *newargs = NULL; + + newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_LOGGING); + if (newargs) + newargs = append_cmd_line(newargs, + "androidboot.veritymode=eio"); + + return newargs; +} + +char *avb_set_enforce_verity(const char *cmdline) +{ + char *newargs; + + newargs = avb_set_enforce_option(cmdline, VERITY_TABLE_OPT_RESTART); + if (newargs) + newargs = append_cmd_line(newargs, + "androidboot.veritymode=enforcing"); + return newargs; +} + +/** + * ============================================================================ * IO(mmc) auxiliary functions * ============================================================================ */ @@ -478,7 +612,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops, u64 *out_rollback_index) { /* For now we always return 0 as the stored rollback index. */ - printf("TODO: implement %s.\n", __func__); + printf("%s not supported yet\n", __func__); if (out_rollback_index) *out_rollback_index = 0; @@ -502,7 +636,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops, u64 rollback_index) { /* For now this is a no-op. */ - printf("TODO: implement %s.\n", __func__); + printf("%s not supported yet\n", __func__); return AVB_IO_RESULT_OK; } @@ -522,7 +656,7 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) { /* For now we always return that the device is unlocked. */ - printf("TODO: implement %s.\n", __func__); + printf("%s not supported yet\n", __func__); *out_is_unlocked = true; diff --git a/include/avb_verify.h b/include/avb_verify.h index fb7ab23..9363ca5 100644 --- a/include/avb_verify.h +++ b/include/avb_verify.h @@ -11,12 +11,23 @@ #include <avb/libavb_ab.h> #include <mmc.h> -#define ALLOWED_BUF_ALIGN 8 +#define AVB_MAX_ARGS 1024 +#define VERITY_TABLE_OPT_RESTART "restart_on_corruption" +#define VERITY_TABLE_OPT_LOGGING "ignore_corruption" +#define ALLOWED_BUF_ALIGN 8 + +enum avb_boot_state { + AVB_GREEN, + AVB_YELLOW, + AVB_ORANGE, + AVB_RED, +}; struct AvbOpsData { struct AvbOps ops; struct AvbABOps ab_ops; int mmc_dev; + enum avb_boot_state boot_state; }; struct mmc_part { @@ -34,6 +45,12 @@ enum mmc_io_type { AvbOps *avb_ops_alloc(int boot_device); void avb_ops_free(AvbOps *ops); +char *avb_set_state(AvbOps *ops, enum avb_boot_state boot_state); +char *avb_set_enforce_verity(const char *cmdline); +char *avb_set_ignore_corruption(const char *cmdline); + +char *append_cmd_line(char *cmdline_orig, char *cmdline_new); + /** * ============================================================================ * I/O helper inline functions
1. Add initial support of boot states mode (red, green, yellow) 2. Add functions for enforcing dm-verity configurations Signed-off-by: Igor Opaniuk <igor.opaniuk@linaro.org> --- cmd/avb.c | 17 ++++++- common/avb_verify.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++-- include/avb_verify.h | 19 ++++++- 3 files changed, 171 insertions(+), 5 deletions(-)