Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65e62b50 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'efi-vars' from Matthew Garrett

* efi-vars:
  efivars: Improve variable validation
parents 6b4c555a 54b3a4d3
Loading
Loading
Loading
Loading
+30 −16
Original line number Original line Diff line number Diff line
@@ -192,19 +192,22 @@ utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
}
}


static bool
static bool
validate_device_path(struct efi_variable *var, int match, u8 *buffer, int len)
validate_device_path(struct efi_variable *var, int match, u8 *buffer,
		     unsigned long len)
{
{
	struct efi_generic_dev_path *node;
	struct efi_generic_dev_path *node;
	int offset = 0;
	int offset = 0;


	node = (struct efi_generic_dev_path *)buffer;
	node = (struct efi_generic_dev_path *)buffer;


	while (offset < len) {
	if (len < sizeof(*node))
		offset += node->length;

		if (offset > len)
		return false;
		return false;


	while (offset <= len - sizeof(*node) &&
	       node->length >= sizeof(*node) &&
		node->length <= len - offset) {
		offset += node->length;

		if ((node->type == EFI_DEV_END_PATH ||
		if ((node->type == EFI_DEV_END_PATH ||
		     node->type == EFI_DEV_END_PATH2) &&
		     node->type == EFI_DEV_END_PATH2) &&
		    node->sub_type == EFI_DEV_END_ENTIRE)
		    node->sub_type == EFI_DEV_END_ENTIRE)
@@ -222,7 +225,8 @@ validate_device_path(struct efi_variable *var, int match, u8 *buffer, int len)
}
}


static bool
static bool
validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len)
validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
		    unsigned long len)
{
{
	/* An array of 16-bit integers */
	/* An array of 16-bit integers */
	if ((len % 2) != 0)
	if ((len % 2) != 0)
@@ -232,19 +236,27 @@ validate_boot_order(struct efi_variable *var, int match, u8 *buffer, int len)
}
}


static bool
static bool
validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len)
validate_load_option(struct efi_variable *var, int match, u8 *buffer,
		     unsigned long len)
{
{
	u16 filepathlength;
	u16 filepathlength;
	int i, desclength = 0;
	int i, desclength = 0, namelen;

	namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));


	/* Either "Boot" or "Driver" followed by four digits of hex */
	/* Either "Boot" or "Driver" followed by four digits of hex */
	for (i = match; i < match+4; i++) {
	for (i = match; i < match+4; i++) {
		if (hex_to_bin(var->VariableName[i] & 0xff) < 0)
		if (var->VariableName[i] > 127 ||
		    hex_to_bin(var->VariableName[i] & 0xff) < 0)
			return true;
			return true;
	}
	}


	/* A valid entry must be at least 6 bytes */
	/* Reject it if there's 4 digits of hex and then further content */
	if (len < 6)
	if (namelen > match + 4)
		return false;

	/* A valid entry must be at least 8 bytes */
	if (len < 8)
		return false;
		return false;


	filepathlength = buffer[4] | buffer[5] << 8;
	filepathlength = buffer[4] | buffer[5] << 8;
@@ -253,7 +265,7 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len)
	 * There's no stored length for the description, so it has to be
	 * There's no stored length for the description, so it has to be
	 * found by hand
	 * found by hand
	 */
	 */
	desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len) + 2;
	desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;


	/* Each boot entry must have a descriptor */
	/* Each boot entry must have a descriptor */
	if (!desclength)
	if (!desclength)
@@ -275,7 +287,8 @@ validate_load_option(struct efi_variable *var, int match, u8 *buffer, int len)
}
}


static bool
static bool
validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len)
validate_uint16(struct efi_variable *var, int match, u8 *buffer,
		unsigned long len)
{
{
	/* A single 16-bit integer */
	/* A single 16-bit integer */
	if (len != 2)
	if (len != 2)
@@ -285,7 +298,8 @@ validate_uint16(struct efi_variable *var, int match, u8 *buffer, int len)
}
}


static bool
static bool
validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len)
validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
		      unsigned long len)
{
{
	int i;
	int i;


@@ -303,7 +317,7 @@ validate_ascii_string(struct efi_variable *var, int match, u8 *buffer, int len)
struct variable_validate {
struct variable_validate {
	char *name;
	char *name;
	bool (*validate)(struct efi_variable *var, int match, u8 *data,
	bool (*validate)(struct efi_variable *var, int match, u8 *data,
			 int len);
			 unsigned long len);
};
};


static const struct variable_validate variable_validate[] = {
static const struct variable_validate variable_validate[] = {
@@ -325,7 +339,7 @@ static const struct variable_validate variable_validate[] = {
};
};


static bool
static bool
validate_var(struct efi_variable *var, u8 *data, int len)
validate_var(struct efi_variable *var, u8 *data, unsigned long len)
{
{
	int i;
	int i;
	u16 *unicode_name = var->VariableName;
	u16 *unicode_name = var->VariableName;