Commit f2c1dac0 authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: fix ipa_cmd_table_valid()

Stop supporting different sizes for hashed and non-hashed filter or
route tables.  Add BUILD_BUG_ON() calls to verify the sizes of the
fields in the filter/route table initialization immediate command
are the same.

Add a check to ipa_cmd_table_valid() to ensure the size of the
memory region being checked fits within the immediate command field
that must hold it.

Remove two Boolean parameters used only for error reporting.  This
actually fixes a bug that would only show up if IPA_VALIDATE were
defined.  Define ipa_cmd_table_valid() unconditionally (no longer
dependent on IPA_VALIDATE).
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent beeee08c
...@@ -159,35 +159,45 @@ static void ipa_cmd_validate_build(void) ...@@ -159,35 +159,45 @@ static void ipa_cmd_validate_build(void)
BUILD_BUG_ON(TABLE_SIZE > field_max(IP_FLTRT_FLAGS_NHASH_SIZE_FMASK)); BUILD_BUG_ON(TABLE_SIZE > field_max(IP_FLTRT_FLAGS_NHASH_SIZE_FMASK));
#undef TABLE_COUNT_MAX #undef TABLE_COUNT_MAX
#undef TABLE_SIZE #undef TABLE_SIZE
}
#ifdef IPA_VALIDATE /* Hashed and non-hashed fields are assumed to be the same size */
BUILD_BUG_ON(field_max(IP_FLTRT_FLAGS_HASH_SIZE_FMASK) !=
field_max(IP_FLTRT_FLAGS_NHASH_SIZE_FMASK));
BUILD_BUG_ON(field_max(IP_FLTRT_FLAGS_HASH_ADDR_FMASK) !=
field_max(IP_FLTRT_FLAGS_NHASH_ADDR_FMASK));
}
/* Validate a memory region holding a table */ /* Validate a memory region holding a table */
bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem, bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem, bool route)
bool route, bool ipv6, bool hashed)
{ {
u32 offset_max = field_max(IP_FLTRT_FLAGS_NHASH_ADDR_FMASK);
u32 size_max = field_max(IP_FLTRT_FLAGS_NHASH_SIZE_FMASK);
const char *table = route ? "route" : "filter";
struct device *dev = &ipa->pdev->dev; struct device *dev = &ipa->pdev->dev;
u32 offset_max;
offset_max = hashed ? field_max(IP_FLTRT_FLAGS_HASH_ADDR_FMASK) /* Size must fit in the immediate command field that holds it */
: field_max(IP_FLTRT_FLAGS_NHASH_ADDR_FMASK); if (mem->size > size_max) {
dev_err(dev, "%s table region size too large\n", table);
dev_err(dev, " (0x%04x > 0x%04x)\n",
mem->size, size_max);
return false;
}
/* Offset must fit in the immediate command field that holds it */
if (mem->offset > offset_max || if (mem->offset > offset_max ||
ipa->mem_offset > offset_max - mem->offset) { ipa->mem_offset > offset_max - mem->offset) {
dev_err(dev, "IPv%c %s%s table region offset too large\n", dev_err(dev, "%s table region offset too large\n", table);
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n", dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
ipa->mem_offset, mem->offset, offset_max); ipa->mem_offset, mem->offset, offset_max);
return false; return false;
} }
/* Entire memory range must fit within IPA-local memory */
if (mem->offset > ipa->mem_size || if (mem->offset > ipa->mem_size ||
mem->size > ipa->mem_size - mem->offset) { mem->size > ipa->mem_size - mem->offset) {
dev_err(dev, "IPv%c %s%s table region out of range\n", dev_err(dev, "%s table region out of range\n", table);
ipv6 ? '6' : '4', hashed ? "hashed " : "",
route ? "route" : "filter");
dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n", dev_err(dev, " (0x%04x + 0x%04x > 0x%04x)\n",
mem->offset, mem->size, ipa->mem_size); mem->offset, mem->size, ipa->mem_size);
...@@ -197,6 +207,8 @@ bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem, ...@@ -197,6 +207,8 @@ bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem,
return true; return true;
} }
#ifdef IPA_VALIDATE
/* Validate the memory region that holds headers */ /* Validate the memory region that holds headers */
static bool ipa_cmd_header_valid(struct ipa *ipa) static bool ipa_cmd_header_valid(struct ipa *ipa)
{ {
......
...@@ -57,20 +57,18 @@ struct ipa_cmd_info { ...@@ -57,20 +57,18 @@ struct ipa_cmd_info {
enum dma_data_direction direction; enum dma_data_direction direction;
}; };
#ifdef IPA_VALIDATE
/** /**
* ipa_cmd_table_valid() - Validate a memory region holding a table * ipa_cmd_table_valid() - Validate a memory region holding a table
* @ipa: - IPA pointer * @ipa: - IPA pointer
* @mem: - IPA memory region descriptor * @mem: - IPA memory region descriptor
* @route: - Whether the region holds a route or filter table * @route: - Whether the region holds a route or filter table
* @ipv6: - Whether the table is for IPv6 or IPv4
* @hashed: - Whether the table is hashed or non-hashed
* *
* Return: true if region is valid, false otherwise * Return: true if region is valid, false otherwise
*/ */
bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem, bool ipa_cmd_table_valid(struct ipa *ipa, const struct ipa_mem *mem,
bool route, bool ipv6, bool hashed); bool route);
#ifdef IPA_VALIDATE
/** /**
* ipa_cmd_data_valid() - Validate command-realted configuration is valid * ipa_cmd_data_valid() - Validate command-realted configuration is valid
...@@ -82,13 +80,6 @@ bool ipa_cmd_data_valid(struct ipa *ipa); ...@@ -82,13 +80,6 @@ bool ipa_cmd_data_valid(struct ipa *ipa);
#else /* !IPA_VALIDATE */ #else /* !IPA_VALIDATE */
static inline bool ipa_cmd_table_valid(struct ipa *ipa,
const struct ipa_mem *mem, bool route,
bool ipv6, bool hashed)
{
return true;
}
static inline bool ipa_cmd_data_valid(struct ipa *ipa) static inline bool ipa_cmd_data_valid(struct ipa *ipa)
{ {
return true; return true;
......
...@@ -161,7 +161,7 @@ ipa_table_valid_one(struct ipa *ipa, enum ipa_mem_id mem_id, bool route) ...@@ -161,7 +161,7 @@ ipa_table_valid_one(struct ipa *ipa, enum ipa_mem_id mem_id, bool route)
else else
size = (1 + IPA_FILTER_COUNT_MAX) * sizeof(__le64); size = (1 + IPA_FILTER_COUNT_MAX) * sizeof(__le64);
if (!ipa_cmd_table_valid(ipa, mem, route, ipv6, hashed)) if (!ipa_cmd_table_valid(ipa, mem, route))
return false; return false;
/* mem->size >= size is sufficient, but we'll demand more */ /* mem->size >= size is sufficient, but we'll demand more */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment