diff mbox series

net: 9p: Fix possible null-pointer dereferences in p9_cm_event_handler()

Message ID 20190724103948.5834-1-baijiaju1990@gmail.com
State Changes Requested
Delegated to: David Miller
Headers show
Series net: 9p: Fix possible null-pointer dereferences in p9_cm_event_handler() | expand

Commit Message

Jia-Ju Bai July 24, 2019, 10:39 a.m. UTC
In p9_cm_event_handler(), there is an if statement on 260 to check
whether rdma is NULL, which indicates that rdma can be NULL.
If so, using rdma->xxx may cause a possible null-pointer dereference.

To fix these bugs, rdma is checked before being used.

These bugs are found by a static analysis tool STCheck written by us.

Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
 net/9p/trans_rdma.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

Comments

Dominique Martinet July 24, 2019, 12:55 p.m. UTC | #1
Jia-Ju Bai wrote on Wed, Jul 24, 2019:
> In p9_cm_event_handler(), there is an if statement on 260 to check
> whether rdma is NULL, which indicates that rdma can be NULL.
> If so, using rdma->xxx may cause a possible null-pointer dereference.

The final dereference (complete(&rdma->cm_done) line 285) has been here
from the start, so we would have seen crashes by now if rdma could be
null at this point.

Let's do it the other way around and remove the useless "if (rdma)" that
has been here from day 1 instead ; I basically did the same with
c->status a few months ago (from a coverity report)...


That said, please note that 'rdma checked for null in this event->event
== RDMA_CM_EVENT_DISCONNECTED branch' does not mean rdma can be null in
other branches.
static analysis does not say anything more than the final complete()
should also have a check if the previous one has, but nothing about the
other cases in the switch.


Thanks,
Dominique Martinet Sept. 3, 2019, 10:55 a.m. UTC | #2
Jia-Ju,

Dominique Martinet wrote on Wed, Jul 24, 2019:
> Jia-Ju Bai wrote on Wed, Jul 24, 2019:
> > In p9_cm_event_handler(), there is an if statement on 260 to check
> > whether rdma is NULL, which indicates that rdma can be NULL.
> > If so, using rdma->xxx may cause a possible null-pointer dereference.
> 
> The final dereference (complete(&rdma->cm_done) line 285) has been here
> from the start, so we would have seen crashes by now if rdma could be
> null at this point.
> 
> Let's do it the other way around and remove the useless "if (rdma)" that
> has been here from day 1 instead ; I basically did the same with
> c->status a few months ago (from a coverity report)...

Did you get anywhere with this, or should I submit a new patch myself ?
In the later case I'll tag this as Reported-by you

Thanks,
diff mbox series

Patch

diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index bac8dad5dd69..eba3c5fc2731 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -242,18 +242,24 @@  p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
 	struct p9_trans_rdma *rdma = c->trans;
 	switch (event->event) {
 	case RDMA_CM_EVENT_ADDR_RESOLVED:
-		BUG_ON(rdma->state != P9_RDMA_INIT);
-		rdma->state = P9_RDMA_ADDR_RESOLVED;
+		if (rdma) {
+			BUG_ON(rdma->state != P9_RDMA_INIT);
+			rdma->state = P9_RDMA_ADDR_RESOLVED;
+		}
 		break;
 
 	case RDMA_CM_EVENT_ROUTE_RESOLVED:
-		BUG_ON(rdma->state != P9_RDMA_ADDR_RESOLVED);
-		rdma->state = P9_RDMA_ROUTE_RESOLVED;
+		if (rdma) {
+			BUG_ON(rdma->state != P9_RDMA_ADDR_RESOLVED);
+			rdma->state = P9_RDMA_ROUTE_RESOLVED;
+		}
 		break;
 
 	case RDMA_CM_EVENT_ESTABLISHED:
-		BUG_ON(rdma->state != P9_RDMA_ROUTE_RESOLVED);
-		rdma->state = P9_RDMA_CONNECTED;
+		if (rdma) {
+			BUG_ON(rdma->state != P9_RDMA_ROUTE_RESOLVED);
+			rdma->state = P9_RDMA_CONNECTED;
+		}
 		break;
 
 	case RDMA_CM_EVENT_DISCONNECTED:
@@ -277,12 +283,14 @@  p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
 	case RDMA_CM_EVENT_ADDR_ERROR:
 	case RDMA_CM_EVENT_UNREACHABLE:
 		c->status = Disconnected;
-		rdma_disconnect(rdma->cm_id);
+		if (rdma)
+			rdma_disconnect(rdma->cm_id);
 		break;
 	default:
 		BUG();
 	}
-	complete(&rdma->cm_done);
+	if (rdma)
+		complete(&rdma->cm_done);
 	return 0;
 }