summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/operation.c
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2015-07-14 15:43:23 +0200
committerGreg Kroah-Hartman <gregkh@google.com>2015-07-15 12:39:13 -0700
commitfffc151381473384629d78cb89b7f7bbb9dc53b0 (patch)
treeff872a539ca01725fb5eed5c368a214c3ad213b7 /drivers/staging/greybus/operation.c
parenta5192032a2a9475c837c2b4b6fc3df02d617c7b0 (diff)
greybus: operation: fix another cancellation use-after-free
An incoming operation could already be scheduled even if gb_operation_result_set succeeds as its initial status is -EINPROGRESS. Avoid potential use-after-free by never dropping the reference count for incoming operations as part of cancellation. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/operation.c')
-rw-r--r--drivers/staging/greybus/operation.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/staging/greybus/operation.c b/drivers/staging/greybus/operation.c
index b78c55fac8cc..41aec7647b2b 100644
--- a/drivers/staging/greybus/operation.c
+++ b/drivers/staging/greybus/operation.c
@@ -853,12 +853,17 @@ void gb_connection_recv(struct gb_connection *connection,
*/
void gb_operation_cancel(struct gb_operation *operation, int errno)
{
- if (gb_operation_result_set(operation, errno)) {
- gb_message_cancel(operation->request);
- gb_operation_put(operation);
- } else if (gb_operation_is_incoming(operation)) {
- if (!gb_operation_is_unidirectional(operation))
+ if (gb_operation_is_incoming(operation)) {
+ /* Cancel response if it has been allocated */
+ if (!gb_operation_result_set(operation, errno) &&
+ !gb_operation_is_unidirectional(operation)) {
gb_message_cancel(operation->response);
+ }
+ } else {
+ if (gb_operation_result_set(operation, errno)) {
+ gb_message_cancel(operation->request);
+ gb_operation_put(operation);
+ }
}
}
EXPORT_SYMBOL_GPL(gb_operation_cancel);