aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-05-21 09:48:05 -0400
committerDavid Howells <dhowells@redhat.com>2014-05-21 09:48:05 -0400
commit6c67c7c38cf32c2a9cbccb6b21aadf61a85fbfb4 (patch)
treed7e2b13f2ff270892babb8bc01799d71aded154c /fs
parent60b5f90d0fac7585f1a43ccdad06787b97eda0ab (diff)
AFS: Fix cache manager service handlers
Fix the cache manager RPC service handlers. The afs_send_empty_reply() and afs_send_simple_reply() functions: (a) Kill the call and free up the buffers associated with it if they fail. (b) Return with call intact if it they succeed. However, none of the callers actually check the result or clean up if successful - and may use the now non-existent data if it fails. This was detected by Dan Carpenter using a static checker: The patch 08e0e7c82eea: "[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC." from Apr 26, 2007, leads to the following static checker warning: "fs/afs/cmservice.c:155 SRXAFSCB_CallBack() warn: 'call' was already freed." Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/cmservice.c19
-rw-r--r--fs/afs/rxrpc.c43
2 files changed, 40 insertions, 22 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 1c8c6cc6de30..4b0eff6da674 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -130,6 +130,15 @@ static void afs_cm_destructor(struct afs_call *call)
130{ 130{
131 _enter(""); 131 _enter("");
132 132
133 /* Break the callbacks here so that we do it after the final ACK is
134 * received. The step number here must match the final number in
135 * afs_deliver_cb_callback().
136 */
137 if (call->unmarshall == 6) {
138 ASSERT(call->server && call->count && call->request);
139 afs_break_callbacks(call->server, call->count, call->request);
140 }
141
133 afs_put_server(call->server); 142 afs_put_server(call->server);
134 call->server = NULL; 143 call->server = NULL;
135 kfree(call->buffer); 144 kfree(call->buffer);
@@ -272,6 +281,16 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
272 _debug("trailer"); 281 _debug("trailer");
273 if (skb->len != 0) 282 if (skb->len != 0)
274 return -EBADMSG; 283 return -EBADMSG;
284
285 /* Record that the message was unmarshalled successfully so
286 * that the call destructor can know do the callback breaking
287 * work, even if the final ACK isn't received.
288 *
289 * If the step number changes, then afs_cm_destructor() must be
290 * updated also.
291 */
292 call->unmarshall++;
293 case 6:
275 break; 294 break;
276 } 295 }
277 296
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index ef943df73b8c..9226a6674d7f 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -184,6 +184,19 @@ static void afs_free_call(struct afs_call *call)
184} 184}
185 185
186/* 186/*
187 * End a call
188 */
189static void afs_end_call(struct afs_call *call)
190{
191 if (call->rxcall) {
192 rxrpc_kernel_end_call(call->rxcall);
193 call->rxcall = NULL;
194 }
195 call->type->destructor(call);
196 afs_free_call(call);
197}
198
199/*
187 * allocate a call with flat request and reply buffers 200 * allocate a call with flat request and reply buffers
188 */ 201 */
189struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type, 202struct afs_call *afs_alloc_flat_call(const struct afs_call_type *type,
@@ -383,11 +396,8 @@ error_do_abort:
383 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT); 396 rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
384 while ((skb = skb_dequeue(&call->rx_queue))) 397 while ((skb = skb_dequeue(&call->rx_queue)))
385 afs_free_skb(skb); 398 afs_free_skb(skb);
386 rxrpc_kernel_end_call(rxcall);
387 call->rxcall = NULL;
388error_kill_call: 399error_kill_call:
389 call->type->destructor(call); 400 afs_end_call(call);
390 afs_free_call(call);
391 _leave(" = %d", ret); 401 _leave(" = %d", ret);
392 return ret; 402 return ret;
393} 403}
@@ -509,12 +519,8 @@ static void afs_deliver_to_call(struct afs_call *call)
509 if (call->state >= AFS_CALL_COMPLETE) { 519 if (call->state >= AFS_CALL_COMPLETE) {
510 while ((skb = skb_dequeue(&call->rx_queue))) 520 while ((skb = skb_dequeue(&call->rx_queue)))
511 afs_free_skb(skb); 521 afs_free_skb(skb);
512 if (call->incoming) { 522 if (call->incoming)
513 rxrpc_kernel_end_call(call->rxcall); 523 afs_end_call(call);
514 call->rxcall = NULL;
515 call->type->destructor(call);
516 afs_free_call(call);
517 }
518 } 524 }
519 525
520 _leave(""); 526 _leave("");
@@ -564,10 +570,7 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
564 } 570 }
565 571
566 _debug("call complete"); 572 _debug("call complete");
567 rxrpc_kernel_end_call(call->rxcall); 573 afs_end_call(call);
568 call->rxcall = NULL;
569 call->type->destructor(call);
570 afs_free_call(call);
571 _leave(" = %d", ret); 574 _leave(" = %d", ret);
572 return ret; 575 return ret;
573} 576}
@@ -790,10 +793,7 @@ void afs_send_empty_reply(struct afs_call *call)
790 _debug("oom"); 793 _debug("oom");
791 rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); 794 rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
792 default: 795 default:
793 rxrpc_kernel_end_call(call->rxcall); 796 afs_end_call(call);
794 call->rxcall = NULL;
795 call->type->destructor(call);
796 afs_free_call(call);
797 _leave(" [error]"); 797 _leave(" [error]");
798 return; 798 return;
799 } 799 }
@@ -823,17 +823,16 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
823 call->state = AFS_CALL_AWAIT_ACK; 823 call->state = AFS_CALL_AWAIT_ACK;
824 n = rxrpc_kernel_send_data(call->rxcall, &msg, len); 824 n = rxrpc_kernel_send_data(call->rxcall, &msg, len);
825 if (n >= 0) { 825 if (n >= 0) {
826 /* Success */
826 _leave(" [replied]"); 827 _leave(" [replied]");
827 return; 828 return;
828 } 829 }
830
829 if (n == -ENOMEM) { 831 if (n == -ENOMEM) {
830 _debug("oom"); 832 _debug("oom");
831 rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT); 833 rxrpc_kernel_abort_call(call->rxcall, RX_USER_ABORT);
832 } 834 }
833 rxrpc_kernel_end_call(call->rxcall); 835 afs_end_call(call);
834 call->rxcall = NULL;
835 call->type->destructor(call);
836 afs_free_call(call);
837 _leave(" [error]"); 836 _leave(" [error]");
838} 837}
839 838