greybus: operation: rate-limit dev_err printing on the receive path
When we receive Greybus operations we don't recognize, requests or responses, en masse, we can pile up a lot of dev_err() printk messages. Doing so along the gb_connection_recv() code path can delay receive processing by up to seven milliseconds, starving the system of bulk-IN urbs. Rate limit those printk messages, ensuring that after too many repeated errors at the same place in the code-path, we'll stop printing to the console at all and let the urbs get returned. This will help prevent denial-of-service attacks on the AP through the UniPro network from malicious or malfunctioning modules. Testing Done: 7 msec recv-to-resubmit-urb processing times go down to <20 usecs Signed-off-by: Eli Sennesh <esennesh@leaflabs.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reviewed-by: Mitchell Tasman <tasman@leaflabs.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
3a238fc784
commit
b0e97bce15
@ -891,7 +891,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
|
|||||||
size_t message_size;
|
size_t message_size;
|
||||||
|
|
||||||
if (!operation_id) {
|
if (!operation_id) {
|
||||||
dev_err(&connection->hd->dev,
|
dev_err_ratelimited(&connection->hd->dev,
|
||||||
"%s: invalid response id 0 received\n",
|
"%s: invalid response id 0 received\n",
|
||||||
connection->name);
|
connection->name);
|
||||||
return;
|
return;
|
||||||
@ -899,9 +899,9 @@ static void gb_connection_recv_response(struct gb_connection *connection,
|
|||||||
|
|
||||||
operation = gb_operation_find_outgoing(connection, operation_id);
|
operation = gb_operation_find_outgoing(connection, operation_id);
|
||||||
if (!operation) {
|
if (!operation) {
|
||||||
dev_err(&connection->hd->dev,
|
dev_err_ratelimited(&connection->hd->dev,
|
||||||
"%s: unexpected response id 0x%04x received\n",
|
"%s: unexpected response id 0x%04x received\n",
|
||||||
connection->name, operation_id);
|
connection->name, operation_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,7 +909,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
|
|||||||
header = message->header;
|
header = message->header;
|
||||||
message_size = sizeof(*header) + message->payload_size;
|
message_size = sizeof(*header) + message->payload_size;
|
||||||
if (!errno && size > message_size) {
|
if (!errno && size > message_size) {
|
||||||
dev_err(&connection->hd->dev,
|
dev_err_ratelimited(&connection->hd->dev,
|
||||||
"%s: malformed response 0x%02x received (%zu > %zu)\n",
|
"%s: malformed response 0x%02x received (%zu > %zu)\n",
|
||||||
connection->name, header->type,
|
connection->name, header->type,
|
||||||
size, message_size);
|
size, message_size);
|
||||||
@ -918,7 +918,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
|
|||||||
if (gb_operation_short_response_allowed(operation)) {
|
if (gb_operation_short_response_allowed(operation)) {
|
||||||
message->payload_size = size - sizeof(*header);
|
message->payload_size = size - sizeof(*header);
|
||||||
} else {
|
} else {
|
||||||
dev_err(&connection->hd->dev,
|
dev_err_ratelimited(&connection->hd->dev,
|
||||||
"%s: short response 0x%02x received (%zu < %zu)\n",
|
"%s: short response 0x%02x received (%zu < %zu)\n",
|
||||||
connection->name, header->type,
|
connection->name, header->type,
|
||||||
size, message_size);
|
size, message_size);
|
||||||
@ -956,13 +956,14 @@ void gb_connection_recv(struct gb_connection *connection,
|
|||||||
if ((connection->state != GB_CONNECTION_STATE_ENABLED &&
|
if ((connection->state != GB_CONNECTION_STATE_ENABLED &&
|
||||||
connection->state != GB_CONNECTION_STATE_ENABLED_TX) ||
|
connection->state != GB_CONNECTION_STATE_ENABLED_TX) ||
|
||||||
gb_connection_is_offloaded(connection)) {
|
gb_connection_is_offloaded(connection)) {
|
||||||
dev_warn(dev, "%s: dropping %zu received bytes\n",
|
dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n",
|
||||||
connection->name, size);
|
connection->name, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size < sizeof(header)) {
|
if (size < sizeof(header)) {
|
||||||
dev_err(dev, "%s: short message received\n", connection->name);
|
dev_err_ratelimited(dev, "%s: short message received\n",
|
||||||
|
connection->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -970,10 +971,11 @@ void gb_connection_recv(struct gb_connection *connection,
|
|||||||
memcpy(&header, data, sizeof(header));
|
memcpy(&header, data, sizeof(header));
|
||||||
msg_size = le16_to_cpu(header.size);
|
msg_size = le16_to_cpu(header.size);
|
||||||
if (size < msg_size) {
|
if (size < msg_size) {
|
||||||
dev_err(dev,
|
dev_err_ratelimited(dev,
|
||||||
"%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n",
|
"%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n",
|
||||||
connection->name, le16_to_cpu(header.operation_id),
|
connection->name,
|
||||||
header.type, size, msg_size);
|
le16_to_cpu(header.operation_id),
|
||||||
|
header.type, size, msg_size);
|
||||||
return; /* XXX Should still complete operation */
|
return; /* XXX Should still complete operation */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user