g: extension: Add a whitelist for vendor commands.

The USB FW upgrade endpoint should really only accept vendor commands
required to perform the firmware update.  This commit adds a whitelist
that is checked whenever a vendor command is received over this
endpoint.

The allowed commands over USB are the following:

 - EXTENSION_POST_RESET
 - VENDOR_CC_IMMEDIATE_RESET (only for dev images)

There is also functionality to have a whitelist for vendor commands that
come over the TPM interface.

BUG=chrome-os-partner:62815
BRANCH=None
TEST=Flash Cr50 with image containing this change.  Verify that an
upgrade over USB to newer image works.
TEST=Try using usb_updater to send a vendor command that's not in the
whitelist.  Verify that the vendor command is dropped.

Change-Id: I71f8ba090a1cc6c9e7c30ce0dd3c25259e8f292f
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/443447
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
This commit is contained in:
Aseda Aboagye
2017-02-15 16:56:10 -08:00
committed by chrome-bot
parent 4ed4044329
commit 114f5cee5a
4 changed files with 67 additions and 19 deletions

View File

@@ -152,11 +152,11 @@ static int try_vendor_command(struct consumer const *consumer, size_t count)
queue_advance_head(consumer->queue, count);
subcommand = (uint16_t *)(cmd_buffer + 1);
extension_route_command(be16toh(*subcommand),
subcommand + 1,
count -
sizeof(struct update_frame_header),
&response_size);
usb_extension_route_command(be16toh(*subcommand),
subcommand + 1,
count -
sizeof(struct update_frame_header),
&response_size);
QUEUE_ADD_UNITS(&upgrade_to_usb, subcommand + 1, response_size);
}

View File

@@ -10,10 +10,10 @@
#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
uint32_t extension_route_command(uint16_t command_code,
void *buffer,
size_t in_size,
size_t *out_size)
static uint32_t extension_route_command(uint16_t command_code,
void *buffer,
size_t in_size,
size_t *out_size)
{
struct extension_command *cmd_p;
struct extension_command *end_p;
@@ -34,3 +34,43 @@ uint32_t extension_route_command(uint16_t command_code,
*out_size = 0;
return VENDOR_RC_NO_SUCH_COMMAND;
}
uint32_t usb_extension_route_command(uint16_t command_code,
void *buffer,
size_t in_size,
size_t *out_size)
{
int is_allowed = 0;
switch (command_code) {
#ifdef CR50_DEV
case VENDOR_CC_IMMEDIATE_RESET:
#endif /* defined(CR50_DEV) */
case EXTENSION_POST_RESET: /* Always need to be able to reset. */
is_allowed = 1;
break;
default:
break;
}
if (is_allowed)
return extension_route_command(command_code, buffer, in_size,
out_size);
/* Otherwise, we don't allow this command. */
CPRINTF("%s: ignoring vendor cmd %d\n", __func__, command_code);
*out_size = 0;
return VENDOR_RC_NO_SUCH_COMMAND;
}
uint32_t tpm_extension_route_command(uint16_t command_code,
void *buffer,
size_t in_size,
size_t *out_size)
{
/*
* TODO(aaboagye): Determine what commands (if any) should be filtered.
*/
return extension_route_command(command_code, buffer, in_size, out_size);
}

View File

@@ -626,11 +626,11 @@ static void call_extension_command(struct tpm_cmd_header *tpmh,
*total_size -= sizeof(struct tpm_cmd_header);
subcommand_code = be16toh(tpmh->subcommand_code);
rc = extension_route_command(subcommand_code,
tpmh + 1,
command_size -
sizeof(struct tpm_cmd_header),
total_size);
rc = tpm_extension_route_command(subcommand_code,
tpmh + 1,
command_size -
sizeof(struct tpm_cmd_header),
total_size);
/* Add the header size back. */
*total_size += sizeof(struct tpm_cmd_header);
tpmh->size = htobe32(*total_size);

View File

@@ -26,8 +26,12 @@ typedef enum vendor_cmd_rc (*extension_handler)(enum vendor_cmd_cc code,
size_t command_size,
size_t *response_size);
/*
/**
* Find handler for an extension command.
*
* Use the interface specific function call in order to check the policies for
* handling the commands on that interface.
*
* @param command_code Code associated with a extension command handler.
* @param buffer Data to be processd by the handler, the same space
* is used for data returned by the handler.
@@ -36,10 +40,14 @@ typedef enum vendor_cmd_rc (*extension_handler)(enum vendor_cmd_cc code,
* data returned by the handler. A single byte return
* usually indicates an error and contains the error code.
*/
uint32_t extension_route_command(uint16_t command_code,
void *buffer,
size_t command_size,
size_t *size);
uint32_t usb_extension_route_command(uint16_t command_code,
void *buffer,
size_t command_size,
size_t *size);
uint32_t tpm_extension_route_command(uint16_t command_code,
void *buffer,
size_t command_size,
size_t *size);
/* Pointer table */
struct extension_command {