aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <dan.carpenter@oracle.com>2016-08-10 19:27:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-10 19:40:56 -0400
commit73984137d32bb6e48646daea60ebe1457a01a061 (patch)
treea4bbaabb47be7b18460f32d887f99048b2aed327
parenta0cba2179ea4c1820fce2ee046b6ed90ecc56196 (diff)
rapidio: dereferencing an error pointer
Original patch: https://lkml.org/lkml/2016/8/4/32 If riocm_ch_alloc() fails then we end up dereferencing the error pointer. The problem is that we're not unwinding in the reverse order from how we allocate things so it gets confusing. I've changed this around so now "ch" is NULL when we are done with it after we call riocm_put_channel(). That way we can check if it's NULL and avoid calling riocm_put_channel() on it twice. I renamed err_nodev to err_put_new_ch so that it better reflects what the goto does. Then because we had flipping things around, it means we don't neeed to initialize the pointers to NULL and we can remove an if statement and pull things in an indent level. Link: http://lkml.kernel.org/r/20160805152406.20713-1-alexandre.bounine@idt.com Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Andre van Herk <andre.van.herk@prodrive-technologies.com> Cc: Barry Wood <barry.wood@idt.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/rapidio/rio_cm.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c
index cecc15a880de..3fa17ac8df54 100644
--- a/drivers/rapidio/rio_cm.c
+++ b/drivers/rapidio/rio_cm.c
@@ -1080,8 +1080,8 @@ static int riocm_send_ack(struct rio_channel *ch)
1080static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id, 1080static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
1081 long timeout) 1081 long timeout)
1082{ 1082{
1083 struct rio_channel *ch = NULL; 1083 struct rio_channel *ch;
1084 struct rio_channel *new_ch = NULL; 1084 struct rio_channel *new_ch;
1085 struct conn_req *req; 1085 struct conn_req *req;
1086 struct cm_peer *peer; 1086 struct cm_peer *peer;
1087 int found = 0; 1087 int found = 0;
@@ -1155,6 +1155,7 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
1155 1155
1156 spin_unlock_bh(&ch->lock); 1156 spin_unlock_bh(&ch->lock);
1157 riocm_put_channel(ch); 1157 riocm_put_channel(ch);
1158 ch = NULL;
1158 kfree(req); 1159 kfree(req);
1159 1160
1160 down_read(&rdev_sem); 1161 down_read(&rdev_sem);
@@ -1172,7 +1173,7 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
1172 if (!found) { 1173 if (!found) {
1173 /* If peer device object not found, simply ignore the request */ 1174 /* If peer device object not found, simply ignore the request */
1174 err = -ENODEV; 1175 err = -ENODEV;
1175 goto err_nodev; 1176 goto err_put_new_ch;
1176 } 1177 }
1177 1178
1178 new_ch->rdev = peer->rdev; 1179 new_ch->rdev = peer->rdev;
@@ -1184,15 +1185,16 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
1184 1185
1185 *new_ch_id = new_ch->id; 1186 *new_ch_id = new_ch->id;
1186 return new_ch; 1187 return new_ch;
1188
1189err_put_new_ch:
1190 spin_lock_bh(&idr_lock);
1191 idr_remove(&ch_idr, new_ch->id);
1192 spin_unlock_bh(&idr_lock);
1193 riocm_put_channel(new_ch);
1194
1187err_put: 1195err_put:
1188 riocm_put_channel(ch); 1196 if (ch)
1189err_nodev: 1197 riocm_put_channel(ch);
1190 if (new_ch) {
1191 spin_lock_bh(&idr_lock);
1192 idr_remove(&ch_idr, new_ch->id);
1193 spin_unlock_bh(&idr_lock);
1194 riocm_put_channel(new_ch);
1195 }
1196 *new_ch_id = 0; 1198 *new_ch_id = 0;
1197 return ERR_PTR(err); 1199 return ERR_PTR(err);
1198} 1200}