Skip to content

Commit

Permalink
net: ipa: fix init header command validation
Browse files Browse the repository at this point in the history
[ Upstream commit b4afd4b ]

We use ipa_cmd_header_valid() to ensure certain values we will
program into hardware are within range, well in advance of when we
actually program them.  This way we avoid having to check for errors
when we actually program the hardware.

Unfortunately the dev_err() call for a bad offset value does not
supply the arguments to match the format specifiers properly.
Fix this.

There was also supposed to be a check to ensure the size to be
programmed fits in the field that holds it.  Add this missing check.

Rearrange the way we ensure the header table fits in overall IPA
memory range.

Finally, update ipa_cmd_table_valid() so the format of messages
printed for errors matches what's done in ipa_cmd_header_valid().

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
alexelder authored and gregkh committed Apr 10, 2021
1 parent 8a57256 commit 6304295
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions drivers/net/ipa/ipa_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,23 @@ bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem,
: field_max(IP_FLTRT_FLAGS_NHASH_ADDR_FMASK);
if (mem->offset > offset_max ||
ipa->mem_offset > offset_max - mem->offset) {
dev_err(dev, "IPv%c %s%s table region offset too large "
"(0x%04x + 0x%04x > 0x%04x)\n",
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter",
ipa->mem_offset, mem->offset, offset_max);
dev_err(dev, "IPv%c %s%s table region offset too large\n",
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
ipa->mem_offset, mem->offset, offset_max);

return false;
}

if (mem->offset > ipa->mem_size ||
mem->size > ipa->mem_size - mem->offset) {
dev_err(dev, "IPv%c %s%s table region out of range "
"(0x%04x + 0x%04x > 0x%04x)\n",
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter",
mem->offset, mem->size, ipa->mem_size);
dev_err(dev, "IPv%c %s%s table region out of range\n",
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
mem->offset, mem->size, ipa->mem_size);

return false;
}

Expand All @@ -205,22 +207,36 @@ static bool ipa_cmd_header_valid(struct ipa *ipa)
u32 size_max;
u32 size;

/* In ipa_cmd_hdr_init_local_add() we record the offset and size
* of the header table memory area. Make sure the offset and size
* fit in the fields that need to hold them, and that the entire
* range is within the overall IPA memory range.
*/
offset_max = field_max(HDR_INIT_LOCAL_FLAGS_HDR_ADDR_FMASK);
if (mem->offset > offset_max ||
ipa->mem_offset > offset_max - mem->offset) {
dev_err(dev, "header table region offset too large "
"(0x%04x + 0x%04x > 0x%04x)\n",
ipa->mem_offset + mem->offset, offset_max);
dev_err(dev, "header table region offset too large\n");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
ipa->mem_offset, mem->offset, offset_max);

return false;
}

size_max = field_max(HDR_INIT_LOCAL_FLAGS_TABLE_SIZE_FMASK);
size = ipa->mem[IPA_MEM_MODEM_HEADER].size;
size += ipa->mem[IPA_MEM_AP_HEADER].size;
if (mem->offset > ipa->mem_size || size > ipa->mem_size - mem->offset) {
dev_err(dev, "header table region out of range "
"(0x%04x + 0x%04x > 0x%04x)\n",
mem->offset, size, ipa->mem_size);

if (size > size_max) {
dev_err(dev, "header table region size too large\n");
dev_err(dev, " (0x%04x > 0x%08x)\n", size, size_max);

return false;
}
if (size > ipa->mem_size || mem->offset > ipa->mem_size - size) {
dev_err(dev, "header table region out of range\n");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
mem->offset, size, ipa->mem_size);

return false;
}

Expand Down

0 comments on commit 6304295

Please sign in to comment.